Pagination, filters and sorting
Every list endpoint (GET /v1/payment_intents, /v1/refunds, /v1/customers, /v1/events, and so on) returns the same envelope and uses cursor pagination.
{
"object": "list",
"url": "/v1/payment_intents",
"has_more": true,
"total_count": 248,
"data": [
{
"id": "pi_01J9ZQ4V8K2M3N5P7R9T1W3Y5A",
"object": "payment_intent",
"amount": 12500,
"currency": "try",
"status": "succeeded",
"capture_method": "automatic",
"created": 1790000000,
"livemode": false
}
]
}
Cursors
| Parameter | Meaning |
|---|---|
limit |
Page size, 1 to 100, default 10. |
starting_after |
The id of the last object of the previous page; returns the next page. |
ending_before |
The id of the first object of the current page; returns the previous page. |
Lists are newest first. Fetch the next page by passing the id of the last item as starting_after, until has_more is false:
curl "https://pay.example.com/v1/payment_intents?limit=50&starting_after=pi_01J9ZQ4V8K2M3N5P7R9T1W3Y5A" \
-H "Authorization: Bearer sk_sandbox_YOUR_KEY"
Cursors are object ids, so they stay valid while new objects are created and when the object stops matching your filters. An id that belongs to another merchant is 404 resource_missing.
Totals
A total costs an extra count, so it is opt-in. Add include[]=total_count and the list carries total_count (the number of objects that match your filters). The count is bounded at 10000: when more than that match, total_count is 10000 and total_count_capped is true. Any other include[] value is a 400.
curl -g "https://pay.example.com/v1/refunds?status=succeeded&include[]=total_count" \
-H "Authorization: Bearer sk_sandbox_YOUR_KEY"
Filters
Filters combine with AND. A filter that is not valid for the endpoint, or a malformed value, returns 400 parameter_invalid with param naming it. Filter values are never echoed back.
- Enums accept one value, a comma list (
status=succeeded,canceled) or repeatedstatus[]=…. - Ranges use
name[gte]andname[lte](and[gt],[lt]where documented). Values are unix seconds forcreated, minor units for amounts,YYYY-MM-DDfor dates.gteabovelteis an error. - Booleans are exactly
trueorfalse.
| Resource | Filters |
|---|---|
| Payments | status, `amount[gte |
| Refunds | payment_intent, status, method, `amount[gte |
| Payouts | status, `created[gte |
| Top-ups | status, `created[gte |
| Disputes | status, `evidence_due_by[gte |
The exact parameters of every endpoint are in the API reference.
Search
q on payments, and GET /v1/search?q=… across payments, refunds, customers and disputes, match only what is indexed: an object id (pi_, att_, re_, cus_, dp_), an exact customer e-mail (case-insensitive), or the start of a payment description. Substring search is not supported; use metadata[key]=value to find payments by your own reference. A card number in q is refused with 400 card_data_in_url.
Sorting
Add sort=<key> for ascending or sort=-<key> for descending order. The default is -created. Keys: created, amount, plus evidence_due_by for disputes and arrival_date for payouts. Cursors stay stable under any sort: rows with equal sort values are neither skipped nor repeated.
Expanding related objects
Some fields hold an id by default. Add expand[]=<field> to receive the whole object, for example expand[]=latest_attempt, expand[]=attempts, expand[]=customer or expand[]=line_items on a payment:
curl -g "https://pay.example.com/v1/payment_intents/pi_01J9ZQ4V8K2M3N5P7R9T1W3Y5A?expand[]=customer&expand[]=line_items" \
-H "Authorization: Bearer sk_sandbox_YOUR_KEY"