Entregas e novas tentativas
Cada evento vira uma entrega para cada endpoint ligado e inscrito nele. A entrega tem a sua própria vida: tentativas, situação e resultado, que você acompanha pelo log.
O que a sua resposta significa
Seção intitulada “O que a sua resposta significa”Cada tentativa tem 15 segundos para terminar. O que vale é só o código HTTP:
| Resposta | O que acontece |
|---|---|
2xx | Entregue. Acabou |
410 | O endpoint é desligado na hora, e a entrega fica como falha, sem nova tentativa |
429, 502, 503, 504 | Falha. A próxima tentativa respeita o Retry-After, se vier |
3xx | Falha. Redirecionamento nunca é seguido |
| Qualquer outro código | Falha, e tenta de novo pela agenda |
| Sem resposta | Falha (tempo esgotado, conexão recusada, erro de TLS, DNS), e tenta de novo |
O corpo da resposta não precisa de nada: um 200 vazio basta. Os cabeçalhos da resposta não são lidos, a não ser o Retry-After, e não são guardados. Do corpo, até 2 KB ficam guardados no log de entregas, então não responda com dado sensível.
Use o 410 só quando o endereço deixou de existir de vez: ele desliga o endpoint para todos os eventos, não só para aquele.
A agenda de novas tentativas
Seção intitulada “A agenda de novas tentativas”Depois da primeira tentativa, as seguintes esperam:
| Tentativa | Espera depois da anterior |
|---|---|
| 2ª | 5 segundos |
| 3ª | 5 minutos |
| 4ª | 30 minutos |
| 5ª | 2 horas |
| 6ª | 5 horas |
| 7ª | 10 horas |
| 8ª | 14 horas |
| 9ª | 20 horas |
| 10ª | 24 horas |
Cada espera varia 10% para cima ou para baixo, ao acaso, para muitas entregas que falharam juntas não voltarem todas no mesmo segundo. São 10 tentativas em pouco mais de 3 dias. Se a décima falhar, a entrega fica como failed, e você ainda pode reenviá-la enquanto o evento existir.
Retry-After
Seção intitulada “Retry-After”Nas respostas 429, 502, 503 e 504, o Retry-After é respeitado, em segundos ou como data HTTP. Ele só aumenta a espera: a próxima tentativa sai no que for mais tarde entre a agenda e o Retry-After. O teto é de 24 horas, então um Retry-After maior vale 24 horas. Valor inválido é ignorado, e ele não acrescenta tentativa: depois da décima, não há outra.
Desligamento automático
Seção intitulada “Desligamento automático”O endpoint que só falhou por 3 dias seguidos é desligado. A contagem começa na primeira falha e só uma entrega com sucesso a zera: um endpoint que falha às vezes e acerta às vezes nunca é desligado por isso.
Nos dois casos de desligamento automático (3 dias de falha e 410), dono e administradores recebem um e-mail com o domínio do endpoint e a data. O endpoint aparece com status: "disabled" e disabled_reason failing ou gone.
Os valores de disabled_reason são quatro: manual (alguém desligou, pelo painel ou por PATCH), failing (3 dias de falha), gone (o destino respondeu 410) e emergency_key_rotation (pausado por segurança: a chave de API que inscreveu o endpoint passou pela rotação “Parar agora” ou, quando a inscrição no programa do GitHub estiver ativa, foi revogada automaticamente por ter sido achada publicada). Com o endpoint ligado, o campo é null.
Enquanto o endpoint está desligado:
- nenhum evento novo gera entrega para ele, e esses eventos não ficam guardados esperando por ele;
- a entrega que já estava na fila é fechada sem envio, com o erro
endpoint_disabled.
Para religar, PATCH /public/v1/webhook_endpoints/{id} com "status": "enabled". Religar zera a contagem de falhas. Os eventos do período em que ele esteve desligado não chegam a esse endpoint e não podem ser reenviados para ele, porque nenhuma entrega foi criada. Para recuperar o que mudou nesse período, sincronize com updated_after (veja Boas práticas). O reenvio manual vale para as entregas que falharam antes do desligamento.
O log de entregas
Seção intitulada “O log de entregas”GET /public/v1/webhook_endpoints/{id}/deliveries lista as entregas do endpoint, das mais novas para as mais antigas, com filtro por status (pending, succeeded, failed) e por event_type. Cada entrega traz a situação, o número de tentativas, a próxima tentativa, o código HTTP e a duração da última, até 2 KB do corpo da resposta e, quando não houve resposta, o motivo em error.
A lista segue a mesma regra de GET /public/v1/events: só aparecem as entregas de eventos dos módulos que a chave lê (<modulo>:read) e que o membro dela pode ver no painel.
Os valores de error:
error | O que houve |
|---|---|
timeout | A tentativa passou de 15 segundos |
connection_refused | O servidor recusou a conexão |
connection_reset | A conexão caiu no meio |
host_unreachable | Não foi possível chegar ao servidor |
dns_failed | O nome não resolveu |
tls_error | Certificado inválido, vencido ou autoassinado, ou falha no TLS |
redirect_not_followed | O servidor respondeu 3xx |
blocked_target | O nome passou a apontar para um endereço interno |
blocked_protocol, blocked_port, credentials_in_url, invalid_url | A URL não passa mais na política de destino |
network_error | Outra falha de rede |
endpoint_disabled | O endpoint estava desligado; a entrega foi fechada sem envio |
subscriber_access_lost | Quem inscreveu o endpoint não lê mais o módulo do evento; fechada sem envio |
plan_without_api | O plano da empresa não tem mais a API; fechada sem envio |
internal_error | Falha do nosso lado. Ela segue a agenda de novas tentativas como qualquer falha |
Quando houve resposta HTTP, error vem null e o motivo está em response_status_code (o 3xx é a exceção: vem com redirect_not_followed). endpoint_disabled, subscriber_access_lost e plan_without_api não gastam tentativa: a entrega é fechada sem ser enviada.
Reenvio manual
Seção intitulada “Reenvio manual”POST /public/v1/webhook_endpoints/{id}/deliveries/{delivery_id}/retry responde 202 e cria uma entrega nova do mesmo evento para o mesmo endpoint. A entrega anterior fica como estava, com o histórico dela, e a nova tem retry_number maior.
O reenvio é um pedido explícito seu: ele confere de novo o acesso de quem inscreveu o endpoint, mas não confere se o endpoint ainda está inscrito naquele tipo de evento. Uma entrega de sale.paid pode ser reenviada mesmo que o endpoint não assine mais sale.paid.
- A entrega nova segue o mesmo caminho de qualquer outra: assinada com o segredo atual, com a mesma conferência de destino e a mesma agenda de novas tentativas se falhar.
- O
webhook-ide oiddo corpo são os mesmos do evento original. Se o seu sistema já tinha processado aquele evento, é pelowebhook-idque ele reconhece a repetição. - O corpo é o do evento, como ele foi registrado. O objeto não é relido: para o estado de agora, consulte a API.
As recusas:
| Resposta | Quando |
|---|---|
404 resource_not_found | A entrega não existe, é de outro endpoint, ou o evento tem mais de 30 dias |
409 conflict com param: "status" | O endpoint está desligado. Religue antes |
409 conflict | Já existe uma entrega desse evento para esse endpoint na fila (a original ainda tentando, ou outro reenvio). Espere ela terminar |
409 conflict | Quem inscreveu o endpoint não lê mais o módulo do evento. Devolva o acesso ou edite o endpoint com quem tem |
403 permission_missing | A chave não tem o <modulo>:read de algum evento que o endpoint assina (a mesma regra da troca de URL) |
403 plan_feature_unavailable | O plano da empresa não tem a API |
Por quanto tempo fica guardado
Seção intitulada “Por quanto tempo fica guardado”Eventos e entregas ficam guardados por 30 dias e depois são apagados. Esse é o prazo do log de entregas, de GET /public/v1/events e do reenvio manual.
Próximo passo
Seção intitulada “Próximo passo”- Boas práticas: como montar o recebimento para aguentar repetição e desordem.
- Referência: as rotas de entregas e de eventos, campo a campo.