Before you go live
The pre-launch checklist every integration should run through before flipping traffic to production
One page, eleven checks. Every item here exists because someone shipped without doing it and had a bad day. Run through this end-to-end before you send your first production order.
If this is your first integration, read it top to bottom. If you're iterating, jump to the section relevant to your change.
Configuration
1. Production host, production credentials
Verify that your production build reads:
Base URL→https://api.octopuscards.io(not sandbox)API key/API secret→ your production pair, not sandbox- Separate environment variables from sandbox (e.g.
API_KEY_PRODvsAPI_KEY_SANDBOX)
A smoke test: your production deployment should fail to start if any of those env vars are missing. No silent defaults.
2. Credentials in a secrets manager
API keys and webhook secrets must live in a managed secrets store - AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, Kubernetes Secrets with encrypted etcd, etc. Not:
.envfiles committed to git (even in a private repo)- CI variables in plaintext
- Configuration files on disk
- Hardcoded strings
See Security for the full threat model.
Reliability
3. Request timeouts
Every outbound HTTP call needs a timeout. Our API has its own timeouts on the server side, but your client can stall on slow connections without one.
- Connect timeout: 5–10 seconds
- Read/response timeout: 30 seconds (orders can take longer during provider hiccups)
- Overall request timeout: 30–60 seconds
In Go:
client := &http.Client{ Timeout: 60 * time.Second }4. Retries with exponential backoff
Network blips happen. Retry these error classes:
- Network errors (connection refused, timeout, DNS failure)
- HTTP
5xxserver errors - HTTP
429 Too Many Requests- respect theRetry-Afterheader if present
Do not retry 4xx errors other than 429. They're not going to succeed on the next try.
Backoff pattern: start at 200ms, double each time, cap at 10s, with jitter. 4–6 retries max.
5. Idempotency via client_reference
Every order must carry your own client_reference. It's how we detect duplicate requests if your retry logic fires twice:
{ "product_id": 123, "denomination": 50, "quantity": 2, "client_reference": "your-uuid-here" }Rules:
- Construct the
client_referencebefore the first request attempt. - Persist it (even on the retry path) so your retries send the same value.
- A second POST with the same
client_referenceis rejected with a 400"Duplicate client_reference". Fetch the existing order via?client_reference=<value>on the list endpoint.
Full pattern: Idempotency.
Operations
6. Webhook endpoint: verified + replay-safe
If you handle async orders or product-catalog updates, your webhook consumer must:
- Verify the
X-SignatureHMAC on every request using your shared secret. See Signature Verification. - Reject stale events - look at
X-Timestampand drop anything older than ~5 minutes. - Deduplicate on
X-Event-ID- we retry at least once; your handler must be safe to run twice. - Respond
2xxwithin a few seconds. Queue the heavy processing asynchronously on your side. - Serve only over HTTPS with a valid certificate.
7. Low-balance alerts
Prepaid wallets run out. Set up monitoring:
- Poll
GET /api/v1/walletson a 1–5 minute cadence. - Alert when any wallet drops below a threshold (e.g. 20% of typical daily spend).
- Pager-level alert at 5% - wire transfers aren't instant.
Alternative/complementary: read the wallet_id balance from order responses and trip an alert from there.
8. Observability: request IDs, structured errors, distributed traces
You will not enjoy debugging a production incident without these. Set them up before you launch, not during the postmortem.
X-Request-Idon every request. Generate a KSUID on your side and send it; we echo it back. Log it alongside your own correlation IDs - it's how we find your request in our logs when you open a ticket.- Structured error logs. Parse the
{ error: { name, code, message } }envelope and logerror.codeas a separate field, not a stringified blob. Send to your monitoring tool (Sentry, Datadog, Rollbar). Redact secrets from the request body before logging. - W3C
traceparentheader if you run any tracing at all. We accept it on every endpoint and tag our internal spans with yourtrace_id- so a support ticket becomes a single trace lookup instead of a forensic dig. Most OTel SDKs inject it automatically; see Observability for the Go and Node patterns.
Full guidance: Observability and Handling Errors.
Behaviour
9. Rate limit handling
- Respect
429 Too Many Requestswhen it appears. - If the response includes
Retry-After, use it - don't just back off blindly. - Consider request batching (larger orders instead of many small ones) to stay under the limit in the first place.
Full detail: Rate Limits.
10. Concurrent order control
If your system can fan out many orders at once:
- Bound concurrency - limit to e.g. 10 in-flight
POST /api/v1/ordersper client worker. - Serialize per-wallet if you care about ordering - balance deductions are atomic but interleaved responses can confuse reconciliation.
- Pre-check balance with the Charges endpoint before committing, especially for bulk campaigns.
11. Sandbox-to-prod parity
Your production deployment should behave identically to your sandbox tests, minus the host. Before you cut over:
- Run your full test suite against sandbox once more.
- Confirm the only diff between the sandbox and prod build is the host + credentials.
- Deploy in a blue/green or canary pattern if your infra supports it - keep a quick rollback option for the first 24–48 hours.
Pre-launch final check
Five-minute dry run, against production credentials, in a staging environment that can reach production:
POST /auth/login- returns a token within 1s.GET /api/v1/wallets- returns your funded production wallet(s).GET /api/v1/products?limit=1- returns the live catalog.POST /api/v1/products/:id/charges- prices out a real product.- (Optional) One minimal-quantity order you're prepared to let land - confirms end-to-end fulfilment. Test wallets can be topped up; the voucher is real.
If all five come back clean, you're ready.
Post-launch, first 24 hours
- Watch your error-rate dashboard.
- Watch the low-balance alerts.
- Make sure at least one webhook has actually fired and been processed - send a small async order to trigger it if needed.
- Keep your rollback path warm until you've seen real traffic behave.