Checkouts
A checkout is a payment link you send to a customer. Webhooks fire at each stage of the checkout lifecycle: checkout.created, checkout.paid (payment detected on-chain — instant, ideal for POS), checkout.completed (confirmed + settled to your balance, ~1 min later), checkout.refunded, checkout.cancelled, and checkout.expired.
Object
POST /v1/checkouts and GET /v1/checkouts/{id} return the full checkout object with payment info:
{
"id": "uuid",
"merchant_id": "uuid",
"title": "Order #1234",
"description": "Premium plan — 1 year",
"amount": 10000000,
"currency": "USDC",
"method": "any",
"status": "active",
"hosted_url": "https://pay.dpt.xyz/checkout/uuid",
"reference": "order-1234",
"customer_id": "uuid",
"paid_amount": null,
"paid_at": null,
"payer_address": null,
"refunded_amount": 0,
"refund_status": null,
"reseller_id": "uuid | null",
"reseller_fee": 0,
"platform_fee": 0,
"expires_at": "2026-04-01T00:00:00Z",
"created_at": "2026-03-16T10:00:00Z",
"updated_at": "2026-03-16T10:00:00Z",
"crypto_chains": [
{
"chain": "Ethereum",
"address": "0xabc...",
"tokens": [
{ "name": "USDC", "contract": "0x..." },
{ "name": "USDT", "contract": "0x..." }
]
}
],
"fiat": {
"session_url": "https://checkout.tazapay.com/...",
"success_url": "https://your-site.com/success",
"cancel_url": "https://your-site.com/cancel"
}
}| Field | Description |
|---|---|
hosted_url | DPT-hosted payment page. Share this with your customer to let them pay via the DPT UI |
payer_address | Wallet address the customer paid from. Populated once the checkout is paid via crypto; null for fiat checkouts or unpaid checkouts. Used as the default refund destination |
crypto_chains | One entry per chain with the deposit address and supported tokens. Empty if method is "fiat" |
fiat | Tazapay-hosted fiat payment URL and redirect links. null if method is "crypto" |
GET /v1/checkouts(list) returns the base checkout object withoutcrypto_chainsorfiat.
Status values: active | paid | completed | partially_refunded | refunded | expired | cancelled
paid= payment detected.completed= confirmed and settled to your balance.partially_refunded= at least one partial refund issued.refunded= fully refunded.
Refund status values: null (not refunded) | partially_refunded | refunded
Create Checkout
POST /v1/checkoutsBody
| Field | Type | Required | Description |
|---|---|---|---|
title | string | ✓ | Short label shown on the payment page |
description | string | Extended description | |
amount | integer | Amount in 6dp. Omit for open-amount checkouts | |
currency | string | USDC, USDT, USD, etc. Default: USDC | |
method | string | crypto (default), fiat (coming soon), or any (coming soon). | |
chains | string[] | Crypto chains to generate deposit addresses for (e.g. ["Ethereum", "Solana"]). Crypto method only. | |
reference | string | Your own order/reference ID. Must be unique per merchant — submitting a duplicate reference returns a 400 error, making it a safe idempotency key | |
success_url | string | Redirect URL after successful payment (fiat method) | |
cancel_url | string | Redirect URL on cancellation (fiat method) | |
expires_at | datetime | ✓ | ISO 8601 expiry time. Unpaid checkouts expire automatically |
customer_id | uuid | Attach an existing customer | |
customer_name | string | Create/attach customer inline | |
customer_email | string | ||
customer_country | string | ISO 3166-1 alpha-3 (e.g. SGP, USA) | |
merchant_id | uuid | Reseller only. Create this checkout on behalf of another merchant. See Reseller |
Example
curl -X POST https://api-test.dpt.xyz/v1/checkouts \
-H "Authorization: Bearer dptb_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Order #1234",
"amount": 50000000,
"currency": "USDC",
"customer_email": "[email protected]"
}'Response 200
Returns the full Checkout object including hosted_url, crypto_chains, and fiat.
List Checkouts
GET /v1/checkoutsReturns an array of checkout objects ordered by creation date (newest first).
Get Checkout
GET /v1/checkouts/{id}Cancel Checkout
DELETE /v1/checkouts/{id}Cancels an active checkout. Returns 204 No Content.
Refund Checkout
POST /v1/checkouts/{id}/refundRequires owner or admin role. Can be called multiple times for partial refunds. Only checkouts with status paid, completed, or partially_refunded can be refunded.
Body
| Field | Type | Required | Description |
|---|---|---|---|
amount | integer | Amount to refund in 6dp. Omit to refund the full remaining balance | |
reason | string | Optional reason memo, included in the webhook payload | |
receiver | string | Customer wallet address to send the refund to. Crypto only; ignored for fiat. If omitted, the refund is sent to the wallet the customer originally paid from. Required only if the payer address was not recorded (checkouts created before this feature was added) | |
gas_fee_payer | string | "merchant" to absorb the on-chain gas fee yourself. Omit (or any other value) to deduct gas from the refund amount (customer receives less). Crypto only; has no effect on fiat refunds |
Gas fee (crypto checkouts)
Every on-chain refund incurs a network gas fee denominated in the checkout currency (USDC/USDT). You control who absorbs it:
gas_fee_payer | Customer receives | Your balance debited |
|---|---|---|
| omitted (default) | refund_amount − gas_fee | proportional share of refund_amount − gas_fee |
"merchant" | refund_amount (full) | proportional share of refund_amount + gas_fee |
The gas fee is calculated as: network_base_fee + refund_amount × commission_rate. If the refund amount is too small to cover the gas fee, the request is rejected with a 400 error.
Fee handling
When you receive a checkout payment, platform fees are held in a 7-day window before being distributed to resellers and DPT. This affects refunds:
- Within 7 days of payment — fees are still held. A refund claws back a proportional share of the held fees alongside your balance, so you only pay back your net portion. Your stored
reseller_feeandplatform_feeon the checkout are reduced accordingly. - After 7 days (or once fees are released) — fees have already been distributed. The full refund amount is debited entirely from your available balance. Reseller and platform fees are not reversed.
Partial refunds
You may call this endpoint multiple times until refunded_amount reaches paid_amount. Each call advances refund_status:
- First partial refund →
refund_status: "partially_refunded",statusunchanged - Subsequent partial refunds → same
- Final refund that reaches the full paid amount →
refund_status: "refunded",status: "refunded"
Example — full refund, merchant pays gas (receiver auto-detected)
curl -X POST https://api-test.dpt.xyz/v1/checkouts/uuid/refund \
-H "Authorization: Bearer dptb_..." \
-H "Content-Type: application/json" \
-d '{
"gas_fee_payer": "merchant"
}'Example — partial refund with explicit receiver
curl -X POST https://api-test.dpt.xyz/v1/checkouts/uuid/refund \
-H "Authorization: Bearer dptb_..." \
-H "Content-Type: application/json" \
-d '{
"amount": 25000000,
"receiver": "0xCustomerWalletAddress",
"reason": "Partial cancellation"
}'Response
200 OK — refund accepted. Returns the updated checkout status:
{
"id": "uuid",
"status": "partially_refunded",
"refund_status": "partially_refunded",
"refunded_amount": 25000000,
"refund_fee": 500000,
"remaining_amount": 75000000
}| Field | Description |
|---|---|
status | Overall checkout status: paid / completed / partially_refunded / refunded |
refund_status | partially_refunded until the full paid amount is returned, then refunded |
refunded_amount | Cumulative amount refunded so far (in 6dp) |
refund_fee | On-chain gas fee charged for this refund (in 6dp). 0 for fiat checkouts |
remaining_amount | Amount still refundable after this refund (in 6dp). 0 when fully refunded |
400 Bad Request — the refund cannot be processed. Body:
{ "error": "reason" }| Reason | Description |
|---|---|
Cannot refund a checkout with status '...' | Checkout is not in a refundable state |
Checkout already fully refunded | Nothing left to refund |
Invalid refund amount. Max refundable: ... | Amount is zero, negative, or exceeds the remaining balance |
Refund amount too small to cover gas fee (gas: ...) | Crypto only — refund is too small after gas deduction |
Merchant balance insufficient to cover refund (required: ..., available: ...) | Your available balance is too low to fund this refund |
A checkout.refunded webhook fires after each successful refund.
