Utopia PaymentsDocs
Payments

List payments

Lists payments, newest first, including every subscription renewal. Filter by `status`, by the customer who paid, or by the checkout session a payment came from. One page carries `items`, `has_more` and `next_cursor`; pass `next_cursor` back as `cursor` for the next page. A page is read from a fixed point in the list, so payments arriving while you walk it do not shift the pages still ahead of you. Only payments belonging to the key's merchant and mode are listed.

GET
/payments

Lists payments, newest first, including every subscription renewal. Filter by status, by the customer who paid, or by the checkout session a payment came from. One page carries items, has_more and next_cursor; pass next_cursor back as cursor for the next page. A page is read from a fixed point in the list, so payments arriving while you walk it do not shift the pages still ahead of you. Only payments belonging to the key's merchant and mode are listed.

Authorization

secretKey
AuthorizationBearer <token>

Your secret key: sk_live_… or sk_test_….

In: header

Query Parameters

limit?integer

How many records to return in one page: 1 to 100, and 20 when left out. Asking for more than 100 is refused with INVALID_REQUEST.

Range1 <= value <= 100
Default20
cursor?string

The next_cursor of the previous page; leave it out for the first page. A cursor marks the record the next page starts after, so records created while you walk the list never shift the pages you have not read yet. Anything the API did not issue is refused with INVALID_CURSOR.

status?string

Only payments in this status.

Value in

  • "processing"
  • "succeeded"
  • "failed"
  • "refunded"
  • "partially_refunded"
customer_id?string

Only payments from this customer, by cus_ id.

Match^cus_[0-9a-f]{32}$
checkout_session_id?string

Only the payments taken through this checkout session, by cks_ id.

Match^cks_[0-9a-f]{32}$

Response Body

application/json

application/json

application/json

curl -X GET "https://example.com/payments"
{  "items": [    {      "object": "payment",      "payment_id": "pay_7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d",      "status": "succeeded",      "total_amount": 34900,      "refunded_amount": 0,      "fee_amount": 3012,      "net_amount": 31888,      "currency": "AED",      "description": "Pro course",      "customer": {        "customer_id": "cus_2c4e6a8b0d1f4a3c5e7b9d1f3a5c7e9b",        "name": "Nour Al Abbas",        "email": "nour.alabbas@example.com",        "phone_number": "+971501234567"      },      "checkout_session_id": "cks_9b1e44a0c3d24f6e8a7b5c2d1e0f9a8b",      "subscription_id": null,      "billing_reason": "payment",      "metadata": {        "order_id": "1001"      },      "livemode": true,      "created_at": "2026-09-14T09:58:12.000Z",      "paid_at": "2026-09-14T10:00:00.000Z"    },    {      "object": "payment",      "payment_id": "pay_0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e",      "status": "succeeded",      "total_amount": 9900,      "refunded_amount": 0,      "fee_amount": 962,      "net_amount": 8938,      "currency": "AED",      "description": "Pro plan",      "customer": {        "customer_id": "cus_2c4e6a8b0d1f4a3c5e7b9d1f3a5c7e9b",        "name": "Nour Al Abbas",        "email": "nour.alabbas@example.com",        "phone_number": "+971501234567"      },      "checkout_session_id": null,      "subscription_id": "sub_4e8f1a6b2c7d3e9f0a5b1c6d2e7f3a8b",      "billing_reason": "subscription_cycle",      "metadata": {},      "livemode": true,      "created_at": "2026-09-01T10:00:00.000Z",      "paid_at": "2026-09-01T10:00:04.000Z"    }  ],  "has_more": true,  "next_cursor": "eyJ0IjoiMjAyNi0wOS0wMVQxMDowMDowMC4wMDAwMDBaIiwiaWQiOiIwYjFjMmQzZS00ZjVhLTZiN2MtOGQ5ZS0wZjFhMmIzYzRkNWUifQ"}

Retrieve a payment GET

Returns one payment: what was charged, what has been refunded, Utopia's fee, what you keep (`net_amount`), who paid, and the checkout session or subscription it belongs to. Read it before fulfilling an order — the parameters appended to your `return_url` are only a hint — and after a `payment.succeeded` event when you would rather trust the API than the delivery. `fee_amount` and `net_amount` are `null` while a payment is processing and if it failed. A refund, made with `POST /payments/{id}/refunds` or from the dashboard, shows up here in `status` and `refunded_amount`.

Refund a payment POST

Gives back all that is left of a succeeded payment, or `amount` of it in the payment's minor unit, to the card it was paid with. Answers the payment once the refund is recorded: `status` is `refunded` or `partially_refunded` and `refunded_amount` has grown, and a `refund.succeeded` event goes out. Utopia's fee is not returned, so `net_amount` can fall below zero. A live refund is drawn on your balance in the payment's currency and is refused while that balance does not cover it (`409 INSUFFICIENT_BALANCE`). More than what is left of the payment is refused (`400 AMOUNT_TOO_LARGE`), as is a payment that has not succeeded or is refunded already (`409 NOT_REFUNDABLE`, `ALREADY_REFUNDED`). Some payments can be refunded only in full: one charged in the customer's own currency (`409 FULL_REFUND_ONLY`), and some payments made today, until they settle overnight (`409 NOT_SETTLED`; a full refund is possible at once). When the card processor cannot be reached the refund is not made (`502 REFUND_FAILED`); try again later. The card holder usually sees the money back within a few working days, depending on their bank. Send `Idempotency-Key` so a retried request does not refund twice.