API: Payments
Create a payment, follow it to settlement, and close it if the customer walks away.
On this page
POST Create a payment/v1/payments
GET
Retrieve a payment
/v1/payments/{id}
GET
List payments
/v1/payments
POST
Cancel a payment
/v1/payments/{id}/cancel
GET
Refunds against a payment
/v1/payments/{id}/refunds
Create a payment
Creates a payment and returns the URL to send the customer to. The method decides where that URL goes: a bank selector, a wallet, or a page showing a reference to pay at a cash machine.
Send an Idempotency-Key header. Retrying
with the same key returns the original result rather than creating a
second one. See idempotency.
Body parameters
| Field | Type | Description |
|---|---|---|
methodrequired |
string | One of the values from payment methods, for example ideal or visa. |
amountrequired |
integer | In minor units. €10.50 is 1050. A decimal is rejected, not rounded. |
currencyrequired |
string | Three-letter ISO 4217 code. Must be one the method supports. |
success_urlrequired |
string | Where the customer returns after paying. HTTPS only. Landing here is not proof of payment; the webhook is. |
error_urlrequired |
string | Where the customer returns after a failure or a cancellation. |
country |
string | Two-letter ISO 3166 code. Required by methods that are country-bound, and used for routing where it is not. |
reference |
string | Your own identifier for the order. Returned on every event and searchable through the list endpoint. |
customer |
object | Optional email, first_name, last_name and reference. Some methods require an email; the error names the field if so. |
metadata |
object | Arbitrary keys and values stored with the payment and returned unchanged. Never sent to the bank. |
Request
curl https://api.cleonpay.com/v1/payments \
-H "Authorization: Bearer ck_live_..." \
-H "Idempotency-Key: order-1001" \
-H "Content-Type: application/json" \
-d '{
"method": "ideal",
"amount": 1050,
"currency": "EUR",
"country": "NL",
"reference": "order-1001",
"success_url": "https://shop.example.com/thanks",
"error_url": "https://shop.example.com/failed"
}'
Response
{
"id": "3743881d-0fce-416c-b3de-8bc3f5d414b1",
"object": "payment",
"status": "awaiting_customer",
"amount": 1050,
"currency": "EUR",
"method": "ideal",
"country": "NL",
"reference": "order-1001",
"redirect_url": "https://ideal.example/pay/3743881d",
"customer": {
"email": "customer@example.com",
"first_name": "Sofia",
"last_name": "Almeida",
"reference": "cust_88213"
},
"failure": null,
"livemode": true,
"metadata": { "cart": "c_9931" },
"authorized_at": null,
"settled_at": null,
"cancelled_at": null,
"created_at": "2026-08-21T13: 15: 24.881Z",
"updated_at": "2026-08-21T13: 15: 24.881Z"
}
Send the customer to
redirect_url. It is single use and expires. Do not
store it or email it later.
Retrieve a payment
Returns the current state of one payment. Use it to reconcile, not to poll: the webhook arrives sooner and costs you nothing.
Response
{
"id": "3743881d-0fce-416c-b3de-8bc3f5d414b1",
"object": "payment",
"status": "awaiting_customer",
"amount": 1050,
"currency": "EUR",
"method": "ideal",
"country": "NL",
"reference": "order-1001",
"redirect_url": "https://ideal.example/pay/3743881d",
"customer": {
"email": "customer@example.com",
"first_name": "Sofia",
"last_name": "Almeida",
"reference": "cust_88213"
},
"failure": null,
"livemode": true,
"metadata": { "cart": "c_9931" },
"authorized_at": null,
"settled_at": null,
"cancelled_at": null,
"created_at": "2026-08-21T13: 15: 24.881Z",
"updated_at": "2026-08-21T13: 15: 24.881Z"
}
List payments
Returns payments newest first, with keyset pagination that stays stable while new payments arrive.
Query parameters
| Field | Type | Description |
|---|---|---|
limit |
integer | Between 1 and 100. Defaults to 25. |
status |
string | Filter to one status, for example settled. |
method |
string | Filter to one payment method. |
reference |
string | Exact match on your own reference. |
created_before |
string | ISO 8601 timestamp. Pass the next_cursor from the previous page to continue. |
Request
curl "https://api.cleonpay.com/v1/payments?status=settled&limit=50" \
-H "Authorization: Bearer ck_live_..."
Response
{
"object": "list",
"data": [ { "id": "3743881d-...", "object": "payment", "status": "settled" } ],
"has_more": true,
"next_cursor": "2026-08-21T13: 15: 24.881Z"
}
Cancel a payment
Closes a payment the customer abandoned. Only valid while the payment is created or awaiting_customer. After the bank has authorised it, refund instead.
Response
{
"id": "3743881d-0fce-416c-b3de-8bc3f5d414b1",
"object": "payment",
"status": "cancelled",
"failure": {
"code": "cancelled_by_merchant",
"message": "Cancelled by the merchant."
},
"cancelled_at": "2026-08-21T13: 41: 02.104Z"
}
Cancelling a payment that is already
authorised returns 422 cannot_cancel. The distinction
matters: a cancellation never reaches the customer's statement, a
refund does.
Refunds against a payment
Every refund raised against one payment, newest first.
Response
{
"object": "list",
"data": [
{
"id": "b1c8b0a2-2f19-4a2e-9d51-6e9f3a1c7d40",
"object": "refund",
"payment_id": "3743881d-0fce-416c-b3de-8bc3f5d414b1",
"amount": 500,
"currency": "EUR",
"status": "settled",
"created_at": "2026-08-22T09: 04: 11.002Z"
}
]
}
On every request
| Header | Description |
|---|---|
Authorization |
Bearer <api key>. The key decides whether you are
in sandbox or live; the host is the same either way. |
Content-Type |
application/json on every request with a body. |
Idempotency-Key |
On every creating request. Up to 255 characters, unique per operation, valid for 24 hours. |
Errors follow one shape across every endpoint, described in errors.