Despachar a mensagem do ato
const url = 'https://api.emmaos.com.br/notices/019928f4-3c21-7a4b-8f0e-6c2d5b1a9f77/dispatch';const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.emmaos.com.br/notices/019928f4-3c21-7a4b-8f0e-6c2d5b1a9f77/dispatch \ --header 'Authorization: Bearer <token>'Envia ao destinatário a mensagem do ato e registra o fato: o ato passa
de PENDING a SENT e ganha um evento MESSAGE_SENT na linha do
tempo. Sempre limitado ao tribunal do token: um id que exista em
outro tribunal responde 404, não 403.
Despachar é ato explícito, e não efeito do cadastro. O ato nasce
PENDING em POST /notices e só sai daí por aqui. A ordem interna é
reserva → claim → envio → registro: o id da mensagem é cunhado e
gravado antes do envio, com o status ainda PENDING; só uma
execução por vez consegue o claim do envio (as concorrentes recebem
409 DISPATCH_IN_PROGRESS); e o evento MESSAGE_SENT é gravado depois
que o provedor aceitou, mesmo que um relatório de entrega já tenha
avançado o status (nesse caso o evento entra e o status fica onde
está; a resposta traz o status real). Uma falha no meio deixa um id
reservado sem evento (que a repetição reivindica), e nunca um
despacho sem rastro.
Não é idempotente por header, e sim por estado. Repetir sobre um
ato que já saiu de PENDING responde 409: o status não retrocede
nem se repete. Re-envio deliberado seria outra mensagem, com outro id,
e ainda não existe; é pergunta aberta na frente projeto.
Qual plataforma envia depende do stage. Os stages autorizados a usar
a Infobip (hoje, só o dev-andre) enviam a primeira mensagem de verdade pelo
WhatsApp. Num stage que tenha lista de destinatários, só para essa
lista (422, RECIPIENT_NOT_ALLOWED, para qualquer outro número); o
dev-andre não tem lista desde a FIN-158, como a produção. Os
outros stages de desenvolvimento e o staging usam um gateway
falso, que não envia nada; ele existe para o rito ser exercitável
de ponta a ponta sem depender do provedor. Produção não sobe sem a
plataforma real.
Authorizations
Seção intitulada “Authorizations”Parameters
Seção intitulada “Parameters”Path Parameters
Seção intitulada “Path Parameters”UUIDv7 do ato.
Example
019928f4-3c21-7a4b-8f0e-6c2d5b1a9f77Responses
Seção intitulada “Responses”Despachado, com o status novo do ato
O resultado do despacho. Dois campos, e só: o id do ato e o status
novo. O id da mensagem no provedor NÃO sai aqui: é controle interno
da reserva, não tem leitor declarado, e publicá-lo prenderia o formato
do fornecedor no contrato (ver projecao-publica-do-ledger.md).
object
UUIDv7 do ato despachado.
Progresso operacional do ato.
Example
{ "id": "019928f4-3c21-7a4b-8f0e-6c2d5b1a9f77", "status": "SENT"}Requisição inválida
object
Código estável do erro. É por ele que se programa.
Campo que causou a recusa, quando aplicável.
Texto em português para diagnóstico. Não programe contra ele: pode mudar sem aviso.
Só com TENANT_NOT_CONFIGURED: o que falta na configuração do
tribunal.
Examples
Campo obrigatório ausente ou malformado
{ "error": "INVALID_REQUEST", "field": "noticeType", "message": "noticeType é obrigatório"}Corpo não é JSON válido
{ "error": "INVALID_JSON", "message": "corpo JSON inválido"}Sem header Authorization. Recusado pelo API Gateway antes de chegar à
aplicação.
Token inválido, expirado, ou de um emissor que não é tribunal conhecido neste stage. Recusado pelo authorizer.
Não existe neste tribunal
object
Código estável do erro. É por ele que se programa.
Campo que causou a recusa, quando aplicável.
Texto em português para diagnóstico. Não programe contra ele: pode mudar sem aviso.
Só com TENANT_NOT_CONFIGURED: o que falta na configuração do
tribunal.
Example
{ "error": "NOT_FOUND"}O pedido é válido, e o conflito é com o estado do ato ou do tribunal. Quatro códigos:
INVALID_STATUS_TRANSITION: o ato já saiu dePENDING. Repetir dá o mesmo resultado.DISPATCH_IN_PROGRESS: outra execução está despachando este ato agora (duas abas, repetição depois de timeout). Esta chamada não enviou nada. Repetir em instantes resolve: ou a primeira mensagem já está registrada (200, com o status real), ou a outra execução soltou o claim e esta envia. Vem comRetry-After.SEALED_DOCUMENT_MISSING: o ato não tem documento selado, e o destinatário nunca recebe o documento-fonte. Só acontece com atos criados antes de o selado existir. Nada foi enviado. Repetir dá o mesmo resultado.TENANT_NOT_CONFIGURED: o tribunal não tem configurado o nome do órgão, o telefone público ou, no stage com WhatsApp real, o número de envio.missingdiz quais faltam. Nada foi enviado, e o ato continuaPENDING. Repetir dá o mesmo resultado até a plataforma configurar o tribunal.
object
Código estável do erro. É por ele que se programa.
Campo que causou a recusa, quando aplicável.
Texto em português para diagnóstico. Não programe contra ele: pode mudar sem aviso.
Só com TENANT_NOT_CONFIGURED: o que falta na configuração do
tribunal.
Examples
{ "error": "INVALID_STATUS_TRANSITION", "message": "Ato 019928f4-3c21-7a4b-8f0e-6c2d5b1a9f77 está em SENT; o evento MESSAGE_SENT afirma SENT, que não é avanço. O status não retrocede."}{ "error": "DISPATCH_IN_PROGRESS", "message": "Outra execução está despachando este ato agora. Aguarde alguns segundos e confira o status."}{ "error": "SEALED_DOCUMENT_MISSING", "message": "O ato 019928f4-3c21-7a4b-8f0e-6c2d5b1a9f77 não tem documento selado e não pode ser despachado"}{ "error": "TENANT_NOT_CONFIGURED", "message": "O tribunal demo não tem displayName, publicPhone configurado(s) em tenant_data (pnpm --filter infra tenant:settings); nada foi enviado.", "missing": [ "displayName", "publicPhone" ]}O despacho foi recusado e repetir dá o mesmo resultado. Dois códigos, duas causas:
RECIPIENT_NOT_ALLOWED: o destinatário não está autorizado neste stage. Recusa nossa, não do provedor.DISPATCH_REJECTED: a plataforma de mensagens recusou de forma permanente (por exemplo, número inválido, ou a mensagem aceita no HTTP mas com statusREJECTEDno corpo). Nada foi registrado como enviado. Não repita: revise o telefone do destinatário no cadastro. Falha transitória (5xx, prazo, limite de taxa) continua sendo502 DISPATCH_FAILED, esta sim repetível.
object
Código estável do erro. É por ele que se programa.
Campo que causou a recusa, quando aplicável.
Texto em português para diagnóstico. Não programe contra ele: pode mudar sem aviso.
Só com TENANT_NOT_CONFIGURED: o que falta na configuração do
tribunal.
Examples
{ "error": "RECIPIENT_NOT_ALLOWED", "message": "Destinatário *********4321 não está autorizado neste stage. Nada foi enviado."}{ "error": "DISPATCH_REJECTED", "message": "A plataforma de mensagens recusou o despacho e repetir não resolve. Revise o telefone do destinatário no cadastro do ato."}Erro interno
object
Código estável do erro. É por ele que se programa.
Campo que causou a recusa, quando aplicável.
Texto em português para diagnóstico. Não programe contra ele: pode mudar sem aviso.
Só com TENANT_NOT_CONFIGURED: o que falta na configuração do
tribunal.
Example
{ "error": "INTERNAL_ERROR"}Falha transitória da plataforma de mensagens (5xx, prazo, limite
de taxa), ou não se sabe se ela aceitou (por exemplo, a resposta dela se perdeu por tempo
esgotado). O ato ficou com o id reservado e sem evento; repita:
a repetição reaproveita a mesma reserva e reenvia com o mesmo
messageId. O backend não garante que o cidadão receba uma mensagem
só: se a plataforma tinha aceitado e o registro se perdeu sem que
nenhum relatório de entrega chegasse, a repetição reenvia, e a
deduplicação pelo messageId do lado da plataforma ainda não foi
verificada (FIN-107, P7). Se um relatório de entrega já chegou, o
claim reconhece o envio e a repetição não manda nada.
object
Código estável do erro. É por ele que se programa.
Campo que causou a recusa, quando aplicável.
Texto em português para diagnóstico. Não programe contra ele: pode mudar sem aviso.
Só com TENANT_NOT_CONFIGURED: o que falta na configuração do
tribunal.
Example
{ "error": "DISPATCH_FAILED", "message": "A plataforma de mensagens não aceitou o despacho. Tente novamente."}O banco do tribunal estava pausado e não retomou dentro do orçamento da requisição. Repita.
object
Código estável do erro. É por ele que se programa.
Campo que causou a recusa, quando aplicável.
Texto em português para diagnóstico. Não programe contra ele: pode mudar sem aviso.
Só com TENANT_NOT_CONFIGURED: o que falta na configuração do
tribunal.
Example
{ "error": "DATABASE_RESUMING", "message": "Banco de dados está retomando. Tente novamente."}Headers
Seção intitulada “Headers”Segundos a esperar antes de repetir.