# Sandboxes and test mode

> Test keys, test accounts, presets, magic values and test helpers, without reaching a network.

A sandbox is a test copy of your Workspace. It runs on the same plan and limits, has its own Projects, posts, keys and webhook endpoints, and nothing in it reaches a network, charges money or sends email. Use one to build and test an integration before it touches real accounts.

## Create a sandbox

Owners, admins and people with the Developer duty create sandboxes in **Settings > API keys > Sandboxes** of the live Workspace. Your plan sets how many you can have. **Open** switches the app into the sandbox: a Test mode banner stays on every page until you exit.

Keys you create inside a sandbox are test keys. They start with `ns_test_` and reach only that sandbox. Its events carry `"livemode": false`, and its webhook endpoints retry for about two hours instead of three days.

## Test accounts

A sandbox never connects a real network account. Add test accounts instead:

- In the app: **Connections > Add connection** in the sandbox, then pick a network. The account appears at once.
- With the API: `POST /v1/test_helpers/accounts` with a test key.

```bash
curl https://api.nowscale.com/v1/test_helpers/accounts \
  -H "Authorization: Bearer $NOWSCALE_TEST_KEY" \
  -H "Idempotency-Key: 9b2f4c1e-7a3d-4e8b-a6c5-1d0e2f3a4b5c" \
  -H "Content-Type: application/json" \
  -d '{"project_id": "PROJECT_ID", "network": "youtube", "preset": "healthy"}'
```

Plan limits per network apply as for real accounts. A test account's preset decides how its network behaves:

| Preset | Behaviour |
| --- | --- |
| `healthy` | Every post publishes on time. |
| `reauth_required` | The account needs reconnecting: its posts fail with `reauth_required`. |
| `expiring` | Publishes normally; its access is shown as expiring within three days. |
| `slow` | Publishes 90 seconds after the due time. |
| `flaky` | About 3 in 10 targets fail with `provider_timeout` (always the same ones). |

Switch a preset with `POST /v1/test_helpers/accounts/{account_id}`, for example to `reauth_required` to see how your integration handles an account that must reconnect.

## Publishing in a sandbox

Create, schedule and publish posts exactly as in live mode, in the app or with `POST /v1/posts`. When a target's time comes, the simulator plays the network: the target publishes (it gets an `external_id` starting with `sim_`) or fails with a code the live API also uses. The post's status, its events and your webhooks follow, as in live mode.

Force an outcome with magic values in the post's caption:

- `ns_test:fail=<code>` fails every target of the post.
- `ns_test:youtube.fail=<code>` fails only the YouTube target (any network id works).
- `ns_test:delay=<seconds>` publishes that long after the due time.

`ns_test:fail=<code>` accepts `reauth_required`, `quota_exceeded`, `connection_gone`, `upload_rejected`, `provider_timeout`, `video_rejected`, `processing_failed`, `publish_outcome_unknown`, `tiktok_private_account_required`. `ns_test:delay=<seconds>` holds a publish up to 3600 seconds.

`POST /v1/test_helpers/posts/{post_id}/advance` runs the simulator for one post right away, delays included, and answers with the post. A target scheduled in the future stays scheduled; publish the post to send it now.

## What a sandbox does not do yet

- Analytics, captions, playlists and other reads that ask the network live answer `simulated_account` for test accounts.
- Comments on test accounts are not simulated yet.
- Paid AI is simulated through the API (see [AI operations and Tokens](/ai-operations)); in the app, AI features other than comment reply drafts answer as unavailable.
- Deleting a sandbox hides it at once; its content is removed later.
