Go-Live Checklist
The pre-production checklist — credentials, ordering correctness, secrets, webhooks, treasury, and resilience.
Run this list before pointing real traffic at your integration. Every item links back to the page that explains it.
Credentials and access
- API keys live in a secret manager; nothing in source control, browsers, or mobile apps. (Authentication)
- Scopes are split by system: display keys can't order, ordering keys can't withdraw,
wallet.withdrawexists only in treasury tooling. - Keys that hand codes to customers hold
orders.reveal(or are the purchasing key withorders.create); support and reporting tools holdorders.readonly and never see codes. (Fulfillment) - Each deployment checks its key with
GET /api/v1/meat startup — scopes and expiry as expected. - Production keys carry a CIDR allow-list pinned to your egress addresses, and
403 ip_not_allowedalerts operations. - Key rotation is rehearsed: issue → deploy → revoke, with both valid during the overlap.
-
401/403responses page someone — they mean revoked/expired/mis-scoped credentials or a refused address. -
403 api_access_inactiveraises a billing alert with itsreason; your integration keeps serving reads (orders, codes already bought, wallet) while the subscription is overdue, and stops placing orders until it is settled.GET /api/v1/workspaceis watched forapiAccess.statusandpaidThroughUtc.
Ordering correctness
- Every
POST /ordersandPOST /orders/{id}/fulfillmentcarries anIdempotency-Keyderived from your order identity and persisted with it; keys are never reused across purchases — they are spent for good, workspace-wide. (Orders) - Timeouts and 5xx on order creation retry with the same key and the same body — no check-then-resend logic.
-
409 idempotency_conflicton an order never leads straight to a new key: the order is looked up byclientReferencefirst, and a new key is used only once the purchase is known to be absent. - Request bodies are built from typed models: an unknown member is refused with
400, never ignored. - One-call orders set
maximumTotalto the price the buyer saw, andprice_above_maximumshows the buyer the new price instead of failing silently. -
insufficient_fundsalerts treasury — the wallet needs funding before orders can resume. - Your state machine handles every order status, treats unknown statuses as non-terminal, and only marks delivery on
fulfilled; afulfilledorder can still becomerefunded. -
reconciliationrequiredorders (andorder.under_reviewevents) surface in your back office instead of silently aging. - Quotes, where you use them, are created at checkout time and never cached past
expiresAtUtc;GET /quotes/{id}statusdecides whether one can still be ordered. (Quotes) - Orders are found by your own id with
GET /orders?clientReference=(or byord_reference), order lines are reconciled byproductId/variantId, and refunds byrefund.
Secrets handling
- Fulfillment is revealed late, over the dedicated endpoint, and artifact values are scrubbed from logs, APM, and error reports. (Fulfillment)
- Each intended reveal uses a fresh
Idempotency-Key; a timed-out reveal is retried under the same key within 15 minutes,fulfillment_replay_expiredis handled by revealing under a new key, andidempotency_conflict(a key already bound to another reveal) is treated as a bug in key derivation, not retried. - The reveal allowance (
remainingReveals, orGET /orders/{id}/fulfillment/allowance) is checked before spending a reveal on a user's request. - If codes must be stored, they are encrypted at rest with restricted access; otherwise they are delivered and dropped.
-
revealCountis tracked and an unexpected increase alerts.
Webhooks
- Signature verification implements all four rules: raw-body HMAC, constant-time compare, ±5-minute freshness, parse-after-verify. (Webhooks)
- The endpoint is subscribed to every event type you handle,
order.under_reviewincluded, and the dashboard's Send test delivery verifies and acknowledges. - Deduplication by
X-Xegora-Event-Idis durable (database unique index). - The receiver acknowledges in <2 s and defers real work to a queue; unknown event types are acknowledged and ignored.
- Out-of-order retries are tolerated (state compared by timestamps, or re-read from the API).
- Order events are reconciled by line
productId/variantId;wallet.creditedbysourceandmovementIdagainst the statement. - The
xgwh_secret is stored like a password and endpoint rotation is rehearsed. - A reconciliation sweep of
GET /orders?updatedFrom=…(and, for treasury,GET /wallet/movements) backstops webhook gaps.
Wallet and treasury
- Deposit networks and stablecoins are read from
GET /wallet/deposit-options, never hard-coded; each deposit address you use was fetched once and pinned in your runbook together with its network and stablecoin; your treasury sends only that stablecoin on that network to it. (Wallet & Deposits) - Balance monitoring alerts before
availableBalancereaches your burn rate. - The daily close reconciles the wallet statement (
GET /wallet/movements) against your books; deposits match by theiridandtransactionHash, withdrawals bypublicReferenceandpayoutReference. (Wallet & Deposits, Withdrawals) - The statement walk follows
nextuntil it is absent and never stops because a page came back shorter thanlimit— atype-filtered page can end early withnextstill set; progress is measured againsttotalCount, not againstlimit. - Withdrawal requests carry an
Idempotency-Keyand the quote'sfeeandnet;withdrawal_terms_changedre-quotes and shows the new terms. -
GET /payout-destinationsshows an approved,readydefault for each currency you withdraw in before the first withdrawal.
Resilience and hygiene
- Backoff-with-jitter retry policy for 5xx/IO;
Retry-Afterhonored on 429 and 503; nothing retries other 4xx (except409 concurrent_update, under the same key). (Errors & Retries) - Scheduled jobs are spread across the minute, sized within 120 requests/min/workspace, and paced by
RateLimit-Remaining; image fetching is cached (ETag) and stays within its own 300/min budget. - Services sharing one egress address keep concurrency modest — the per-address limits apply before keys are checked.
- Error handling branches on
code, never onmessage,titleordetail. - The correlation id is logged on every response — from the
X-Correlation-Idheader, which every response carries, or from a problem'scorrelationId, which repeats it — and included in support tickets; your ownX-Correlation-Id(letters, digits,.,_,:,-, at most 128) is sent where you want to trace a request end to end. - Amounts are parsed as decimals and timestamps as offset-aware instants; a
+in a timestamp query parameter is URL-encoded. - HTTPS keep-alive connection reuse is enabled; client timeouts are 10–15 s.
- Clocks are NTP-synced (webhook freshness depends on it).
When every box is checked, you are running the same patterns our own surfaces are built on. Welcome to production.
Updated 18 days ago
Did this page help you?