Pular para o conteúdo

Os webhooks de notificação são a forma recomendada de acompanhar as mudanças de estado do pagamento no Payments Direct. No entanto, se a sua integração não puder receber webhooks de entrada (por exemplo, por restrições de rede ou regras de firewall que impeçam uma URL de callback HTTPS pública), você pode fazer polling na API para detectar atualizações de pagamento.

Este tópico descreve quando e como fazer polling de forma eficaz e aborda dois padrões complementares:

  • Polling de pagamento único: acompanha o estado de um pagamento específico pelo paymentId
  • Polling de busca em lote: detecta todos os pagamentos atualizados desde um determinado timestamp
Combine polling com webhooks sempre que possível

Polling e webhooks não são mutuamente exclusivos. Mesmo quando os webhooks são o seu mecanismo principal de notificação, um polling periódico de busca em lote é uma rede de segurança útil para capturar transições de estado que o seu handler de webhook possa ter perdido por falhas de entrega ou entrega fora de ordem.


Quando usar cada padrão

PadrãoIndicado para
Polling de pagamento únicoAcompanhar o resultado de um pagamento específico que você acabou de criar
Polling de busca em loteConciliar todos os pagamentos atualizados desde a sua última verificação; capturar notificações de webhook perdidas

Polling de pagamento único

Use GET /v3/payments/{paymentId} para verificar o estado atual de um pagamento específico.

Exemplo: fazer polling de um pagamento por ID

curl -X GET "https://{base-url}/v3/payments/5ce2c433-a96d-48d0-8857-02637a60abf4" \
  -H "Authorization: Bearer <access_token>"

Resposta (200 OK)

{
  "paymentId": "5ce2c433-a96d-48d0-8857-02637a60abf4",
  "paymentState": "TRANSFERRING",
  "initiatedAt": "2025-10-01T14:00:00.000Z",
  "updatedAt": "2025-10-01T14:00:45.321Z",
  "expiresAt": "2025-11-30T14:00:00.000Z"
}

Repita a requisição em intervalos fixos até que o pagamento chegue a um estado terminal: COMPLETED, FAILED, DECLINED ou RETURNED.

Use updatedAt, não a ordem de chegada

Se estiver comparando várias respostas, use updatedAt para determinar o estado mais recente. Não confie na ordem em que as respostas chegam, porque as condições de rede podem fazer com que elas cheguem fora de sequência.

Orientações sobre o intervalo de polling

  • Não faça polling com frequência maior que 30 segundos para pagamentos ativos.
  • Para pagamentos nos estados iniciais INITIATED ou VALIDATING, um intervalo de 30 a 60 segundos é adequado.
  • Quando um pagamento chega a TRANSFERRING, o tempo até a conclusão depende do corredor e do payment rail. Ajuste o seu intervalo para atender aos seus requisitos de SLA.
  • Pare o polling quando o pagamento chegar a um estado terminal (COMPLETED, FAILED, DECLINED, RETURNED).

Tratamento de erros no polling de pagamento único

Status HTTPAção
200 OKLeia paymentState e continue o polling se não for terminal
404 Not FoundO ID do pagamento é inválido ou não pertence à sua conta
429 Too Many RequestsAplique espera exponencial antes de tentar novamente (consulte Espera exponencial)
500 / 503Repita com espera exponencial; acione um alerta se a condição persistir

Polling de busca em lote

Use POST /v3/payments/filter (Search payments) para recuperar todos os pagamentos cujo estado foi atualizado pela última vez dentro de um intervalo de tempo. Essa é a abordagem recomendada para conciliação e para integrações que processam grandes volumes de pagamentos.

A combinação de filtros principal:

  • filterRangeType: PAYMENT_STATUS_LAST_UPDATED: filtra pelo momento em que um pagamento mudou de estado pela última vez
  • afterTimestamp: o timestamp do seu último polling bem-sucedido (o seu "cursor")
  • beforeTimestamp: o horário atual (opcional, mas recomendado para evitar processar atualizações em andamento)

Etapa 1: Requisição inicial

curl -X POST "https://{base-url}/v3/payments/filter" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {
      "filterRangeType": "PAYMENT_STATUS_LAST_UPDATED",
      "afterTimestamp": "2025-10-01T14:00:00Z",
      "beforeTimestamp": "2025-10-01T14:05:00Z"
    },
    "page": {
      "size": 100
    }
  }'

