Pular para conteúdo
Postman

Webhooks

Webhooks permitem receber notificações em tempo real sobre eventos da plataforma. A MediQuo pode configurar as inscrições diretamente para o parceiro. Se preferir, utilize os endpoints abaixo para gerenciar as inscrições de forma autônoma.


Eventos Disponíveis

Evento Descrição
LICENCE_CREATED_SUCCESS Licença criada e processada com sucesso
LICENCE_CREATED_FAILED Falha na criação ou processamento da licença

GET /webhooks/subscriptions

Retorna a lista paginada de inscrições.

Parâmetros da Query

Nome Tipo Obrigatório Descrição
page integer não Número da página (padrão: 0)
size integer não Itens por página (padrão: 20)
sort string não Ordenação (ex: name,asc)
index string não Filtro de busca por nome

Cabeçalhos

Header Valor
Authorization Bearer {token}
Accept application/hal+json

Exemplo de Requisição

Bash
curl -X GET "https://api-portal.mediquo.com.br/webhooks/subscriptions?page=0&size=20" \
  -H "Authorization: Bearer {seu_token}" \
  -H "Accept: application/hal+json"

Respostas

Código Descrição
200 Lista paginada de inscrições
401 Token inválido ou expirado
403 Sem permissão

GET /webhooks/subscriptions/active

Retorna a lista paginada de inscrições filtrada pelo status ativo.

Parâmetros da Query

Nome Tipo Obrigatório Descrição
active boolean não Filtro por status ativo/inativo
page integer não Número da página (padrão: 0)
size integer não Itens por página (padrão: 20)

Cabeçalhos

Header Valor
Authorization Bearer {token}
Accept application/hal+json

Exemplo de Requisição

Bash
curl -X GET "https://api-portal.mediquo.com.br/webhooks/subscriptions/active?active=true&page=0&size=20" \
  -H "Authorization: Bearer {seu_token}" \
  -H "Accept: application/hal+json"

Respostas

Código Descrição
200 Lista paginada de inscrições filtrada
401 Token inválido ou expirado
403 Sem permissão

GET /webhooks/subscriptions/{id}

Retorna os dados de uma inscrição específica.

Parâmetros do Path

Nome Tipo Obrigatório Descrição
id integer sim ID da inscrição

Cabeçalhos

Header Valor
Authorization Bearer {token}
Accept application/hal+json

Exemplo de Requisição

Bash
curl -X GET https://api-portal.mediquo.com.br/webhooks/subscriptions/1 \
  -H "Authorization: Bearer {seu_token}" \
  -H "Accept: application/hal+json"

Resposta de Sucesso: 200 OK

JSON
{
  "id": 1,
  "tenant": "partner-tenant",
  "active": true,
  "name": "Minha Integração",
  "url": "https://meu-dominio.com/webhook/licencas",
  "description": "Receber eventos de licenças",
  "events": ["LICENCE_CREATED_SUCCESS", "LICENCE_CREATED_FAILED"],
  "createdAt": "2025-01-27T10:00:00.000Z",
  "updatedAt": "2025-01-27T10:00:00.000Z"
}

Respostas de Erro

Código Descrição
401 Token inválido ou expirado
403 Sem permissão
404 Inscrição não encontrada

POST /webhooks/subscriptions

Cria uma nova inscrição de webhook.

Cabeçalhos

Header Valor
Authorization Bearer {token}
Content-Type application/json
Accept application/hal+json

Corpo da Requisição

Campo Tipo Obrigatório Descrição
name string sim Nome identificador da inscrição
url string sim URL HTTPS do endpoint receptor
events array sim Lista de eventos para inscrição
description string não Descrição opcional
active boolean não Status da inscrição (padrão: true)
headerName string não Nome do header customizado enviado em cada entrega
headerValue string não Valor do header customizado

Os campos headerName e headerValue permitem configurar um header de autenticação que será incluído em todas as requisições enviadas ao seu endpoint (ex: X-Webhook-Secret).

A URL do endpoint receptor deve obrigatoriamente usar protocolo HTTPS.

Exemplo de Requisição

Bash
curl -X POST https://api-portal.mediquo.com.br/webhooks/subscriptions \
  -H "Authorization: Bearer {seu_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Minha Integração",
    "url": "https://meu-dominio.com/webhook/licencas",
    "description": "Receber eventos de licenças",
    "events": ["LICENCE_CREATED_SUCCESS", "LICENCE_CREATED_FAILED"],
    "active": true,
    "headerName": "X-Webhook-Secret",
    "headerValue": "meu-segredo"
  }'

Resposta de Sucesso: 200 OK

Retorna o objeto da inscrição criada com seu id.

Respostas de Erro

