Skip to main content

Card issuing events

The events a card issuing program emits. The envelope they arrive in, test deliveries and the rule for unknown types are on the event catalog and apply to every product.

Each event has its own anchor. For example, /docs/webhooks/events-card-issuing#card.frozen goes straight to card.frozen.

Cardholder​

data.object is a cardholder with id, object, type, kyc_status, has_identity_document, created_at, updated_at, plus first_name, last_name, email, and reference when those fields are set.

Sensitive identity information isn't included in webhook payloads. The identity document number is never returned; has_identity_document only tells you whether a document is on file. The address, phone number, and date of birth aren't included either.

cardholder.kyc_approved
{
"id": "evt_01HX8ZQ2K4M7P9RSTV",
"object": "event",
"type": "cardholder.kyc_approved",
"api_version": "2026-08-01",
"environment": "sandbox",
"created_at": "2026-07-29T14:35:02Z",
"data": {
"object": {
"id": "chd_01HX8ZQ2K4M7P9RSTV",
"object": "cardholder",
"type": "individual",
"kyc_status": "approved",
"has_identity_document": true,
"first_name": "Test",
"last_name": "Approved",
"email": "test.approved@example.com",
"reference": "user-4471",
"created_at": "2026-07-29T14:32:05Z",
"updated_at": "2026-07-29T14:35:02Z"
}
}
}

cardholder.created​

A new cardholder record was created.

cardholder.updated​

A mutable cardholder field changed. This includes changes to kyc_status.

cardholder.kyc_approved​

The cardholder's identity verification was approved.

cardholder.kyc_rejected​

The cardholder's verification was definitively rejected.

Account​

data.object is an account with id, object, cardholder_id, program_id, currency, status, ledger_balance, held_balance, available_balance, created_at, and updated_at, plus reference when set.

The three balance fields are integers in the minor units of currency. This is different from the REST API representation, where monetary values use {amount, currency} objects.

The processor's own account number is never included in an event payload.

account.funded
{
"id": "evt_01HX8ZQ2K4M7P9RSTW",
"object": "event",
"type": "account.funded",
"api_version": "2026-08-01",
"environment": "sandbox",
"created_at": "2026-07-29T14:36:10Z",
"data": {
"object": {
"id": "acct_01HX8ZQ2K4M7P9RSTV",
"object": "account",
"cardholder_id": "chd_01HX8ZQ2K4M7P9RSTV",
"program_id": "prog_01HX8ZQ2K4M7P9RSTVWXYZABCD",
"currency": "SGD",
"status": "active",
"ledger_balance": 25000,
"held_balance": 0,
"available_balance": 25000,
"created_at": "2026-07-29T14:32:06Z",
"updated_at": "2026-07-29T14:36:10Z"
}
}
}

The balances reflect the account at the time the event is created. For account.funded, that means the values have been read back after the credit was applied rather than coming from the account's previous state.

account.created​

An account was opened.

account.updated​

The account changed. This includes status changes, such as an account being blocked or unblocked, as well as changes reported by the processor or a debit from the account.

account.funded​

Value was credited to the account. The balance fields contain the values after the credit was applied.

Card​

data.object is a card with id, object, cardholder_id, account_id, program_id, form_factor, status, currency, is_default, created_at, and updated_at, plus last_four, embossed_name, expires_at, and reference when set.

card.created
{
"id": "evt_01HX8ZQ2K4M7P9RSTX",
"object": "event",
"type": "card.created",
"api_version": "2026-08-01",
"environment": "sandbox",
"created_at": "2026-07-29T14:32:08Z",
"data": {
"object": {
"id": "card_01HX8ZQ2K4M7P9RSTV",
"object": "card",
"cardholder_id": "chd_01HX8ZQ2K4M7P9RSTV",
"account_id": "acct_01HX8ZQ2K4M7P9RSTV",
"program_id": "prog_01HX8ZQ2K4M7P9RSTVWXYZABCD",
"form_factor": "virtual",
"status": "active",
"currency": "SGD",
"last_four": "4242",
"expires_at": "2029-04-30T23:59:59Z",
"is_default": true,
"created_at": "2026-07-29T14:32:08Z",
"updated_at": "2026-07-29T14:32:08Z"
}
}
}

The full card number and CVV are never included in webhook payloads. last_four is the only part of the card number exposed here.

card.created means the card request was accepted. card.issued means the card now exists and can be activated. card.activated means it can be used.

Every card follows the same path, on every program:

Eventstatus in the payloadWhat to do
card.createdpending, or inactive if the card was issued at onceNothing yet
card.issuedinactiveCall POST /v1/cards/{id}/activate when you want the card to start working
card.activatedactiveThe card can be used

card.created fires for every card. card.issued fires when a card moves out of pending. A card that was issued at once is inactive already in the card.created payload and has no card.issued event, so use the status in the payload rather than relying on the event name.

card.created​

Your request to issue a card was accepted and the card record now exists. It fires once for every card, on every program.

The status tells you what happened:

  • pending — the request was accepted, but the card isn't ready yet. card.issued follows once it is.
  • inactive — the card was issued at once and is ready to be activated.

card.issued​

A pending card now exists at the processor. Its status is inactive: the card is ready to be activated, and can't be used yet.

The card may take a few minutes to appear, and sometimes closer to an hour. We check for it for you and send the event once it's ready, so there's no need to poll. The payload carries last_four and expires_at when the processor reports them.

Activate the card with POST /v1/cards/{card_id}/activate when you're ready for it to be used.

card.activated​

The card is now active and can be used. It fires when you activate a card with POST /v1/cards/{card_id}/activate, for virtual and physical cards alike.

Unfreezing a card does not trigger card.activated. It triggers card.unfrozen.

card.frozen​

The card was temporarily blocked.

card.unfrozen​

A temporary card block was removed.

card.closed​

The card was permanently terminated.

Authentication​

data.object is an authentication with id, object, status, method, card_id, cardholder_id, amount, created_at, and updated_at, plus merchant and expires_at when the Access Control Server provides them.

Unlike the account balance fields, amount uses the normal {amount, currency} format.

authentication.challenged
{
"id": "evt_01HX8ZQ2K4M7P9RSTX",
"object": "event",
"type": "authentication.challenged",
"api_version": "2026-08-01",
"environment": "sandbox",
"created_at": "2026-07-29T14:38:00Z",
"data": {
"object": {
"id": "authn_01HX8ZQ2K4M7P9RSTV",
"object": "authentication",
"status": "pending",
"method": "out_of_band",
"card_id": "card_01HX8ZQ2K4M7P9RSTV",
"cardholder_id": "chd_01HX8ZQ2K4M7P9RSTV",
"merchant": { "name": "Kopi Roastery" },
"amount": { "amount": 4250, "currency": "SGD" },
"created_at": "2026-07-29T14:38:00Z",
"updated_at": "2026-07-29T14:38:00Z"
}
}
}

Only out-of-band challenges produce authentication events. Passcode challenges are handled entirely inside the ACS and don't create an authentication object or webhook event.

An authentication can have a status of pending, approved, or declined.

authentication.challenged​

A challenge is waiting for an answer from your application. The response window is only a few minutes, so this should be treated as a high-priority event.

authentication.approved​

The challenge was approved and the authentication now has an approved status.

This doesn't mean the purchase is complete. The authorization happens separately and can still be declined because of the card state, available funds, or other controls.

authentication.declined​

The challenge was declined, either by the cardholder or because your step-up flow failed. The merchant transaction will fail as a result.