Create a payment intent
Ask one of your terminals to take a payment (server-driven checkout, for example from your POS or ordering system).
/v1/payment_intentsscope payments:writeThe terminal picks the intent up, shows the amount and settles it when the customer taps; follow the outcome with webhooks (payment_intent.*, payment.succeeded) or by retrieving the intent. Live mode needs an approved business verification.
Body parameters
amountintegerrequiredAmount to charge, in USDC atoms (6 decimals:
2500000= 2.50 USDC). The payer also pays the network fees on top. Between 1 and 1000000000000.terminalstringrequiredThe terminal that takes the payment (
tml_…, fromGET /v1/terminals).order_idstringYour order reference, 1-8 characters
A-Z a-z 0-9 - _(it is written on-chain with the settlement and must be unique per account and mode). Generated when omitted.descriptionstringShown on the terminal while it waits for the tap. Up to 500 characters.
metadataobjectUp to 20 key/value pairs (keys 1-40 characters of
A-Z a-z 0-9 _ . -, string values up to 500 characters) returned unchanged. Never store secrets or personal data here.expires_inintegerdefault 120Seconds until the intent expires if nobody pays it (30-600). After that it is
canceledwithcancellation_reason: expired.
Headers
ZyloPay-VersionstringPin the request to an API version (2026-09-28). Defaults to the version the API key was created with.
Idempotency-KeystringrequiredRequired. A unique key per operation (a UUID v4). Retrying with the same key and body returns the first response (
Idempotent-Replayed: true); a different body is refused with 409idempotency_key_reused. Keys are kept 48 hours.
Returns
HTTP 201 with the payment intent object.
Errors
| Status | Meaning |
|---|---|
400 | Invalid request (invalid_request_error / idempotency_error). |
401 | Missing, invalid, expired or revoked API key (authentication_error). |
403 | The key lacks the scope, the IP is not allowed, or the account is disabled (permission_error). |
409 | Conflict: idempotency key reused or in progress, or the object is in the wrong state. |
429 | Rate limit reached for this key (rate_limit_error); see Retry-After. |
500 | Internal error (api_error). Retry with the same Idempotency-Key. |
Branch on error.code. Every code is listed in error codes.
Example request
curl https://zylopay-api.fly.dev/api/v1/payment_intents \
-H "Authorization: Bearer $ZYLOPAY_SECRET_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"amount": 2500000,
"terminal": "tml_ZP-4821-K",
"order_id": "A7K2Q9XZ",
"description": "Table 12",
"metadata": {
"pos_order": "48213"
},
"expires_in": 120
}'Example response
{
"id": "pi_3f2c9e1a7b6d4c0e9f8a1b2c3d4e5f60",
"object": "payment_intent",
"livemode": false,
"amount": 2500000,
"currency": "usdc",
"status": "requires_payment_method",
"terminal": "tml_ZP-4821-K",
"order_id": "A7K2Q9XZ",
"description": "Table 12",
"metadata": {
"pos_order": "48213"
},
"source": "api",
"payment": null,
"tx_hash": null,
"next_action": null,
"last_payment_error": null,
"cancellation_reason": null,
"canceled_at": null,
"network": "testnet",
"expires_at": "2026-09-28T14:04:11.000Z",
"created": "2026-09-28T14:02:11.000Z"
}