Todos os endpoints exigem o header
X-API-KEY e respondem em https://api.malvo.io. Os webhooks
chegam de um único IP de egresso estático que você libera no firewall.As duas camadas
1
Camada 1 — Webhooks (tempo real)
Em cada evento
item/*, re-busque o recurso canônico (nunca confie só no payload):
GET /items/{itemId} e GET /accounts?itemId=.... Em transactions/created /
transactions/updated, liste as contas do itemId, pagine GET /v2/transactions para cada
conta e faça upsert por id da transação. Em
transactions/deleted, apague por id.2
Camada 2 — Job noturno (rede de segurança)
Liste todos os Items ativos; para cada Item com
lastUpdatedAt mais velho que o esperado,
chame PATCH /items/{id} para disparar um sync; e re-busque transações dos últimos N dias
para pegar o que escapou durante quedas de webhook.Camada 1 — Handler idempotente
Toda entrega carrega umeventId (UUID). O mesmo eventId é reusado em todas as
re-entregas de um evento e entre todos os endpoints inscritos no mesmo evento (ex.: um webhook
all e um item/error recebem o mesmo eventId para uma ocorrência). Persista o eventId e
trate duplicatas como no-op antes de aplicar qualquer efeito colateral.
Handler (ack-first + dedupe por eventId)
Camada 2 — Job noturno de reconciliação
Job noturno
Reconcilie por
dateFrom/createdAtFrom e faça upsert por id — reprocessar os mesmos dias
nunca duplica dados. Prefira GET /v2/transactions (cursor-based): pagine seguindo o next até
ele vir null.Lidando com 429 e limites mensais do Open Finance
Dois limites distintos te afetam:
Backoff com jitter + Retry-After
Quando o retry do webhook se esgota
A Malvo tenta entregar cada evento em até 9 tentativas, distribuídas em 3 fases:
Esgotadas as 9 tentativas, o evento é descartado permanentemente. (Exceção:
item/login_succeeded é entregue no máximo 3 vezes, sem backoff — é só uma dica de UX.)
O que fazer quando um evento é descartado
O que fazer quando um evento é descartado
Não há re-entrega automática depois das 9 tentativas. A recuperação é exatamente o job
noturno (Camada 2): liste os Items, dê
PATCH /items/{id} nos defasados e re-busque
GET /v2/transactions dos últimos N dias. Como tudo é upsert por id, você fecha o buraco
sem duplicar nada.Re-entrega manual pelo Dashboard
Re-entrega manual pelo Dashboard
Para um evento específico que você sabe ter perdido, use a re-entrega manual na página de
Eventos do Dashboard — ela reusa o mesmo
eventId, então o seu handler idempotente trata
sem efeito duplicado.Checklist de robustez
1
Dedupe por eventId
Persista todo
eventId e trate duplicatas como no-op antes de qualquer efeito colateral.2
Ack first, work later
Responda
2XX em <5s e processe na fila. Trabalho pesado síncrono causa timeout e retries.3
REST como fonte da verdade
Em cada
item/*, re-busque GET /items/{id} e GET /accounts. Upsert por id.4
Job noturno
Liste Items,
PATCH nos defasados, refetch dos últimos N dias.5
Backoff com jitter
Em
429, respeite Retry-After e espace os jobs para não queimar a cota mensal do Open Finance.Próximos passos
Webhooks
Eventos, entrega, retries e segurança em detalhe.
Sincronizar transações
Paginação por cursor e atualização incremental com
createdAtFrom.