Agendamento e Expiração de Mensagens (deliverAt e deliverUntil)
O endpoint POST /v1/messages/send suporta agendamento opcional via deliverAt e limite máximo de entrega via deliverUntil.
Como funciona o agendamento (deliverAt)
deliverAt(request) é a data/hora alvo (ISO 8601) a partir da qual a mensagem pode ser enviada.- No backend, esse valor é salvo no banco como
Message.deliverBy. - O job no BullMQ é enfileirado com
delay = max(0, deliverBy - now). - Mesmo após estar “pronta”, o worker ainda aplica o delay aleatório padrão (ex.: 30–45s) entre envios, para evitar disparos simultâneos.
Como funciona a expiração (deliverUntil)
deliverUntil(request) é a data/hora limite (ISO 8601) para a entrega da mensagem.- Se o momento do processamento pelo worker ultrapassar esse horário, a mensagem não é enviada e recebe status
FAILED. - Se omitido, a plataforma aplica regras padrão de expiração baseadas na categoria do template:
- OTP: expira em 2 minutos.
- UTILITY: expira em 1 hora.
- MARKETING: expira em 4 horas.
Payload
deliverAt e deliverUntil são opcionais.
{
"templateId": "onboarding-test",
"destinationNumber": "+5511999999999",
"variables": {
"name": "Ismael",
"lastname": "Ash"
},
"deliverAt": "2026-03-12T17:05:00.000Z",
"deliverUntil": "2026-03-12T17:15:00.000Z"
}
Regras:
- Se
deliverAtnão for enviado, a mensagem é tratada como imediata (deliverBy = now). - Use sempre ISO 8601 (ex.:
"2026-03-12T17:05:00.000Z").
Status e comportamento
- A mensagem continua com
status = QUEUEDaté ser enviada e confirmada (ou falhar). - Quando chega a hora (
deliverAt), o job sai do delay e entra no fluxo normal de envio. - Antes de enviar (ou em cada re-tentativa), o worker verifica o
deliverUntil. Se estiver expirado, marca comoFAILEDinstantaneamente e avisa o webhook.
Reconciliação no startup (SLA de 10 minutos)
Sempre que o worker inicia (e também periodicamente), ele verifica o banco por mensagens QUEUED que já deveriam ter sido processadas e aplica:
- Se
now > deliverBy + 10 minutos: marca a mensagem comoFAILED(timeout de entrega). - Se
deliverBy <= now <= deliverBy + 10 minutos: garante que a mensagem será enviada (reenfileira/promove o job se necessário).
Isso cobre casos como restart/crash do worker ou perda do job na fila.
Configuração
- Intervalo do reconciler:
MESSAGE_RECONCILER_INTERVAL_MS(padrão: 60000).