Payments
A payment represents a single KHQR charge. It moves through a strict lifecycle from creation to a terminal state.
Lifecycle
State machine
pending ──▶ scanned ──▶ paid (terminal)
│ │
├───────────┴──▶ expired (terminal)
├──────────────▶ failed (terminal)
└──────────────▶ cancelled (terminal)
paid ──▶ refunded / partially_refundedTransitions are one-way — a terminal payment never changes state (except a paid payment being refunded).
Create a payment
| Field | Type | Notes |
|---|---|---|
amount | string | Required. Decimal string, e.g. "1.50". |
currency | string | Required. USD or KHR. |
reference_id | string | Your order id. Returned on the payment and in webhooks. |
description | string | Optional. Shown on checkout / receipts. |
expires_in | number | Optional. Seconds until expiry (default set by the provider). |
metadata | object | Optional. Key/value pairs echoed back to you. |
POST /v1/payments
curl https://api.paykh.cambobia.com/v1/payments \
-H "Authorization: Bearer bk_test_your_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_1001" \
-d '{ "amount": "12.00", "currency": "USD", "reference_id": "order_1001" }'ℹ️ Idempotency
Send an
Idempotency-Key header on create. Retrying with the same key returns the original payment instead of creating a duplicate — safe against network retries. A conflicting reuse returns 409 idempotency_conflict.Retrieve, list, cancel
curl
# Retrieve one
curl https://api.paykh.cambobia.com/v1/payments/pay_123 \
-H "Authorization: Bearer bk_test_your_key"
# List (paginated)
curl "https://api.paykh.cambobia.com/v1/payments?limit=20" \
-H "Authorization: Bearer bk_test_your_key"
# Cancel a still-pending payment
curl -X POST https://api.paykh.cambobia.com/v1/payments/pay_123/cancel \
-H "Authorization: Bearer bk_test_your_key"Getting notified
Don’t poll in production. Register a webhook and react to payment.completed. For a live UI, the hosted checkout page streams status over SSE.