# Environments

You build against the **sandbox** and go live on **production**. Both run the same
code, the same rate limits, and the same signatures — the sandbox is the full platform
running on a separate database with deterministic fixtures.

```bash
# Sandbox — test tokens, deterministic fixtures, no real money:
curl "https://sandbox-pay.mmokick.com/api/v1/whoami" -H "Authorization: Bearer $CK_TEST_TOKEN"

# Production — live tokens, real orders and payouts:
curl "https://pay.mmokick.com/api/v1/whoami" -H "Authorization: Bearer $CK_LIVE_TOKEN"
```

| | Production | Sandbox |
|---|---|---|
| Base URL | `https://pay.mmokick.com/api/v1` | `https://sandbox-pay.mmokick.com/api/v1` |
| Tokens | `ck_live_*` | `ck_test_*` |
| Getting access | KYC-vetted onboarding (24–72 h) | **Instant** — submitting your supplier application approves you into the sandbox on submit; create a `ck_test_` token in the portal and call the sandbox base URL right away |
| Data | Real | Fixtures re-asserted nightly; **no destructive resets** — your suppliers, tokens, and offers persist; orders and logs are pruned after 30 days |
| Payments | Real providers | Stripe/PayPal test mode |
| Settlement clock | Funds clear 7 days after delivery | Funds clear **10 minutes** after delivery, so you can test balance flows in one session |

Tokens are prefix-locked to their environment. A `ck_test_` token on production (or a
`ck_live_` token on sandbox) returns `401` / `wrong_environment` and stops there. Match
the token prefix to the host every time.

## Start in the sandbox

Sandbox access is instant and auto-approved. When you submit the production supplier
application in the portal, your supplier is mirrored into sandbox the moment you submit,
so you can create a `ck_test_` token and reach a delivered test order in minutes while
production vetting runs in the background.

There is a published demo supplier and token already seeded in the sandbox, so you can
run read calls even before creating your own token:

| Fixture | Value |
|---|---|
| Demo supplier ("Acme Digital GmbH") | `01SANDBX00000000000000SP01` |
| Published sandbox token | `ck_test_sandbox000000000000000000000000000000001` |

Use your own token for anything you write, so your offers and webhook endpoints stay
scoped to you.

## Deterministic fixtures

The sandbox ships fixed products, offers, and keys with hard-coded ULIDs you can embed
in your tests. A nightly upsert re-asserts them in place and **preserves every ID**, so
a suite that hard-codes these IDs keeps working.

| Fixture | ID |
|---|---|
| Product — `game_key` ("Cyber Odyssey — PC (Steam)", region `global`) | `01SANDBX00000000000000PD01` |
| Product — `gift_card` ("Steam Gift Card 20 EUR", region `europe`) | `01SANDBX00000000000000PD02` |
| Product — `topup` ("MMO Kick Gold — 1000 G", `form_fields`: `user_id` regex `^[0-9]{6}$`, `server_id` select) | `01SANDBX00000000000000PD03` |
| Deterministic uploaded keys | `CKTEST-OK-00001` … `CKTEST-OK-00100` |

The `CKTEST-OK-*` keys are safe, deterministic values you upload as inventory in the
sandbox — see [Your first sale in 15 minutes](https://pay.mmokick.com/developers/guides/first-sale-in-15-minutes).

## Magic top-up test values

For `topup` products, four magic `user_id` values drive the top-up contract down a
fixed path, so you can prove each branch without a real player account. Send them as
`form_fields.user_id` to `POST /sandbox/orders` (or your own `validate`/`execute`
endpoints when the sandbox calls them):

| `user_id` | Behavior |
|---|---|
| `100001` | Validates and executes cleanly (happy path) |
| `999999` | Fails validation with code `invalid_user_id` |
| `888888` | Validates, then fails execute with status `failed` and code `topup_failed` |
| `777777` | Times out once, then succeeds on retry — the idempotency demo |

These are the same values used throughout the [Top-up products](https://pay.mmokick.com/developers/guides/topup-products)
guide.

## Sandbox parity

The sandbox is the same code as production. Specifically:

- **Rate limits are identical** to production, so your load assumptions transfer
  directly. See [Rate limits](https://pay.mmokick.com/developers/rate-limits).
- **Signatures are identical** — the HMAC scheme and the published test vectors are the
  same in both environments. See [Webhooks](https://pay.mmokick.com/developers/guides/webhooks).
- Webhook and fulfilment targets may use any HTTPS port in sandbox. Point them at a
  public HTTPS address — the sandbox reaches public hosts and rejects private and
  link-local IPs — so use a tunnel for local development.

If the dedicated sandbox host is ever unavailable, the same API is reachable under a
`/sandbox` path prefix on the production origin. Every example in these guides renders
the correct sandbox base URL for you — copy and paste it as written.

## Next steps

- [Your first API call in 5 minutes](https://pay.mmokick.com/developers/getting-started/first-call) — make a real sandbox call now.
- [Your first sale in 15 minutes](https://pay.mmokick.com/developers/guides/first-sale-in-15-minutes) — end to end, including a signed webhook.
- [Authentication](https://pay.mmokick.com/developers/getting-started/authentication) — tokens, scopes, and failure responses.
