Creating a Payment
POST /api/v1/payments
Authorization: Bearer cp_live_…
Content-Type: application/json
Idempotency-Key: order-CLOUD-12345
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
amount |
integer | yes | Amount in Rials (IRR), no decimals. Min 10,000, max 5,000,000,000. |
currency |
string | no | Only IRR for now. Defaults to IRR. |
order_id |
string | yes | Your reference (≤ 191 chars, A-Z a-z 0-9 _ - . :). Not required to be unique; use Idempotency-Key for de-duplication. |
description |
string | no | ≤ 500 chars. Shown to the payer by some gateways. |
callback_url |
string | yes | Must match a registered callback URL. HTTPS. |
metadata |
object | no | Free-form JSON, ≤ 50 keys, ≤ 4 KB. Echoed back in responses and webhooks. See Metadata. |
{
"amount": 500000,
"currency": "IRR",
"order_id": "CLOUD-12345",
"description": "Cartino Cloud subscription",
"callback_url": "https://cartino.cloud/payment/callback",
"metadata": { "user_id": 123, "plan": "pro" }
}
Response 201 Created
{
"success": true,
"data": {
"payment_id": "PAY_01J9X4Z8K3M2N5P7Q9R1S3T5V7",
"application": "cartino-cloud",
"order_id": "CLOUD-12345",
"amount": 500000,
"currency": "IRR",
"status": "pending",
"description": "Cartino Cloud subscription",
"gateway": "zarinpal",
"payment_url": "https://payment.zarinpal.com/pg/StartPay/A0000…",
"tracking_code": null,
"card_pan_masked": null,
"failure_code": null,
"failure_reason": null,
"test": false,
"metadata": { "user_id": 123, "plan": "pro" },
"callback_url": "https://cartino.cloud/payment/callback",
"expires_at": "2026-09-14T10:30:00+03:30",
"paid_at": null,
"verified_at": null,
"created_at": "2026-09-14T10:00:00+03:30",
"updated_at": "2026-09-14T10:00:00+03:30"
}
}
payment_idis generated by Cartino Pay (PAY_+ 26 characters). Persist it with your order. The gateway's own authority/token is an internal detail you never see.payment_urlis where you send the payer. It is only present while the payment is not final.expires_at— the payer must complete the payment before this time (default 30 minutes); afterwards the payment becomesexpired.
A replayed request (same Idempotency-Key and body) returns 200 OK with the identical payment and header Idempotency-Replayed: true.
Errors
| HTTP | Code | Fix |
|---|---|---|
| 422 | INVALID_AMOUNT |
Integer within limits |
| 422 | INVALID_CURRENCY |
Use IRR |
| 422 | INVALID_CALLBACK_URL |
Register the URL with an admin / use https |
| 422 | INVALID_IDEMPOTENCY_KEY |
≤ 191 chars, A-Z a-z 0-9 _ - . : |
| 422 | VALIDATION_ERROR |
See error.details |
| 409 | IDEMPOTENCY_CONFLICT |
Same key, different body — use a new key |
| 502 | GATEWAY_NOT_CONFIGURED / GATEWAY_DISABLED |
Ask an admin to configure the application's gateway |
| 502 | GATEWAY_ERROR |
The gateway rejected the request; see message. The payment is recorded as failed. |
| 503 | GATEWAY_UNAVAILABLE |
Transient; retry with the same Idempotency-Key |
When creation fails at the gateway, the Idempotency-Key is released so a retry with the same key creates a fresh attempt.