Partners
Markdown

List a customer’s crypto orders

GET /api/v1/partner/customers/{customerId}/orders

Required scope: orders:read. Capability: payments.crypto.

Newest first. Returns only orders minted by this partner relationship — a partner never sees another partner’s orders, even though both share the merchant’s underlying account.

curl "https://www.niftipay.com/api/v1/partner/customers/pc-1/orders?limit=25" \
  -H "Authorization: Bearer <partner_api_key>"

Response 200

{
  "request_id": "req-1",
  "api_version": "2026-08-01",
  "data": {
    "orders": [
      {
        "id": "7d1dcdd4-9f3a-4c21-8f0e-2b1c9a5d4e10",
        "reference": "CRY-1042",
        "network": "ETH",
        "asset": "USDT",
        "amount": "116.751879",
        "totalToSend": "116.751879",
        "networkFees": null,
        "currency": "EUR",
        "fiatAmount": "100",
        "address": "0x49d83b0d1f2c4a6e8b7d5c3a9f1e0d2b4c6a8e70",
        "paymentUri": "ethereum:0x49d83b0d?contract=0xdAC17F&amount=116.751879",
        "qrUrl": "https://www.niftipay.com/api/qr?data=ethereum%3A0x49d83b0d",
        "status": "pending",
        "createdAt": "2026-08-27T09:12:02.923Z",
        "expiresAt": "2026-08-27T21:12:02.923Z"
      }
    ],
    "next_cursor": "b3JkOjE3NjQyMzc1MjI5MjM6N2QxZGNkZDQ"
  }
}

An empty list is 200 with [], never 404. The customer exists — “no orders yet” is a fact about the collection, not a missing resource.

Paging

?limit= defaults to 25 and caps at 100. An out-of-range value is clamped, not rejected — a partner tuning a page size should not get a 400.

?before= takes the next_cursor from a previous response. Treat it as opaque: it is a keyset cursor over (createdAt, id), and constructing one yourself will silently skip rows that share a timestamp at a page boundary.

next_cursor is issued only on a full page. A short page is the end of the list, so it comes back null. A full page that happens to be the last one gets a cursor whose next fetch is an empty page — that is the loop’s ordinary termination.

while cursor is not null:
    page = GET /customers/{id}/orders?limit=100&before=<cursor>
    cursor = page.data.next_cursor

A before we did not issue is a 400 invalid_cursor rather than a silent page one — ignoring it would turn “fetch until empty” into an infinite loop.

Two shape notes

next_cursor is snake_case; the order objects are camelCase. The order view is inherited verbatim from the merchant-internal one rather than re-shaped, so it keeps its own casing. Everything partner-native inside data is snake_case.

List rows carry qrUrl but not qrImage. The inline PNG is rendered only for single-order reads — a page of 100 would be 100 renders. Fetch the order by id, or render qrUrl yourself.

Errors

Status code Meaning
400 invalid_cursor before is not a cursor this API issued.
403 insufficient_scope Token was not minted with orders:read.
403 capability_not_enabled payments.crypto is off for this customer.
404 resource_not_found Not your customer, or the relationship was revoked.
503 temporarily_unavailable Read failed transiently; retry shortly.
500 internal_error Unknown failure. Not an invitation to retry.