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.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
failedstatus payments. - Payment returns — test your return action flow (accept, contest, or repair).
- Rate limiting — send rapid-fire requests to trigger
429responses 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
| Item | Sandbox | Production |
|---|---|---|
| Base URL | sandbox.api.openfx.com/v1 | api.openfx.com/v1 |
| API key prefix | sk_sandbox_ | sk_live_ |
| Ed25519 key pair | Sandbox-specific | Production-specific |
| Webhook endpoint | Test URL (webhook.site, ngrok) | Your production HTTPS endpoint |
| KYB review | Auto-approved in sandbox | Performed by compliance team (async) |
| Money movement | Simulated | Real bank transfers and blockchain transactions |
Go-Live Sequence
Create production credentials
Generate a new Ed25519 key pair for production. Create a production API key in the
OpenFX Dashboard. Register the public key.
Configure production environment
Update your application’s base URL, API key, and signing key to production values.
These should be environment variables, not hardcoded.
Register production webhooks
Create webhook subscriptions pointing to your production HTTPS endpoint. Subscribe
only to the event types you need.
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.
Related
- Quickstart — end-to-end sandbox walkthrough