Skip to content

Going live

Work through this before your first real order. Most of it is about what happens when something goes wrong, because that is what separates an integration that survives from one that pages you at 3am.

  • A live key exists, created by an Owner or Admin.
  • It holds only the scopes you call. Drop orders:write from a key that only reads.
  • The secret is in a secret store — not in your repository, not in an environment variable committed to an image.
  • You know how to rotate. The old secret keeps working during the transition, so rotation needs no downtime.
  • Optional: an IP allowlist on the key, if your egress addresses are fixed.
  • Every order sends an Idempotency-Key that is persisted before the call, so a retry reuses it. See Idempotency.
  • You branch on code, never on message.
  • request_id is written to your logs on every error.
  • Access tokens are cached for their hour rather than fetched per request.
  • 429, 500 and 503 retry with exponential backoff and jitter.
  • 422 does not retry.
  • Balance is monitored, and someone is alerted before it runs out. Subscribe to balance.low.
  • You handle insufficient_balance as a real branch in your checkout, not as a generic failure.
  • If you show a price before ordering, you send expected_total so a price move rejects the order rather than surprising the customer.
  • Your webhook endpoint verifies the signature and rejects anything that fails. See Webhooks.
  • It is idempotent on the event id — duplicate deliveries are expected.
  • It returns 2xx quickly and does its real work asynchronously.
  • You have a reconciliation path that polls for anything a webhook missed, so a delivery outage cannot leave an order permanently stuck.
  • Sandbox ids are gone from configuration and caches.
  • One small live order has been placed, installed, and confirmed on a real device.
  • You know which of your own alerts fires when the API returns errors.