On its way…
Your store's orders go straight to a fulfilment centre — and every status streams back, signed, to the PIN at the door.
REST + JSON · x-api-key auth · idempotent writes · HMAC-signed webhooks
POST /merchant-api/v1/ordersx-api-key: rlk_9f2c4e81…{"customer_name": "Amaka Okafor","delivery_address": "12 Allen Ave, Ikeja","external_ref": "shop-6c2a","items": [{ "sku": "rose-glow", "quantity": 2 }]}→ 201 Created · "order_number": "RLY-000231"
Base URL https://api.relayapp.ng/merchant-api — JSON in, JSON out, your key in x-api-key on every request.
Create an order. Priced from your Relay catalogue, idempotent on external_ref, straight onto the centre's board.
Fetch one order — by Relay id or your own external_ref — with every timestamp from created to delivered.
The fulfilment centres your store is linked to.
Products stocked at a centre, with live stock counts.
The same catalogue grouped by variant — options and stock per SKU.
Every delivery area a centre serves, with the fee and ETA for each.
Fee, ETA and stock across up to ten centres in one call — in development. v1 is the live order path today.
Networks flake and jobs double-fire. Relay dedupes on the external_ref you pass: the retry returns the original order with idempotent_replay: true — a 200, not a second parcel. Safe from any retry queue.
POST /v1/orders "external_ref": "shop-6c2a"→ 201 Created "order_number": "RLY-000231"# the network flakes — your worker retriesPOST /v1/orders "external_ref": "shop-6c2a"→ 200 OK "idempotent_replay": true
// x-relay-timestamp unix seconds// x-relay-signature-v2 hex hmacconst expected = createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");timingSafeEqual(expected, signatureV2)
One event — order.status_changed — fires on every transition of every order your key created. Verify the signature before you trust the payload.
pending → accepted → assigned → picked_up → in_transit → deliveredfailed · cancelled · declined
Every error body is { error, code } — a sentence for your logs, a constant for your code.
Key missing, malformed or revoked.
Past 60 requests a minute on this key — back off and retry.
Your store isn't linked to that centre.
An item is missing its SKU or quantity.
An item sold out between quote and commit.
The address isn't in any area the centre serves.
The delivery quote passed its ten-minute window.
The fee you passed no longer matches the area's fee.
No order with that id or external_ref.
Settings → API keys, self-serve. No sales call, no invoice — the API is free for merchants, at 60 requests a minute per key.
One key per service or environment — name each for what it does.
The full rlk_ key appears exactly once at creation. After that, only the prefix.
Every key shows the last time it was used.
Revoke takes effect on the very next request. No propagation delay.
Merchant, not a developer? Send yours this page and a key — it's the whole brief.
Create a key, point your checkout at the API, and watch the statuses land — through to the PIN at the door.