NorelioDeveloper documentation

Customer export

List every buyer page by page — the cabinet's customer list with account references and totals — with a cursor, up to 100 per page, and updatedSince for catch-up sync.

GET /api/v1/customers lists your buyers page by page: the rows of the cabinet's customer list (its Clients section) — the same buyers in the same order (newest first purchase on top) and the same totals — plus the account references found on each buyer's orders and the moment the buyer last changed. Use it to fill your own database once and to keep it in sync. The partner's internal figures (commission, payout share, hold) are not in it, as in the webhooks.

The server API is for a partner whose application knows its own user: a payment is created from your server, with no button or panel on a page, and the user's state (subscriptions and purchases) is read by your own account reference. The key is the same as for the access check (API key tab in the cabinet), sent as Authorization: Bearer; the partner is identified by the key, there is no partner parameter. Rate limits are the same as for the access check: per your server's address and per key. Responses are JSON only and never cached. You can ask only about your own products and buyers: a foreign product or buyer and a non-existent one answer alike.

Request

http
GET https://app.norelio.eu/api/v1/customers?limit={1..100}&cursor={nextCursor}&updatedSince={date-time}
Authorization: Bearer {api key}

Every parameter is optional: limit — rows per page, 1 to 100 (default 100); cursor — the nextCursor of the previous page; updatedSince — an ISO 8601 date-time with a time zone (2026-03-14T00:00:00Z): only buyers whose own record or any of whose orders changed at or after that moment. A malformed value is 400 invalid_request.

Two pages
curl -s "https://app.norelio.eu/api/v1/customers?limit=2" \
  -H "Authorization: Bearer $NORELIO_API_KEY"

curl -s "https://app.norelio.eu/api/v1/customers?limit=2&cursor=eyJ0IjoiMjAyNi0wMi0wMVQxODowMzoxMS4wMDBaIiwiayI6ImNtN2s5In0" \
  -H "Authorization: Bearer $NORELIO_API_KEY"

Response

200 OK. Each row of customers:

FieldDescription
emailThe buyer's email, lower-cased as in the cabinet.
clientReferencesYour account references found on the buyer's orders, newest first, up to 50; empty when none was passed.
firstPurchaseAtThe buyer's first purchase (ISO 8601) — the order of the list.
lastPaymentAtThe last confirmed payment (ISO 8601); null when there is none.
ordersCountThe number of the buyer's orders on which money moved — paid, refunded and disputed — the same count as in the cabinet's customer list.
paidAmountThe sum of those orders, in the smallest unit of currency, without VAT — the purchases total of the cabinet's customer list.
refundedAmountHow much of it went back to the buyer, in the same units.
currencyThe currency of paidAmount and refundedAmount, three-letter code.
updatedAtWhen the buyer's record or any of their orders last changed (ISO 8601) — what updatedSince compares with.
Example response
{
  "customers": [
    {
      "email": "buyer@example.com",
      "clientReferences": [
        "acc_10294"
      ],
      "firstPurchaseAt": "2026-03-14T09:26:53.000Z",
      "lastPaymentAt": "2026-03-14T09:26:53.000Z",
      "ordersCount": 1,
      "paidAmount": 1990,
      "refundedAmount": 0,
      "currency": "EUR",
      "updatedAt": "2026-03-14T09:26:54.000Z"
    },
    {
      "email": "second@example.com",
      "clientReferences": [],
      "firstPurchaseAt": "2026-02-01T18:03:11.000Z",
      "lastPaymentAt": "2026-03-01T18:03:12.000Z",
      "ordersCount": 2,
      "paidAmount": 1980,
      "refundedAmount": 990,
      "currency": "EUR",
      "updatedAt": "2026-03-02T10:15:00.000Z"
    }
  ],
  "nextCursor": "eyJ0IjoiMjAyNi0wMi0wMVQxODowMzoxMS4wMDBaIiwiayI6ImNtN2s5In0"
}

Paging

The response is an object with customers (the rows) and nextCursor: an opaque string to pass back as cursor for the next page, null on the last one. The order is stable — by first purchase, then by an internal id — so no buyer is repeated or skipped between pages, even when several bought at the same moment.

Keeping a copy in sync

To keep a copy in sync, remember the moment you START each run and pass it as updatedSince to the next one: a buyer who changes while you are reading the pages is then picked up by the next run. Between runs, the customer.state_changed webhook tells you about each change as it happens.

Buyers changed since the start of the previous run
curl -s "https://app.norelio.eu/api/v1/customers?updatedSince=2026-03-14T00:00:00Z" \
  -H "Authorization: Bearer $NORELIO_API_KEY"

One buyer's subscriptions and purchases are in Customer state; changes as they happen, in Customer state notification.

Test mode

With the test key the export lists the buyers of your test orders, by the email of each paid, refunded or disputed test order, in the same shape and with the same paging; with the live key, real buyers only. Test buyers never appear in the cabinet's customer list. See Test mode.

Errors

An error from any API endpoint is JSON of one shape: an error object with code (one of the codes below) and message (a short English sentence). A 429 or 503 response carries a Retry-After header. The access check keeps its own, older error shape.

StatusCodeWhen
429rate_limitedtoo many requests in a row, from your address or with your key
503rate_limiter_busythe request could not be counted against the rate limits, so nothing was done; send the same request again after the number of seconds in the Retry-After header
401invalid_api_keythe key is missing or does not match
400invalid_requestthe body or the query is malformed; message says what exactly
403direct_checkout_not_enabledcreating payments from your server is not yet enabled for your account: the platform first reviews your purchase terms (the same review as for direct checkout)
404product_not_foundno product with this id belongs to your account, or it cannot be bought right now
502checkout_failedthe payment provider could not start the payment; retry later
404not_foundno such endpoint
405method_not_allowedthe endpoint does not accept that method
403test_key_requiredthe endpoint works only with the test API key (it starts with nrl_test_), and the request came with the live key
404test_order_not_foundno test order with this id belongs to your account, or it has already been deleted: test orders live for 30 days
409test_action_not_allowedthe action is not possible in the test order's current state, such as a refund of an order not yet paid or a renewal of a canceled subscription; message names the reason
409insufficient_balancethe balance is lower than the amount to debit; nothing was debited, and the response carries the current balance in the balance field next to error
422idempotency_conflicta request with this idempotency key was already processed with a different body; use a new key for a new operation. A balance debit or grant answers 422 (idempotencyKey in the body), a payment created with the Idempotency-Key header answers 409
409idempotency_in_progressa payment request with this Idempotency-Key is still being processed; send the same request again after the number of seconds in Retry-After and you get its response
404subscription_not_foundno subscription with this id belongs to your account in this mode: a live key sees only live subscriptions, a test key only test ones
Example error
{
  "error": {
    "code": "direct_checkout_not_enabled",
    "message": "Creating payments from your server is enabled after the platform has reviewed your purchase terms. Ask support from the cabinet's Messages section."
  }
}