Webhooks
Receive push notifications when an order changes status, instead of (or in addition to) polling.
Setup
Webhook endpoints are configured per partner — contact support@n.exchange with:
- your HTTPS endpoint URL,
- the event type you want: order status changes and/or KYC status changes,
- the payload API version — request v2 so payloads match the v2 REST responses (v1 remains the default for legacy configurations),
- optionally, a signing secret for HMAC verification (recommended).
Delivery
POSTto your URL withContent-Type: application/json.- One delivery attempt per status change with a 5-second timeout — respond
2xxfast (enqueue internally; don't process synchronously). - No automatic retry on failure. Webhooks are a latency optimization, not a source of truth: keep a reconciliation sweep via
GET /orders/{unique_reference}/to catch missed deliveries. - Endpoints failing persistently (error rate ≥ 50% over the monitoring window) are auto-disabled; re-enabling is manual via support. Monitor your endpoint's health.
Payload
For order-status events with v2 payload version, the body is the same shape as GET /orders/{unique_reference}/ (the OrderV2 detail representation), plus a top-level delivery-deduplication id:
{
"id": "wh_1f4a9c2e7b3d48f0a1c2e7b3d48f0a1c",
"unique_reference": "ABCDEF123456",
"created_on": "2026-05-18T10:15:30Z",
"side": "BUY",
"status": "PAID",
"deposit_amount": "500.00000000",
"withdraw_amount": "0.01061111",
"deposit_currency": "USDTERC",
"withdraw_currency": "BTC",
"deposit_address": "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
"deposit_address_extra_id": "",
"withdraw_address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"withdraw_address_extra_id": "",
"refund_address": "",
"refund_address_extra_id": "",
"payment_window_minutes": 60,
"fixed_rate_deadline": "2026-05-18T11:15:30Z",
"rate": "45000.00000000",
"deposit_transaction": "8a3f4c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f8c2d9e1b6a5f",
"withdraw_transaction": ""
}
idis stable per (order, status change) — use it to deduplicate; the same event redelivered carries the sameid.- With the legacy v1 payload version, the body is the v1 order representation instead (nested
pair, numericstatusviastatus_name,amount_base/amount_quote, different extra-ID field names). If you consume v1 webhooks today, prefer migrating the webhook config to v2 together with your REST migration — mixing v1 webhooks with v2 REST means reconciling two field vocabularies.
Field truth
Treat the webhook payload as a notification; on receipt, confirm current state with GET /orders/{unique_reference}/ before acting on money-moving logic. This also makes your handler robust to payload-version differences.
Signature verification
When a signing secret is configured, each request carries:
| Header | Value |
|---|---|
X-Webhook-Timestamp | Unix seconds at signing time |
X-Webhook-Signature | sha256= + hex HMAC-SHA256 over "{timestamp}." + raw_body, keyed with your secret |
Verification steps:
- Reject if
X-Webhook-Timestampis older than ~5 minutes (replay protection). - Compute
HMAC_SHA256(secret, timestamp + "." + raw_body)over the raw request body (before any JSON parsing). - Constant-time-compare against the header value after the
sha256=prefix.
Node.js verification
import { createHmac, timingSafeEqual } from 'node:crypto';
function verifyWebhook(rawBody, headers, secret) {
const ts = headers['x-webhook-timestamp'];
const sig = headers['x-webhook-signature'] ?? '';
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
const expected = 'sha256=' + createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
const a = Buffer.from(sig);
const b = Buffer.from(expected);
return a.length === b.length && timingSafeEqual(a, b);
}
Handler checklist
- Respond
2xxwithin 5 seconds; process asynchronously - Deduplicate on
id - Verify the HMAC signature and timestamp window
- Confirm state via
GET /orders/{unique_reference}/before side effects - Keep the polling reconciliation sweep as backstop (no automatic redelivery)
Next steps
- Order Tracking — the polling backstop
- Order Lifecycle — which transitions you'll be notified about