Skip to main content

Webhook Event Format

This page describes what every webhook delivery looks like, regardless of which integration you are on: the envelope, how events are identified, and how delivery behaves.

The contents of data depend on the event, and each event is documented in the Event Catalog.

Event Structure​

When an event occurs that matches one of your destinations, banca.me sends an HTTP POST to that destination's URL with a JSON body. new_lead and pre_approve deliveries carry an eventType field; loan_approved deliveries do not — see below for why:

{
"eventId": "9f2a1c4e-3b8d-4f71-a205-6c9e8d0b1a37",
"eventType": "pre_approve",
"data": {}
}
FieldTypeDescription
eventIdstringIdentifies the event, not the delivery attempt
eventTypestringThe event's name — new_lead or pre_approve. Not present on loan_approved
dataobjectEvent-specific payload. Its shape depends on the event

Why loan_approved has no eventType​

new_lead and pre_approve share a registration route, so one destination can legitimately be subscribed to both. eventType tells you which one just arrived without inspecting data.

loan_approved deliveries do not carry eventType, and structurally cannot need it: a loan_approved destination is BNPL's frozen, hmac-verified route (see Verify HMAC Signatures), and it can never be combined with another event type on the same URL — there is nothing to disambiguate, and widening what a frozen, externally-verified signature covers is not a risk worth taking for a field that route never needed.

If you built a discriminator against data's shape before eventType existed, it still works — see Telling the events apart for that approach, kept for loan_approved and for anyone who prefers it regardless.

eventId and idempotency​

eventId identifies the event itself. A retry carries the same eventId as the original attempt, so it is what you use to recognise a duplicate.

Store processed ids and skip anything you have already handled:

async function handleWebhook(event) {
const { eventId, data } = event;

if (await alreadyProcessed(eventId)) {
return; // duplicate delivery — nothing to do
}

await process(data);
await markProcessed(eventId);
}

Delivery behaviour​

These hold for every event:

Destination schemeHTTPS only
RedirectsNot followed
Private addressesRejected at registration

Timeouts and retries are not universal — they depend on the event:

EventTimeoutRetries
loan_approved5 secondsone retry
pre_approve5 secondsone retry
new_lead3 secondsnone — a single attempt

Respond 2xx quickly and do the real work afterwards. A handler that finishes its processing inline before responding will time out on anything slow, even though the data arrived intact. That matters most for new_lead, which has both the tightest timeout and no second chance.

Once an event exhausts its attempts it is not delivered again, and there is no self-service replay. For new_lead that means a single failure loses the event — see Best Practices for the recovery path. To recover a range of missed events, contact us.

What arrives in data​

EventIntegrationPayload
loan_approvedBNPLLoan terms and instalment schedule
new_leadReal estateIdentity and contact, 11 fields
pre_approveReal estateThe risk evaluation, flat, in 51 fields

All three are documented field by field in the Event Catalog. If you are not sure which apply to you, see Which Webhook Integration Is Yours.

Next steps​