Overview

This checklist covers every area of your integration that must be verified before moving from sandbox to production. Work through each section in order — later sections build on earlier ones.
Do not go live until every item in the Authentication & Security, Integration, and Webhooks sections is complete. Items in Testing and Monitoring may be adapted to your specific use case, but skipping them increases operational risk.

Authentication & Security

These items ensure your production requests are properly authenticated and your signing keys are managed securely.
Ed25519 key pair generated and public key registered. Generate a dedicated production key pair and register the public key in the OpenFX Dashboard under production settings. Do not reuse your sandbox key pair.
Separate production API credentials created. Your production API key (prefixed sk_live_) must be distinct from your sandbox key (sk_sandbox_). Credentials from one environment will return 401 authentication_error in the other.
Private keys stored securely (HSM/KMS, not in code). Your Ed25519 private key must never be committed to version control, embedded in client-side code, or stored in plain text on disk. Use a hardware security module (HSM), cloud KMS (AWS KMS, GCP Cloud KMS, Azure Key Vault), or a secrets manager (HashiCorp Vault, AWS Secrets Manager).
Request signing implemented and tested. Every request to the OpenFX API requires three headers: Authorization (Bearer token), X-Signature (Ed25519 signature), and X-Timestamp (Unix timestamp). Verify your signing implementation produces valid signatures for GET, POST, PATCH, and DELETE requests.
Webhook signature verification implemented. All incoming webhook deliveries include an X-OpenFX-Signature header containing an HMAC-SHA256 signature. Your webhook receiver must verify this signature before processing any event. See Signature Verification.
Clock synchronization verified. The OpenFX server rejects requests where X-Timestamp differs from server time by more than 60 seconds. Ensure your production servers synchronize clocks via NTP.

Integration

These items cover the core integration patterns that prevent data loss, duplicate operations, and breaking changes.
Idempotency keys on all POST, PATCH, and DELETE requests. Every state-changing request must include an Idempotency-Key header with a unique value (UUID v4 recommended). Reuse the same key when retrying the same operation. Generate a new key for each distinct operation.
Error handling with retry logic. Implement exponential backoff with jitter for retryable errors (5xx, 429, network timeouts). Respect the Retry-After header when present. Do not retry 4xx errors other than 429 (rate limit) and 409 (idempotency_key_in_flight).
Rate limit handling. Monitor X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset response headers. When X-RateLimit-Remaining approaches zero, proactively slow your request rate. On 429 Too Many Requests, back off for the duration specified in Retry-After.
Forward compatibility (ignore unknown fields in responses). Your JSON deserialization must not fail when encountering new fields added to response bodies. Use permissive parsing (e.g., Pydantic extra="ignore", standard JSON.parse, Go default json.Unmarshal). Never validate responses against a strict schema.
Unknown enum values handled gracefully. All switch/match statements on enum fields (status, rail, type) must include a default branch. Log unknown values and treat them as a safe fallback (e.g., “in progress”) until you deploy an update.
Cursor-based pagination implemented. List endpoints return paginated results. Use starting_after and ending_before parameters to traverse pages. Do not assume a fixed page size — the limit parameter controls page size but the actual count may be fewer. Always check hasMore to determine if additional pages exist.
Monetary amounts handled as strings. All amount fields (sendAmount.amount, receiveAmount.amount, fee.amount, balance amounts) are JSON strings. Parse them with a decimal library (Python Decimal, JavaScript BigNumber.js or Decimal.js, Java BigDecimal). Never use floating-point types for money.
Base URL updated to production. Replace https://sandbox.api.openfx.com/v1 with https://api.openfx.com/v1 in your configuration. This should be a single environment variable, not hardcoded in multiple locations.

Webhooks

Webhooks are the primary mechanism for receiving asynchronous events (payment status changes, KYB decisions, collection returns). A robust webhook integration is essential for production.
Webhook subscription created with appropriate event types. Create a production webhook subscription via POST /webhooks/subscriptions with your production endpoint URL. Subscribe only to the event types you need rather than using ["*"]. At minimum, subscribe to: payment.completed, payment.failed, payment.returned, and customer.kyb_status_changed.
Signature verification on all incoming webhooks. Verify the X-OpenFX-Signature HMAC-SHA256 signature on every delivery before processing. Reject any delivery with a missing or invalid signature. See Signature Verification.
Idempotent event processing (deduplicate by event ID). Webhook deliveries may be retried if your endpoint returns a non-2xx response or times out. Your handler must be idempotent — processing the same event twice should not create duplicate side effects. Deduplicate using the id field on the event payload (evt_ prefix).
Fallback polling via GET /events implemented. If your webhook endpoint goes down or misses deliveries, use GET /events to poll for events you may have missed. This is your recovery mechanism. Store the last processed event ID and poll periodically to fill gaps.
Webhook endpoint returns 200 within 10 seconds. Your webhook endpoint must acknowledge receipt quickly. Perform heavy processing asynchronously after returning the 200 response. If your endpoint consistently times out, OpenFX will disable the subscription after exhausting retries.
Secret rotation procedure documented. Document and test the process for rotating your webhook signing secret via POST /webhooks/subscriptions/{id}/rotate-secret. During rotation, both the old and new secrets are valid for a grace period. See Secret Rotation.
Unknown event types handled gracefully. Return a 200 response for event types you do not recognize. New event types may be added at any time without a version change. Never return a non-2xx response for an unrecognized event — this triggers unnecessary retries.

