Overview
OpenFX provides two fully isolated environments. Each has its own base URL, credentials, and data. Resources created in sandbox never exist in production and vice versa.| Sandbox | Production | |
|---|---|---|
| Base URL | https://sandbox.api.openfx.com/v1 | https://api.openfx.com/v1 |
| Purpose | Integration development and testing | Live money movement |
| Real money | No | Yes |
| Simulation endpoints | Available (5 endpoints) | Return 404 Not Found |
| KYB review | Simulated via API | Performed by compliance team |
| Payment settlement | Simulated | Real settlement on payment rails |
| Webhooks | Delivered to your test URL | Delivered to your production URL |
| Rate limits | Relaxed for testing | Standard production limits |
| Data isolation | Completely separate from production | Completely separate from sandbox |
Base URLs
All API requests are made to the versioned base URL for the target environment:Credentials
Each environment requires its own set of credentials. You manage credentials through the OpenFX Dashboard.| Credential | Sandbox | Production |
|---|---|---|
| API key (Bearer token) | Prefixed with sk_sandbox_ | Prefixed with sk_live_ |
| Ed25519 public key | Registered in sandbox settings | Registered in production settings |
| Webhook signing secret | Unique per sandbox subscription | Unique per production subscription |
| Header | Purpose |
|---|---|
Authorization | Bearer token carrying your API key. Establishes caller identity. |
X-Signature | Ed25519 signature over the request. Provides integrity and non-repudiation. |
X-Timestamp | Unix timestamp. Server rejects requests outside a tolerance window for replay protection. |
See the Authentication guide for complete details
on generating Ed25519 key pairs, computing request signatures, and registering
public keys.
Sandbox environment
The sandbox environment is a full replica of the production API surface with the addition of simulation endpoints. All 138 API operations are available. The only functional difference is that no real money moves and certain asynchronous processes (KYB review, payment settlement, inbound deposits) are controllable via simulation.What works the same as production
- Entity, customer, account, counterparty, and payment method CRUD
- FX quotes and conversions (using sandbox rates)
- Payment creation and lifecycle state transitions
- Webhook delivery to your configured endpoints
- Idempotency enforcement
- Request signing validation
- Error responses and validation rules
- Pagination and filtering
- Rate limiting (relaxed thresholds)
What is different from production
- No real money movement. Payments are created and transition through statuses but no actual bank transfers or blockchain transactions occur.
- Simulation endpoints are available. Five endpoints let you trigger events that would normally require external action.
- KYB is instant. Use the simulation endpoint to approve or reject customers immediately instead of waiting for manual review.
- Sandbox FX rates may differ slightly from live market rates but follow the same pricing structure.
Simulation endpoints
Simulation endpoints are available only in sandbox at paths under/simulation/. They
allow you to trigger events that depend on external systems — inbound payments from
banks, KYB decisions from compliance, and payment status transitions from rail providers.
Simulate KYB decision
Approve or reject a customer’s KYB review. In production, this happens asynchronously via the compliance team and is communicated through thecustomer.kyb_status_changed
webhook.
Request body
decision field accepts approved or rejected.
Simulate account deposit
Add funds to an account for testing. In production, funds arrive via real bank transfers or crypto deposits.Request body
Simulate inbound payment
Create an inbound payment record as if funds had arrived via a specific payment rail. In production, these are created automatically by the system when external deposits are detected.{rail} parameter accepts any supported rail: ach, fedwire, swift, fednow,
crypto, sepa, fps.
Simulate payment status change
Force a payment into a specific status for testing lifecycle transitions, error handling, and webhook processing. In production, status changes are driven by rail-level settlement events.Request body
status field accepts any valid payment status: processing, completed,
returned, reversed, failed, canceled.
Simulate collection status change
Force a collection into a specific status for testing ACH debit return scenarios.Request body
Testing best practices
Use unique idempotency keys
Every state-changing request requires anIdempotency-Key header. Use UUID v4 values
and generate a new one for each distinct operation. Reusing a key with a different
request body returns a 409 idempotency_error.
Test the full lifecycle
Do not test just the happy path. Use simulation endpoints to exercise:- KYB rejection — Call simulate KYB with
"decision": "rejected"and verify your integration handles thecustomer.kyb_status_changedwebhook correctly. - Payment failures — Simulate
failedandreturnedstatuses to test your error handling and reconciliation flows. - Compliance gates — Create payments that enter
requires_actionstatus and test submitting compliance actions.
Set up webhooks early
Register a webhook subscription in sandbox pointing to a test URL (tools like webhook.site or ngrok work well). This lets you observe the full event stream as you test:["*"] subscribes to all event types. In production, subscribe only
to the event types you need.
Test with realistic data
Use realistic but fictional data in sandbox. This helps catch validation errors early and ensures your integration produces sensible output.Verify webhook signatures
Even in sandbox, verify theX-OpenFX-Signature header on every webhook delivery.
This ensures your signature verification code works before you go to production.
See Signature Verification for
implementation details.
Going to production
When your sandbox integration is working correctly:- Create production credentials in the OpenFX Dashboard.
- Register your production Ed25519 public key.
- Update your base URL from
sandbox.api.openfx.com/v1toapi.openfx.com/v1. - Update your API key from
sk_sandbox_...tosk_live_.... - Register production webhook subscriptions with your production endpoint URL.
- Remove any simulation endpoint calls from your production code path.
Environment-specific headers
All standard response headers are present in both environments:| Header | Description |
|---|---|
X-Request-ID | Unique request identifier. Include in support tickets. |
X-RateLimit-Limit | Maximum requests allowed in the current window. |
X-RateLimit-Remaining | Requests remaining in the current window. |
X-RateLimit-Reset | Seconds until the rate-limit window resets. |
Retry-After | Seconds to wait before retrying (on 429 and 409 responses). |
Idempotency-Replayed | true when the response is served from the idempotency cache. |