Events
A full list of events Bahn may send to your webhook endpoint.
Each section below lists the events for a given resource type and documents the fields in the data object of the notification. For the delivery format, envelope fields, and signature verification, see Introduction and Signatures.
PaymentIntent
Events triggered by lifecycle changes on a PaymentIntent.
| Event Name | Description |
|---|---|
payment_intent.status.requires_payment_method | The payment intent is waiting for a payment method to be attached. |
payment_intent.status.requires_action | Additional action is required from the customer (e.g. 3DS challenge). |
payment_intent.status.processing | The payment is currently being processed. |
payment_intent.status.succeeded | The payment was completed successfully. |
payment_intent.status.canceled | The payment intent was canceled. |
payment_intent.status.requires_capture | The payment has been authorized and is awaiting capture. |
payment_intent.status.requires_confirmation | The payment intent is ready to be confirmed. |
payment_intent.payment_failed | The payment attempt failed. Check last_payment_error in the data for the reason. |
Data Fields
data_type is payment_intent.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the PaymentIntent. |
status | string | Current status. One of: requires_payment_method, requires_confirmation, requires_action, requires_capture, processing, succeeded, canceled. |
amount | integer (int64) | The payment amount in the smallest currency unit (e.g. cents; whole đồng for VND). |
currency | string | ISO 4217 numeric currency code (e.g. "704" for VND). |
payment_method_id | string | ID of the PaymentMethod attached to this PaymentIntent. |
payment_method | object | Expanded PaymentMethod object — convenience copy of the payment_method_id resource. See PaymentMethod below. |
latest_charge_id | string | ID of the most recent Charge created for this PaymentIntent. |
last_payment_error | object|null | Details of the last error, if the payment failed. See LastPaymentError below. |
metadata | object|null | Set of key-value pairs for storing additional information. null if none. |
created_at | string | ISO 8601 timestamp of when the PaymentIntent was created. |
updated_at | string | ISO 8601 timestamp of the last update. |
canceled_at | string|null | ISO 8601 timestamp of when the PaymentIntent was canceled. null if not canceled. |
PaymentMethod
Describes how the customer is paying. The shape of the type-specific sub-object depends on type — only the sub-object matching type is present.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the PaymentMethod. Matches payment_method_id on the parent PaymentIntent. |
type | string | Payment method type. One of: napas_qr, card. |
napas_qr | object | Present when type is napas_qr. Currently an empty object ({}); reserved for future Napas-specific fields. |
card | object | Present when type is card. See Card below. |
Napas QR example
{
"id": "5LYq5DYyyrzP8z99ShSM3Z",
"type": "napas_qr",
"napas_qr": {}
}Card
Card metadata captured at the time the PaymentMethod was created. Only the non-sensitive subset is returned — full PAN and CVV never appear in webhooks.
| Field | Type | Description |
|---|---|---|
brand | string | Card network. e.g. visa, mastercard, amex, jcb. |
last4 | string | The last four digits of the card number. |
exp_month | integer | Two-digit expiration month (1–12). |
exp_year | integer | Four-digit expiration year. |
fingerprint | string | Stable, opaque identifier for this card. Useful for detecting that the same physical card was used across multiple PaymentMethods without storing the PAN. |
Card example
{
"id": "DoSLcGdpuXrE7DZtgsTQ4m",
"type": "card",
"card": {
"brand": "visa",
"last4": "1116",
"exp_month": 12,
"exp_year": 2031,
"fingerprint": "PH1So8jjwTRm46G/cnJxEcIxNiNLHMWSe2BLvIPiR9U="
}
}LastPaymentError
| Field | Type | Description |
|---|---|---|
charge_id | string | ID of the Charge that failed. |
payment_method_id | string | ID of the PaymentMethod used in the failed attempt. |
code | string | Machine-readable error code. |
message | string | Human-readable description of the error. |
{
"merchant_id": "c_ticket",
"event_id": "a58ab5b3-ffd2-404e-9774-974d74899a26",
"event_name": "payment_intent.status.succeeded",
"data_type": "payment_intent",
"data": {
"id": "8Eg7sndPybDGj8sz2TBhte",
"status": "succeeded",
"amount": 123888,
"currency": "704",
"payment_method_id": "5LYq5DYyyrzP8z99ShSM3Z",
"payment_method": {
"id": "5LYq5DYyyrzP8z99ShSM3Z",
"type": "napas_qr",
"napas_qr": {}
},
"latest_charge_id": "ACG12NOCPB8HFS",
"metadata": null,
"created_at": "2026-05-19T07:20:34.358398567Z",
"updated_at": "2026-05-19T07:24:20.810341464Z",
"canceled_at": null
},
"published_at": "2026-05-19T14:24:21.612679167+07:00"
}Charge
Events triggered by status changes and actions on a Charge.
| Event Name | Description |
|---|---|
charge.status.pending | The charge has been created and is pending processing. |
charge.status.succeeded | The charge was successfully processed. |
charge.status.failed | The charge failed. |
charge.captured | The charge was captured after a prior authorization. |
charge.paid | The charge has been marked as paid. |
charge.refunded | A refund has been issued against the charge. |
Data Fields
data_type is charge.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the Charge. |
status | string | Current status. One of: pending, succeeded, failed. |
payment_intent_id | string | ID of the PaymentIntent associated with this Charge. |
amount | string (int64) | The charged amount in the smallest currency unit (e.g. cents). |
currency | string | Three-letter ISO 4217 currency code. |
balance_transaction_id | string | ID of the balance transaction for a successful charge. |
failure_balance_transaction_id | string | ID of the balance transaction created when the charge failed. |
metadata | object | Set of key-value pairs for storing additional information. |
created_at | string | ISO 8601 timestamp of when the Charge was created. |
updated_at | string | ISO 8601 timestamp of the last update. |
{
"merchant_id": "mer_123",
"event_id": "3a7bc210-1234-4abc-def0-1234567890ab",
"event_name": "charge.status.succeeded",
"data_type": "charge",
"data": {
"id": "ch_abc123",
"status": "succeeded",
"payment_intent_id": "pi_xyz789",
"amount": "10000",
"currency": "704",
"balance_transaction_id": "txn_def456",
"failure_balance_transaction_id": "",
"metadata": {
"order_id": "order_001"
},
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:01:00Z"
},
"published_at": "2026-01-01T07:01:00+07:00"
}Refund
Events triggered by lifecycle status changes on a Refund.
| Event Name | Description |
|---|---|
refund.status.pending | The refund has been initiated and is pending processing. |
refund.status.requires_action | Additional action is required to complete the refund. |
refund.status.succeeded | The refund was completed successfully. |
refund.status.failed | The refund failed. |
refund.status.canceled | The refund was canceled. |
Data Fields
data_type is refund.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the Refund. |
status | string | Current status. One of: pending, requires_action, succeeded, failed, canceled. |
reason | string | Reason for the refund. One of: duplicate, fraudulent, requested_by_customer. |
charge_id | string | ID of the Charge being refunded. |
payment_intent_id | string | ID of the PaymentIntent associated with this refund. |
amount | string (int64) | The refunded amount in the smallest currency unit (e.g. cents). |
currency | string | Three-letter ISO 4217 currency code. |
metadata | object | Set of key-value pairs for storing additional information. |
created_at | string | ISO 8601 timestamp of when the Refund was created. |
updated_at | string | ISO 8601 timestamp of the last update. |
{
"merchant_id": "mer_123",
"event_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_name": "refund.status.succeeded",
"data_type": "refund",
"data": {
"id": "re_abc123",
"status": "succeeded",
"reason": "requested_by_customer",
"charge_id": "ch_xyz789",
"payment_intent_id": "pi_def456",
"amount": "5000",
"currency": "704",
"metadata": {
"note": "customer request"
},
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:01:00Z"
},
"published_at": "2026-01-01T07:01:00+07:00"
}SetupIntent
Events triggered by lifecycle changes on a SetupIntent (saving a card for future use). Use setup_intent.status.succeeded to learn when a card is verified and read the resulting payment_method_id for later CIT/MIT charges.
| Event Name | Description |
|---|---|
setup_intent.status.requires_payment_method | Initial state, or reset after a failed verification — the customer can (re)submit a card. |
setup_intent.status.requires_confirmation | The setup intent is ready to be confirmed. |
setup_intent.status.requires_action | Additional action is required from the customer (the mandatory 3DS challenge). |
setup_intent.status.processing | 3DS completed; the card-verification authorization is being processed. |
setup_intent.status.succeeded | The card was verified and saved. payment_method_id is now populated and reusable. |
setup_intent.status.canceled | The setup intent was canceled. |
Data Fields
data_type is setup_intent.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the SetupIntent. |
status | string | Current status. One of: requires_payment_method, requires_confirmation, requires_action, processing, succeeded, canceled. |
usage | string | How the saved card will be reused: on_session (CIT) or off_session (MIT). |
description | string | Merchant-provided description. |
payment_method_id | string | ID of the saved PaymentMethod. Empty until the intent reaches succeeded. |
customer_id | string | The customer the card is saved against. |
latest_setup_attempt_id | string | ID of the most recent verification attempt (the card-verification authorization). |
metadata | object | Arbitrary key-value pairs supplied at creation. |
created_at | string | ISO 8601 timestamp of when the SetupIntent was created. |
updated_at | string | ISO 8601 timestamp of the last update. |
{
"merchant_id": "mc_5g3rNHWpoH",
"event_id": "f7d8cae4-6ad8-439e-899d-eff2c03103f3",
"event_name": "setup_intent.status.requires_payment_method",
"data_type": "setup_intent",
"data": {
"id": "15rEusGuKrkAXnK4W9p63c",
"status": "requires_payment_method",
"usage": "off_session",
"description": "",
"payment_method_id": "",
"customer_id": "BAuufV3pHK8PxYvg7TonJC",
"latest_setup_attempt_id": "",
"metadata": {
"key1": "value1",
"key2": "value2"
},
"created_at": "2026-06-30T10:01:49.688965063Z",
"updated_at": "2026-06-30T10:01:49.710943Z"
},
"published_at": "2026-06-30T17:01:50.459672255+07:00"
}ReaderAction
Events triggered by lifecycle changes on a ReaderAction (a payment action dispatched to a card reader or terminal). Use these to track the state of an in-progress reader action and to react when it succeeds, fails, or is canceled.
| Event Name | Description |
|---|---|
reader_action.status.in_progress | The reader action has been dispatched to the terminal and is running. |
reader_action.status.succeeded | The reader action completed successfully. |
reader_action.status.failed | The reader action failed. Check failure_code and failure_message for the reason. |
reader_action.status.canceled | The reader action was canceled (by the customer, the merchant, or the terminal). |
Data Fields
data_type is reader_action.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier of the ReaderAction. |
reader_id | string | ID of the device that runs the action. Several readers can share one terminal_id, so use this field to identify the till. |
merchant_id | string | ID of the merchant that owns the reader. |
account_id | string|null | ID of the account the reader belongs to. null if not applicable. |
terminal_id | string | ID of the terminal bound to the reader. |
type | string | Action type. One of: process_payment_intent, confirm_payment_intent, collect_payment_method, refund_payment. |
status | string | Current status. One of: in_progress, succeeded, failed, canceled. |
target_id | string|null | ID of the target resource the action operates on (e.g. the PaymentIntent for process_payment_intent). null if not applicable. |
failure_code | string|null | Machine-readable failure code. Present when status is failed. |
failure_message | string|null | Human-readable failure description. Present when status is failed. |
failure_decline_code | string|null | Card-network decline code when the failure came from an issuer decline. null otherwise. |
process_payment_intent | object|null | Present when type is process_payment_intent. Describes the payment being processed on the reader. See ProcessPaymentIntent below. |
created_at | string | ISO 8601 timestamp of when the ReaderAction was created. |
updated_at | string | ISO 8601 timestamp of the last update. |
ProcessPaymentIntent
Describes a process_payment_intent action running on the reader.
| Field | Type | Description |
|---|---|---|
process_config | object | Runtime configuration for the action. See ProcessConfig below. |
amount | integer (int64) | The payment amount in the smallest currency unit (whole đồng for VND). Omitted until the amount is known. |
currency | string | ISO 4217 numeric currency code (e.g. "704" for VND). Omitted until the currency is known. |
payment_method_details | object|null | Payment method chosen for this action. Omitted until the method is chosen. See PaymentMethodDetailsPreview below. |
ProcessConfig
| Field | Type | Description |
|---|---|---|
enable_customer_cancellation | boolean | Whether the customer can cancel the action from the reader UI. |
PaymentMethodDetailsPreview
The shape of the type-specific sub-object depends on type. Only the sub-object matching type is present.
| Field | Type | Description |
|---|---|---|
type | string | Payment method type. One of: card_present, napas_qr, visa_qr. |
card_present | object | Present when type is card_present. { "brand": string, "last4": string }. |
napas_qr | object | Present when type is napas_qr. See NapasQr below. |
visa_qr | object | Present when type is visa_qr. { "brand": string, "last4": string }. |
NapasQr
| Field | Type | Description |
|---|---|---|
service | string | Napas service. One of: local, global. |
bank_code | string | Napas bank code of the destination account. |
account_holder_name | string | Account holder name displayed on the reader. Empty if not provided. |
Example
{
"merchant_id": "mer_123",
"event_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"event_name": "reader_action.status.succeeded",
"data_type": "reader_action",
"data": {
"id": "ra_5g3rNHWpoH",
"reader_id": "rdr_9kLmNpQrSt",
"merchant_id": "mer_123",
"terminal_id": "tm_7aBcDeFgHi",
"type": "process_payment_intent",
"status": "succeeded",
"target_id": "8Eg7sndPybDGj8sz2TBhte",
"failure_code": null,
"failure_message": null,
"failure_decline_code": null,
"process_payment_intent": {
"process_config": {
"enable_customer_cancellation": true
},
"amount": 123888,
"currency": "704",
"payment_method_details": {
"type": "napas_qr",
"napas_qr": {
"service": "local",
"bank_code": "970416",
"account_holder_name": "NGUYEN VAN A"
}
}
},
"created_at": "2026-05-19T07:20:34.358398567Z",
"updated_at": "2026-05-19T07:24:20.810341464Z"
},
"published_at": "2026-05-19T14:24:21.612679167+07:00"
}