Webhooks
TradeOn POSTs JSON events to the URL you configure in the cabinet
(Settings → Webhook) when a merchant order changes state or a balance deposit
completes. No per-event subscription — the URL receives everything.
What you need to get right before going live:
- Verify
X-Signatureand rejectX-Timestampskewed by more than ±5 min — Signature. - Return 2xx within ~10 s. 5xx / timeouts auto-retry, 4xx does not — Retry policy.
- Dedup on
(purchase_id, event)forpurchase.*, ondata.provider_uuidforbalance.deposited— Dedup contract. - Tolerate unknown event types and unknown fields (return 2xx) — Versioning.
Headers on every delivery
| Header | Value |
|---|---|
Content-Type | application/json; charset=utf-8 |
User-Agent | TradeOn-Merchant-Webhook/1.0 |
X-Event | Event type, e.g. purchase.completed (matches the event field in the body). |
X-Event-Id | Server-generated UUID, also present as event_id in the body. Stable across retries. |
X-Timestamp | Unix seconds at delivery time (regenerated per attempt, signed payload). |
X-Signature | hex(HMAC-SHA256(secret, "{X-Timestamp}.{raw_body}")), lowercase hex. |
The body is always a JSON envelope:
{
"event": "purchase.completed",
"event_id": "11111111-2222-3333-4444-555555555555",
"occurred_at": "2026-05-05T12:34:56.789Z",
"data": { /* event-specific payload */ }
}Six event types in v1
purchase.createdpurchase.sent_to_steampurchase.completedpurchase.failedpurchase.refundedbalance.deposited
See Event Catalogue for per-event payload schemas.