CleonPay

API: Payouts

Send money to an individual, to a card or a bank account.

A payout goes to a recipient, so a recipient is created first. That separation is deliberate: recipient details are sealed at rest and reused, and the payout request itself carries no personal data.

Create a recipient

POST /v1/payout-recipients

Stores who is being paid. Card recipients are created from a token or from a payment they already made. There is no field for a card number.

Send an Idempotency-Key header. Retrying with the same key returns the original result rather than creating a second one. See idempotency.

Body parameters

FieldTypeDescription
type
required
string card or bank_account.
first_name
required
string As held by the bank.
last_name
required
string As held by the bank.
card_token string Card recipients: a token from your tokenisation flow.
parent_payment_reference string Card recipients: pay back to the card used on an earlier payment. The bank still holds it, we hold only a reference.
iban string Bank recipients: the account, in IBAN form.
bic string Bank recipients: required outside SEPA reach.
last4 string Last four digits, for your own reporting only.
scheme string visa, mastercard or amex.
country string Two-letter ISO 3166 code.
email string Optional, used by some rails for notification.
date_of_birth string YYYY-MM-DD. Required by some rails for sanctions screening.
reference string Your own identifier for this recipient.

Request

curl https://api.cleonpay.com/v1/payout-recipients \
  -H "Authorization: Bearer ck_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "card",
    "first_name": "Sofia",
    "last_name": "Almeida",
    "country": "PT",
    "scheme": "visa",
    "last4": "4242",
    "parent_payment_reference": "order-1001"
  }'

Response

{
  "id": "6d4ff39f-72fb-44c4-9e13-9c724683d40a",
  "object": "payout_recipient",
  "type": "card",
  "scheme": "visa",
  "last4": "4242",
  "created_at": "2026-08-21T15: 02: 19.441Z"
}

A raw card number is refused by the schema, not merely discouraged. That refusal is what keeps both sides out of the heavier parts of PCI DSS.

Send a payout

POST /v1/payouts

Sends money to a recipient over the rail you choose.

Send an Idempotency-Key header. Retrying with the same key returns the original result rather than creating a second one. See idempotency.

Body parameters

FieldTypeDescription
recipient_id
required
string From the call above.
method
required
string A rail from GET /v1/payout-methods, for example card_payout or sepa_credit_transfer.
amount
required
integer Minor units.
currency
required
string Three-letter ISO 4217 code.
reference string Your own identifier. Shown on the recipient statement where the rail carries it.
metadata object Stored and returned unchanged.

Request

curl https://api.cleonpay.com/v1/payouts \
  -H "Authorization: Bearer ck_live_..." \
  -H "Idempotency-Key: payout-2026-0001" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient_id": "6d4ff39f-72fb-44c4-9e13-9c724683d40a",
    "method": "card_payout",
    "amount": 2500,
    "currency": "EUR",
    "reference": "PAYOUT-2026-0001"
  }'

Response

{
  "id": "9a2c1e77-3b41-4e0a-9f18-0c5b2d7e6a33",
  "object": "payout",
  "status": "sent",
  "amount": 2500,
  "currency": "EUR",
  "method": "card_payout",
  "recipient_id": "6d4ff39f-72fb-44c4-9e13-9c724683d40a",
  "reference": "PAYOUT-2026-0001",
  "failure": null,
  "returned": null,
  "livemode": true,
  "created_at": "2026-08-21T15: 04: 52.118Z",
  "completed_at": null
}

Retrieve a payout

GET /v1/payouts/{id}

Returns one payout. A returned payout carries a returned object with the reason the receiving bank gave.

Response

{
  "id": "9a2c1e77-3b41-4e0a-9f18-0c5b2d7e6a33",
  "object": "payout",
  "status": "returned",
  "returned": {
    "code": "account_closed",
    "reason": "Beneficiary account closed"
  },
  "completed_at": "2026-08-24T07: 31: 09.660Z"
}

returned is not failed. Failed means the money never left. Returned means it reached the recipient's bank and came back, sometimes days later, and your balance moved in between.

List payouts

GET /v1/payouts

Every payout on the account, newest first.

Query parameters

FieldTypeDescription
limit integer Between 1 and 100. Defaults to 25.
status string Filter to one status.

Response

{
  "object": "list",
  "data": [ { "id": "9a2c1e77-...", "object": "payout", "status": "completed" } ]
}

Available payout rails

GET /v1/payout-methods

The rails enabled on your account, with what each one reaches and how quickly.

Response

{
  "object": "list",
  "data": [
    {
      "method": "card_payout",
      "display_name": "Card payout",
      "recipient_type": "card",
      "typical_speed": "Instant",
      "can_be_returned": false
    }
  ]
}

On every request

HeaderDescription
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.