Código Descrição
400 Campos obrigatórios ausentes ou inválidos
401 Token inválido ou expirado
403 Sem permissão

PUT /webhooks/subscriptions/{id}

Atualiza os dados de uma inscrição.

Parâmetros do Path

Nome Tipo Obrigatório Descrição
id integer sim ID da inscrição

Cabeçalhos

Header Valor
Authorization Bearer {token}
Content-Type application/json
Accept application/hal+json

Corpo da Requisição

Campo Tipo Obrigatório Descrição
name string sim Nome identificador da inscrição
url string sim URL HTTPS do endpoint receptor
events array sim Lista de eventos para inscrição
description string não Descrição opcional
active boolean não Status da inscrição
headerName string não Nome do header customizado
headerValue string não Valor do header customizado

Exemplo de Requisição

Bash
curl -X PUT https://api-portal.mediquo.com.br/webhooks/subscriptions/1 \
  -H "Authorization: Bearer {seu_token}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Minha Integração Atualizada",
    "url": "https://meu-dominio.com/webhook/licencas",
    "events": ["LICENCE_CREATED_SUCCESS"]
  }'

Respostas

Código Descrição
200 Inscrição atualizada. Retorna o objeto completo
400 Requisição inválida
401 Token inválido ou expirado
403 Sem permissão
404 Inscrição não encontrada

DELETE /webhooks/subscriptions/{id}

Remove uma inscrição de webhook.

Parâmetros do Path

Nome Tipo Obrigatório Descrição
id integer sim ID da inscrição

Cabeçalhos

Header Valor
Authorization Bearer {token}
Accept application/hal+json

Exemplo de Requisição

Bash
curl -X DELETE https://api-portal.mediquo.com.br/webhooks/subscriptions/1 \
  -H "Authorization: Bearer {seu_token}"

Respostas

Código Descrição
200 Inscrição removida
401 Token inválido ou expirado
403 Sem permissão
404 Inscrição não encontrada

GET /webhooks/subscriptions/{id}/deliveries

Retorna o histórico de entregas de uma inscrição.

Parâmetros do Path

Nome Tipo Obrigatório Descrição
id integer sim ID da inscrição

Parâmetros da Query

Nome Tipo Obrigatório Descrição
page integer não Número da página (padrão: 0)
size integer não Itens por página (padrão: 20)

Cabeçalhos

Header Valor
Authorization Bearer {token}
Accept application/hal+json

Exemplo de Requisição

Bash
curl -X GET "https://api-portal.mediquo.com.br/webhooks/subscriptions/1/deliveries?page=0&size=20" \
  -H "Authorization: Bearer {seu_token}" \
  -H "Accept: application/hal+json"

Resposta de Sucesso: 200 OK

JSON
{
  "totalPages": 1,
  "totalElements": 2,
  "content": [
    {
      "id": 1,
      "subscriptionId": 1,
      "subscriptionName": "Minha Integração",
      "eventType": "LICENCE_CREATED_SUCCESS",
      "status": "SUCCESS",
      "httpStatusCode": 200,
      "errorMessage": null,
      "sentAt": "2025-01-27T10:00:00.000Z",
      "createdAt": "2025-01-27T10:00:00.000Z"
    }
  ]
}

Campos do Histórico

Campo Tipo Descrição
subscriptionId integer ID da inscrição
subscriptionName string Nome da inscrição
eventType string Tipo do evento entregue
status string SUCCESS ou FAILED
httpStatusCode integer Código HTTP retornado pelo seu endpoint
errorMessage string Mensagem de erro (quando FAILED)
sentAt string Data/hora do envio

Respostas de Erro

Código Descrição
401 Token inválido ou expirado
403 Sem permissão
404 Inscrição não encontrada

Formato do Payload

O sistema envia uma requisição POST com Content-Type: application/json para a URL configurada em cada evento.

Payload: LICENCE_CREATED_SUCCESS

JSON
{
  "eventType": "LICENCE_CREATED_SUCCESS",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "tenant": "partner-tenant-id",
  "licence": {
    "code": "LIC-2025-001",
    "clientId": 1,
    "planId": 1,
    "name": "Maria Silva",
    "email": "maria@email.com",
    "phoneNumber": "11999999999",
    "status": "CREATED",
    "maxRedemptions": 10,
    "pricing": 49.90
  },
  "error": null
}

Payload: LICENCE_CREATED_FAILED

JSON
{
  "eventType": "LICENCE_CREATED_FAILED",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "tenant": "partner-tenant-id",
  "licence": null,
  "error": {
    "message": "Client not found for tenant",
    "type": "ResourceNotFoundException"
  }
}

Requerimentos do Endpoint Receptor

