Event catalog
The shape every webhook arrives in, and where to find the events each product emits. You choose which events an endpoint receives in Cockpit under Developers → Webhook endpoints.
| Product | Events |
|---|---|
| Card issuing | Card issuing events |
Event names follow the resource.past_tense_verb pattern and don't change once
they're published. New event types may be added in minor releases, so your
handler should ignore event types it doesn't recognize instead of treating them
as errors.
The envelope
All webhook events use the same outer structure:
{
"id": "evt_01HX8ZQ2K4M7P9RSTV",
"object": "event",
"type": "card.activated",
"api_version": "2026-08-01",
"environment": "sandbox",
"created_at": "2026-07-29T14:35:02Z",
"data": { "object": { "…": "the affected object" } }
}
environment is included on every event, so the same endpoint can handle both
sandbox and production traffic without needing separate URLs.
api_version records the version used to serialize that particular payload.
Don't assume it based on the version you're currently using to make API
requests.
For a given resource, every event type uses the same payload object. For
example, every cardholder.* event contains a cardholder, and every card.*
event contains a card. The event type tells you what happened; data.object
tells you which object it happened to.
The payload represents the object as it looked when the event was created. It isn't re-read when the webhook is delivered.
There is one exception to the normal REST API shape: on account.* events,
ledger_balance, held_balance, and available_balance are plain integers in
minor units. The currency is provided separately in the payload's currency
field.
Test deliveries
data.object is a webhook_test object containing object, endpoint_id,
message, and sent_at. This is the one event payload that isn't based on a
REST API resource.
{
"id": "evt_01HX8ZQ2K4M7P9RSU3",
"object": "event",
"type": "webhook.test",
"api_version": "2026-08-01",
"environment": "sandbox",
"created_at": "2026-07-29T14:30:00Z",
"data": {
"object": {
"object": "webhook_test",
"endpoint_id": "whe_01HX8ZQ2K4M7P9RSTV",
"message": "This is a test event from AletaPlanet Cockpit.",
"sent_at": "2026-07-29T14:30:00Z"
}
}
}
Test events use the same outbox, signing, and retry path as normal events. That's useful for testing the complete webhook setup rather than just checking whether an endpoint is reachable.
Handle webhook.test explicitly instead of letting it fall through to whatever
your default event handler does.
webhook.test
A test event was sent from Cockpit. This event is only used for testing and never appears as part of normal card activity.
Handling unknown event types
Your webhook handler should always have a fallback for event types it doesn't know about:
switch (event.type) {
case 'cardholder.kyc_approved':
return onKycApproved(event.data.object);
case 'card.closed':
return onCardClosed(event.data.object);
default:
// New event types can be added in minor releases.
// Acknowledge events you don't handle rather than failing the webhook.
logger.debug({ type: event.type }, 'unhandled webhook event');
return;
}
New event types shouldn't require you to deploy a new version of your integration just to keep receiving existing events. Log unknown types if they're useful to you, but acknowledge them normally.