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
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.
| Padrão | Indicado para |
|---|---|
| Polling de pagamento único | Acompanhar o resultado de um pagamento específico que você acabou de criar |
| Polling de busca em lote | Conciliar todos os pagamentos atualizados desde a sua última verificação; capturar notificações de webhook perdidas |
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.
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.
- Não faça polling com frequência maior que 30 segundos para pagamentos ativos.
- Para pagamentos nos estados iniciais
INITIATEDouVALIDATING, 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).
| Status HTTP | Ação |
|---|---|
200 OK | Leia paymentState e continue o polling se não for terminal |
404 Not Found | O ID do pagamento é inválido ou não pertence à sua conta |
429 Too Many Requests | Aplique espera exponencial antes de tentar novamente (consulte Espera exponencial) |
500 / 503 | Repita com espera exponencial; acione um alerta se a condição persistir |
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 vezafterTimestamp: 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)
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"
}
}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.
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.
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.
- 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: 100oferece 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.
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.
Aplique espera exponencial com jitter quando receber 429 Too Many Requests ou erros de servidor 5xx:
- Na primeira falha, aguarde um intervalo base curto (por exemplo, 2 segundos).
- A cada falha seguinte, dobre o tempo de espera.
- Adicione um jitter aleatório (por exemplo, ±10 a 20% do intervalo) para evitar tempestades de novas tentativas sincronizadas.
- Limite a espera máxima a um teto razoável (por exemplo, 5 minutos).
- 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 tentativa | Espera antes de tentar novamente |
|---|---|
| 1 | 2s |
| 2 | 4s |
| 3 | 8s |
| 4 | 16s |
| 5 | 32s |
| 6+ | 60s (limite) |
O fluxograma a seguir ilustra o laço de polling de busca em lote, incluindo a paginação e o avanço do cursor.
- Para receber notificações push em vez de fazer polling, consulte Webhooks de notificação.
- Para orientações sobre os estados de pagamento que as suas respostas de polling retornarão, consulte Ciclo de vida do pagamento.
- Para ver a referência completa da API de busca de pagamentos, consulte Search payments (v3).