Seu endpoint webhook deve:

  • Aceitar requisições HTTP POST com Content-Type: application/json
  • Responder com código 2xx para confirmar o recebimento
  • Responder em até 30 segundos. Entregas que ultrapassem esse limite são marcadas como FAILED
  • Ser idempotente. O mesmo evento pode ser entregue mais de uma vez; use a combinação de eventType + timestamp + licence.code para detectar duplicatas
  • Usar HTTPS obrigatoriamente

O sistema não reenvia automaticamente entregas com falha. Monitore o histórico via GET /webhooks/subscriptions/{id}/deliveries e acione reenvios manualmente se necessário.


Garantias de Entrega

Política de Retry

O sistema não reenvia automaticamente entregas que falharam caso seu endpoint retorne código não 2xx, ultrapasse o tempo limite ou esteja inacessível. A entrega é marcada como FAILED no histórico.

Ordem de Entrega

Webhooks são entregues de forma assíncrona. A ordem das entregas não é garantida, especialmente em momentos de alta carga.

Idempotência

Seu endpoint deve tratar eventos duplicados de forma idempotente. Use a combinação de eventType + timestamp + licence.code (para eventos de sucesso) para detectar e ignorar duplicatas.


Considerações de Segurança

HTTPS Obrigatório

Seu endpoint de webhook deve usar HTTPS para garantir a transmissão segura dos dados.

Whitelist de IPs

A lista de endereços IP de onde as requisições de webhook serão originadas é fornecida durante o processo de integração.

Validação da Requisição

Sempre valide as requisições de webhook recebidas:

  • Verifique se a estrutura da requisição corresponde ao payload esperado
  • Valide se o tenant informado corresponde ao(s) tenant(s) esperados
  • Verifique o timestamp para prevenir ataques de replay
  • Use headerName / headerValue para autenticar entregas no seu endpoint

Exemplos de Implementação

Node.js / Express

JavaScript
app.post('/webhook/licence-events', (req, res) => {
  const { eventType, timestamp, tenant, licence, error } = req.body;

  if (eventType === 'LICENCE_CREATED_SUCCESS') {
    console.log(`Licença ${licence.code} criada com sucesso`);
  } else if (eventType === 'LICENCE_CREATED_FAILED') {
    console.log(`Falha na criação: ${error.message}`);
  }

  res.status(200).json({ received: true });
});

Python / Flask

Python
@app.route('/webhook/licence-events', methods=['POST'])
def handle_webhook():
    data = request.json
    event_type = data['eventType']

    if event_type == 'LICENCE_CREATED_SUCCESS':
        print(f"Licença {data['licence']['code']} criada com sucesso")
    elif event_type == 'LICENCE_CREATED_FAILED':
        print(f"Falha na criação: {data['error']['message']}")

    return jsonify({'received': True}), 200

Java / Spring Boot

Java
@PostMapping("/webhook/licence-events")
public ResponseEntity<Map<String, Boolean>> handleWebhook(@RequestBody WebhookPayloadDTO payload) {
    if (payload.getEventType() == WebhookEventType.LICENCE_CREATED_SUCCESS) {
        logger.info("Licença {} criada com sucesso", payload.getLicence().getCode());
    } else if (payload.getEventType() == WebhookEventType.LICENCE_CREATED_FAILED) {
        logger.error("Falha na criação: {}", payload.getError().getMessage());
    }
    return ResponseEntity.ok(Map.of("received", true));
}

Monitoramento e Problemas Comuns

Webhook não recebido

  • Verifique se a inscrição está active: true
  • Confirme que os tipos de evento corretos estão inscritos
  • Garanta que seu endpoint esteja acessível a partir dos nossos servidores
  • Revise regras de firewall e configuração de rede

Entrega marcada como FAILED

  • Verifique os logs do seu endpoint em busca de erros
  • Confirme que seu endpoint retorna código 2xx
  • Garanta que o tempo de resposta esteja abaixo de 30 segundos
  • Verifique o campo errorMessage no histórico de entregas

Recebimento de eventos duplicados

Esse comportamento é esperado. Implemente processamento idempotente usando licence.code + timestamp para detectar duplicatas.


Boas Práticas

  1. Responda rapidamente: Confirme o recebimento imediatamente (200 OK) e processe em segundo plano de forma assíncrona.
  2. Registre tudo: Registre todos os webhooks recebidos para auditoria e depuração.
  3. Trate falhas de forma resiliente: Seu sistema deve continuar operando mesmo se o processamento de webhooks falhar.
  4. Monitore o status de entrega: Verifique regularmente o histórico de entregas para identificar problemas cedo.
  5. Use filas: Considere usar uma fila de mensagens para processar webhooks de forma assíncrona.