NorelioDeveloper documentation

Test mode

Go through the whole integration without money: the test API key, a test payment page with Pay and Decline, the same webhooks with test: true, test subscriptions and credits, refund, dispute and renewal actions from the cabinet or the API, and why test orders never touch the partner's money.

Test mode lets you — or your coding agent — go through the whole integration without money: create a payment, "pay" it, receive the webhook, read the customer state, check access, then trigger a refund, a dispute and a subscription renewal. Everything runs through the same endpoints, the same webhook body and the same signature as a real payment; what differs is the key you send and where the buyer "pays".

The test key

Issue the test key in the cabinet under API and webhooks → API key, in the "Test key" panel; it starts with nrl_test_ and is shown once, like the live key (nrl_live_…; keys issued before test mode existed have no prefix and keep working as live keys). Send it as Authorization: Bearer to the same endpoints. The key decides the mode: a request with the test key creates test payments and reads test data only; a request with the live key never sees a test order, and the test key never sees a live one. There is no "mode" parameter.

A test payment

POST /api/v1/checkouts with the test key takes the same body and runs the same checks as a live payment — your own product, a required clientReference, exactly one of packageId or amount for a top-up — but needs no platform permission (no 403 direct_checkout_not_enabled), no approved moderation and no payment provider: the product only needs a price, a subscription its period, a top-up its settings and the webhook delivery method. The response has the same fields with test: true, the order id starts with test_, and url leads to a Norelio test page on the payment domain (/test-checkout/continue): a large "TEST MODE — no real money" banner, the product and the price, a switch between "a buyer in the EU" (VAT 21% added as a fixed example, not a Stripe Tax calculation) and "outside the EU" (no VAT), and two buttons: Pay and Decline. The address is single-use and expires like a live one; open it in a browser.

Example response with the test key
{
  "id": "test_k3m2p9q7r4s1",
  "url": "https://pay.lis-system.eu/test-checkout/continue?order=test_k3m2p9q7r4s1&key=k4Xw1QmR9zL2nT8vB0cY7pH5sJ3eF6gD",
  "expiresAt": "2026-03-14T10:26:53.000Z",
  "clientReference": "acc_10294",
  "warnings": [],
  "credits": null,
  "creditsUnit": null,
  "test": true
}

Pay runs the same after-payment path a real order runs: the order.paid webhook with test: true, the same body and signature and an eventId starting with test_ (only for a product delivered by webhook — other delivery methods deliver nothing in test mode: no codes or files are taken from stock); a test subscription with the access date computed by the same period arithmetic; the credits of a top-up in the webhook; the return to your site by the same return URL rules. Decline marks the order declined and sends nothing. What never happens: no buyer emails, no buyer in the partner's "Customers", no access in "Subscribers", no provider call.

Example webhook for a test order
{
  "version": 1,
  "event": "order.paid",
  "test": true,
  "productId": "prod_1a2b3c",
  "customerEmail": "buyer@example.com",
  "paymentId": "test_k3m2p9q7r4s1",
  "amount": 1990,
  "currency": "EUR",
  "taxAmount": 418,
  "occurredAt": "2026-03-14T09:26:53.000Z",
  "accessValidUntil": null,
  "clientReference": "acc_10294",
  "credits": null,
  "creditsUnit": null,
  "refundedAmount": null,
  "eventId": "test_cm9a1b2c30009xy4z5w6v7u8t"
}

Test orders never touch money

A test order never enters any money figure of the partner or the platform: not the payout base, not "available / on hold / earned", not the statement, not the summaries, not reconciliation, not CSV exports, not VAT reports. Test orders live in their own tables, separate from real orders, so nothing that reads money can read them even by mistake. The cabinet shows them only on the "Test orders" tab under API and webhooks, and the delivery log marks their notifications "Test".

Trigger refunds, disputes and subscription events

