> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs-v3.openfx.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Environments

> Sandbox and Live share api.openfx.com; Sandbox API keys carry a sandbox_ prefix.

OpenFX runs Sandbox and Live on the **same base URL** (`api.openfx.com`). Which environment you hit is determined entirely by the **API key** you authenticate with — each key is bound to one environment server-side. Sandbox API keys carry a **`sandbox_` prefix**; Live keys are unprefixed, so you can tell the two apart at a glance. Sandbox and Live use the same endpoints and code paths, but differ in real-vs-simulated funds, the key prefix, and rate limits. Code validated in Sandbox therefore follows the same API contract in Live, but its traffic pattern must also be tested against Live's lower rate limit.

## Sandbox vs Live

| Aspect                 | Live                                  | Sandbox                                        |
| ---------------------- | ------------------------------------- | ---------------------------------------------- |
| Base URL               | `api.openfx.com`                      | `api.openfx.com` (same)                        |
| API key                | Unprefixed (bound to env server-side) | `sandbox_`-prefixed (bound to env server-side) |
| Real funds             | Yes                                   | No (simulated)                                 |
| Webhook signing secret | `whsec_…`                             | `sandbox_whsec_…`                              |
| Rate limits            | 300 requests / 10-second window       | 600 requests / 10-second window (2× Live)      |
| Data persistence       | Permanent                             | May reset periodically                         |

Sandbox's ceiling is 2× Live's, so code that stays comfortably under the Sandbox limit still has headroom to check against the tighter Live limit before going live. See [Rate limiting](/v3/rate-limiting) for the back-off pattern.

## Sample request

A Sandbox call differs from a Live call only by the `sandbox_`-prefixed key; everything else, including the required `X-Request-Signature`, is the same.

```bash theme={null}
# X-Request-Signature is an ES256 signature over the canonical request string;
# compute it with one of the language helpers in /v3/authentication (shell signing is impractical).

# Sandbox
curl https://api.openfx.com/v3/fx/pairs \
  -H "Authorization: Bearer $OPENFX_SANDBOX_JWT" \
  -H "X-Request-Signature: $OPENFX_SIGNATURE"

# Live
curl https://api.openfx.com/v3/fx/pairs \
  -H "Authorization: Bearer $OPENFX_LIVE_JWT" \
  -H "X-Request-Signature: $OPENFX_SIGNATURE"
```

The JWT in each case was minted with the matching environment's API key (Sandbox keys carry a `sandbox_` prefix; Live keys don't). See [Authentication](/v3/authentication) for the minting flow.

## Safety net: wrong-environment errors

If your key doesn't match the environment you're trying to reach, OpenFX rejects the request instead of silently doing the wrong thing — you can't accidentally execute a Live trade with Sandbox credentials, or vice versa.

| Error code                      | When you'll see it              |
| ------------------------------- | ------------------------------- |
| `AUTH_API_KEY_SANDBOX_REQUIRED` | Sandbox traffic uses a Live key |
| `AUTH_API_KEY_LIVE_REQUIRED`    | Live traffic uses a Sandbox key |

Both codes return `AUTHORIZATION_ERROR` / 403 — the request authenticated successfully, but the key isn't valid for this environment. Full entries live in the v3 [error catalog](/v3/errors#error-code-catalog).

## Going live

The full pre-launch list lives in the [Live checklist](/v3/live-checklist). The minimum cutover from a working Sandbox integration is:

<Steps>
  <Step title="Swap credentials">
    Replace the Sandbox `name` and `privateKey` in your secrets store with the
    Live values from the dashboard.
  </Step>

  <Step title="Update webhook signing key">
    Live webhook signing secrets are prefixed `whsec_` (Sandbox secrets are
    `sandbox_whsec_…`). Point your verifier at the Live signing secret.
  </Step>
</Steps>

<Tip>
  Run end-to-end through Sandbox first. Identical endpoints and code paths
  mean what works in Sandbox works in Live — with one exception: Sandbox's
  rate limit is 2× Live's, so a traffic pattern that stays under Sandbox's
  600 req/10s ceiling can still exceed Live's tighter 300 req/10s ceiling
  after cutover. Load-test against 300 req/10s specifically, don't rely on
  Sandbox passing as proof Live will.
</Tip>

## Common mistakes

* **Mixing credentials in the same process.** Two key pairs (one Sandbox, one Live) stored in two distinctly-named secrets. Never read `OPENFX_KEY` and hope it's the right one.
* **Assuming Sandbox data persists.** Sandbox may be reset periodically; don't seed long-running test workflows with Sandbox IDs you expect to still exist next month.
* **Hard-coding the base URL.** It's the same in both environments, but writing `api.openfx.com` as a literal in two places will trip you up the day OpenFX adds a regional endpoint.
* **Load-testing only against Sandbox's rate limit.** Sandbox's 600 req/10s ceiling is 2× Live's 300 req/10s — a burst pattern that passes in Sandbox can still 429 on Live. Test against Live's tighter limit before cutover, not just Sandbox's.

## What's next

<CardGroup cols={2}>
  <Card title="Live checklist" icon="list-check" href="/v3/live-checklist">
    Full pre-launch checklist: keys, IP allowlist, monitoring.
  </Card>

  <Card title="Authentication" icon="key" href="/v3/authentication">
    JWT minting flow with code samples in JS, TS, Python, and Go.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/v3/errors#authentication-authorization">
    `AUTH_*` codes and recovery patterns.
  </Card>
</CardGroup>