Resposta (200 OK)

{
  "data": [
    {
      "paymentId": "5ce2c433-a96d-48d0-8857-02637a60abf4",
      "paymentState": "COMPLETED",
      "updatedAt": "2025-10-01T14:03:12.000Z"
    },
    {
      "paymentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "paymentState": "FAILED",
      "updatedAt": "2025-10-01T14:04:55.000Z"
    }
  ],
  "filter": { "filterRangeType": "PAYMENT_STATUS_LAST_UPDATED", "afterTimestamp": "2025-10-01T14:00:00Z", "beforeTimestamp": "2025-10-01T14:05:00Z" },
  "page": {
    "size": 100,
    "lastPageToken": "eyJrZXkiOiJhMWIyYzNkNCJ9"
  }
}

Etapa 2: Paginar os resultados

Se a resposta incluir um page.lastPageToken, há mais resultados. Inclua-o na próxima requisição para recuperar a página seguinte.

curl -X POST "https://{base-url}/v3/payments/filter" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "filter": {
      "filterRangeType": "PAYMENT_STATUS_LAST_UPDATED",
      "afterTimestamp": "2025-10-01T14:00:00Z",
      "beforeTimestamp": "2025-10-01T14:05:00Z"
    },
    "page": {
      "size": 100,
      "lastPageToken": "eyJrZXkiOiJhMWIyYzNkNCJ9"
    }
  }'

Continue paginando até que uma resposta não retorne lastPageToken. Nesse ponto, todos os resultados desta janela de tempo foram recuperados.

Etapa 3: Avançar o cursor

Depois de esgotar todas as páginas de uma janela de tempo, registre o beforeTimestamp daquela requisição como o novo afterTimestamp do próximo ciclo de polling.

afterTimestamp (next poll) = beforeTimestamp (this poll)

Isso cria um cursor estável e sem sobreposição, que evita que você perca transições de estado entre os pollings.

Use um beforeTimestamp fixo por ciclo de polling

Defina beforeTimestamp como o horário atual antes de começar a paginar e mantenha-o constante em todas as páginas do mesmo ciclo de polling. Se você usar um timestamp móvel entre as páginas, corre o risco de perder atualizações ocorridas enquanto paginava.

Intervalo do polling de busca em lote

  • Execute o seu polling de busca em lote a cada 1 a 5 minutos, conforme o seu volume e o SLA de conciliação.
  • Em integrações de alto volume, um intervalo de 1 minuto com page.size: 100 oferece um bom equilíbrio entre agilidade e eficiência da API.
  • Se um ciclo de polling retornar zero resultados, aumente um pouco o intervalo (por exemplo, dobre-o, até um máximo de 10 minutos) para reduzir carga desnecessária.

Tratamento de estados terminais

Quando um pagamento chega a um estado terminal (COMPLETED, FAILED, DECLINED ou RETURNED), pare o polling daquele pagamento e processe o resultado.

Nos estados FAILED, DECLINED e RETURNED, o payload do webhook (e os resultados da busca) não incluem detalhes do erro. Para obter o motivo da falha, chame GET /v3/payments/{paymentId} depois de detectar o estado terminal.

Para mais informações sobre os estados terminais e o significado deles, consulte Ciclo de vida do pagamento.


Espera exponencial

Aplique espera exponencial com jitter quando receber 429 Too Many Requests ou erros de servidor 5xx:

  1. Na primeira falha, aguarde um intervalo base curto (por exemplo, 2 segundos).
  2. A cada falha seguinte, dobre o tempo de espera.
  3. Adicione um jitter aleatório (por exemplo, ±10 a 20% do intervalo) para evitar tempestades de novas tentativas sincronizadas.
  4. Limite a espera máxima a um teto razoável (por exemplo, 5 minutos).
  5. Após um número configurável de novas tentativas sem sucesso, acione a sua equipe de plantão.

Exemplo de escalonamento de espera:

Nova tentativaEspera antes de tentar novamente
12s
24s
38s
416s
532s
6+60s (limite)

Fluxograma do polling

O fluxograma a seguir ilustra o laço de polling de busca em lote, incluindo a paginação e o avanço do cursor.

Fluxograma de polling de pagamentos


Próximos passos