Every event of the webhook catalog can be triggered on a test order — from the "Test orders" tab in the cabinet (a button per action) or with the test key: POST /api/v1/test/orders/{id}/{action}, where action is one of the values below. Each action changes the test order the way the real event would and sends the real event with test: true. Actions on a subscription are only possible on the order that started it; a test subscription renews only by the renew action, never by time.

ActionWhat it does
refund-partialA partial refund: the body carries amount — an integer in the units of amount (without VAT), smaller than the unrefunded remainder. Sends order.refunded_partial with refundedAmount; for a subscription the access date is shortened in proportion, like a real refund.
refund-fullA refund of the whole unrefunded remainder: order.refunded_full with refundedAmount equal to the remainder; a test subscription's access closes without grace, like after a real full refund.
dispute-openThe buyer disputed the payment: the order becomes disputed, order.dispute_opened is sent. Refunds are not possible while the dispute is open.
dispute-closeThe dispute is resolved in the seller's favour: the order returns to paid (or refunded, if refunds came before), order.dispute_resolved is sent.
renewA successful recurring charge: a NEW test order for the next period, the access date moves to its end, subscription.renewed is sent with accessValidUntil. Possible while the subscription is active or past due.
payment-failedA failed charge the provider would retry: the subscription becomes past due, subscription.payment_failed is sent with accessValidUntil; access is not extended.
cancelThe buyer canceled: no further renewals, access stays until the paid date, subscription.canceled is sent with accessValidUntil.
endThe subscription ended: subscription.ended is sent with accessValidUntil; no further actions on it.
Example: a partial refund
curl -s -X POST "https://app.norelio.eu/api/v1/test/orders/test_k3m2p9q7r4s1/refund-partial" \
  -H "Authorization: Bearer $NORELIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"amount":500}'

The response, with these fields:

FieldDescription
idThe id of the test order the event is about — for renew, the id of the NEW renewal order.
testAlways true.
statusThe order's status after the action: paid, refunded or disputed.
refundedAmountThe total refunded on the order so far, in the units of amount.
subscriptionThe test subscription after the action (id, status, validUntil, currentPeriodEnd, cancelAtPeriodEnd), or null for a one-off or top-up order.
eventThe event the action produced: event (the catalog value), eventId (the number in the webhook body, starting with test_; null when no notification was sent) and delivery — delivered, pending (retries follow), needs_action (all attempts failed) or not_applicable (the product is not delivered by webhook or the webhook address is not set).
Example response
{
  "id": "test_k3m2p9q7r4s1",
  "test": true,
  "status": "refunded",
  "refundedAmount": 500,
  "subscription": {
    "id": "test_sub_7d4e2f9a",
    "status": "active",
    "validUntil": "2026-04-06T15:11:53.000Z",
    "currentPeriodEnd": "2026-04-14T09:26:53.000Z",
    "cancelAtPeriodEnd": false
  },
  "event": {
    "event": "order.refunded_partial",
    "eventId": "test_cm9a1b2c30009xy4z5w6v7u8t",
    "delivery": "delivered"
  }
}

Reading with the test key

GET /api/v1/customers/state and GET /api/public/access-check with the test key answer from test orders and test subscriptions only, in the same response shape: purchases are the paid, refunded and disputed test orders, subscriptions the test subscriptions, and the access check applies the same grace rule to a test subscription's validUntil. With the live key the same requests answer from real data only.

Lifetime and limits

Test orders, test subscriptions and their deliveries are deleted 30 days after creation. A test subscription does not renew by time and sends no reminders. There are no test keys for Stripe or PayPal here: test mode is Norelio's own page, not a provider's sandbox. The errors test_key_required (an action endpoint called with the live key), test_order_not_found and test_action_not_allowed are described with the other error codes.

Going live

When the integration works in test mode, issue the live key on the same tab and replace the value of NORELIO_API_KEY: the endpoints, the body and the webhook are the same. Only a live payment still needs the platform's permission for creating payments from your server and an approved product.

In full: Create a payment from your server, Webhooks, Customer state, Access check.