/api/v1/payment-intents
201 Created
Create a payment intent
Creating an intent with an `order_id` that already has an open intent returns that existing intent instead of a duplicate — the check and the insert share one transaction and a row lock. Pass `payment_channel` to have the destination issued immediately and returned as `instruction`; leave it out and the payer chooses on the hosted page instead.
| Field | Type | Required | Notes |
|---|---|---|---|
| amount | integer | Yes | Amount in the smallest unit of the currency. |
| currency | string | Yes | An active currency code, e.g. `IDR`. |
| order_id | string | Yes | Your own order identifier. Reusable once the intent reaches a terminal state. |
| payment_channel | string | No | A channel key from `GET /api/v1/payment-channels` for this currency. Issued in the response as `instruction`. Resending an open intent with a different key switches the destination; omitting it leaves an already-issued one untouched. |
| callback_url | string | No | Where to send webhooks. Falls back to your default webhook URL. |
| return_url | string | No | Where to send the payer once the checkout finishes. |
| scenario | string | No | Force a deterministic outcome, e.g. `always_fail`. |
Example response
{
"mode": "simulation",
"data": {
"intent_id": "pi_01M2B8WVQ8KVKEVWM6YWG65FV2",
"order_id": "ORDER-1029",
"amount": 150000,
"currency": "IDR",
"status": "pending",
"checkout_url": "https://fauxpay.test/checkout/J2ZlOvlEqDuebxr4FDEHHHRYEEDYNs7CSKvxYWQ1jSzAbnBV",
"scenario": null,
"payment_method": "bca_va",
"payment_channel": "bca_va",
"instruction": {
"kind": "transfer",
"label": "Virtual account number",
"account_number": "88080000003",
"account_holder": "BCA",
"amount": 150000,
"amount_formatted": "Rp1,500.00",
"unique_code": null,
"expires_at": "2026-09-12T17:28:32.000000Z"
},
"expires_at": "2026-09-12T17:28:32.000000Z",
"resolved_at": null,
"created_at": "2026-09-12T16:58:32.000000Z"
}
}