Testing

Complete these testing items in sandbox before switching to production credentials.
Full end-to-end flow tested in sandbox. Walk through the entire flow at least once: create onboarding, wait for KYB approval, create account, create counterparty, add payment method, create payment, verify completion. The Quickstart covers this flow.
All payment rails you will use tested individually. For each rail your integration supports (ACH, Fedwire, SWIFT, crypto, OPEN), create at least one outbound payment and verify the response schema and lifecycle. Use rail-specific endpoints (POST /payments/{rail}) or the unified endpoint (POST /payments). See Payment Rails.
Error scenarios tested. Test and handle the following failure modes:
  • Insufficient funds — attempt a payment exceeding the available balance.
  • Invalid request data — submit malformed requests and verify your error parsing.
  • Payment failures — verify your handling of failed status payments.
  • Payment returns — test your return action flow (accept, contest, or repair).
  • Rate limiting — send rapid-fire requests to trigger 429 responses and verify your backoff logic.
Webhook delivery tested. Send a test delivery via POST /webhooks/subscriptions/{id}/test and verify your endpoint receives, verifies the signature, and processes the event correctly.
Return handling flow tested. Verify your return-action submission flow (accept, contest, or repair) works correctly. See Payment Returns.
Cross-currency payment flow tested (if applicable). If your integration uses FX conversions, test the full flow: create an FX quote, create a cross-currency payment with the quote, and verify the conversion amounts and fees. See Cross-Currency Payments.
Collection flow tested (if applicable). If your integration initiates ACH debit collections, test the full lifecycle including returns. See Collections.

Monitoring

Production monitoring ensures you detect and respond to issues before they affect your customers.
X-Request-ID logged for all API interactions. Every API response includes an X-Request-ID header. Log this value alongside your internal request records. When contacting OpenFX support, include the X-Request-ID for fast issue resolution.
Payment status transitions monitored. Track the time payments spend in each status. Alert on payments that remain in created or processing for longer than expected. This catches stuck payments early.
Balance reconciliation implemented. Periodically call GET /accounts/{id}/balances and reconcile against your internal ledger. Use GET /transactions to identify discrepancies.
Webhook delivery failures monitored. Monitor your webhook endpoint’s response codes and latency. If deliveries start failing (non-2xx responses), investigate immediately. Implement fallback polling via GET /events when webhook delivery is degraded.
Error rate monitoring in place. Track the rate of 4xx and 5xx responses from the OpenFX API. A spike in 4xx errors may indicate a bug in your integration. A spike in 5xx errors may indicate an OpenFX platform issue — check status.openfx.com.

Quick Reference: Production vs. Sandbox

ItemSandboxProduction
Base URLsandbox.api.openfx.com/v1api.openfx.com/v1
API key prefixsk_sandbox_sk_live_
Ed25519 key pairSandbox-specificProduction-specific
Webhook endpointTest URL (webhook.site, ngrok)Your production HTTPS endpoint
KYB reviewAuto-approved in sandboxPerformed by compliance team (async)
Money movementSimulatedReal bank transfers and blockchain transactions

Go-Live Sequence

1

Complete this checklist

Work through every section above. Address any gaps before proceeding.
2

Create production credentials

Generate a new Ed25519 key pair for production. Create a production API key in the OpenFX Dashboard. Register the public key.
3

Configure production environment

Update your application’s base URL, API key, and signing key to production values. These should be environment variables, not hardcoded.
4

Register production webhooks

Create webhook subscriptions pointing to your production HTTPS endpoint. Subscribe only to the event types you need.
5

Run a small-value test payment

Create a real payment for a minimal amount to verify end-to-end connectivity, signing, and webhook delivery in the production environment.
6

Monitor and scale

Watch your monitoring dashboards closely for the first 48 hours. Gradually increase volume once you have confirmed stable operation.