# Sandbox and test mode

> Send test emails and sign watermarked documents without billing.

Source: https://signclad.com/docs/sandbox-and-test-mode/

Test mode exists so you can build and run a full integration — send, sign, complete, webhook, download — without usage charges. Recipients receive real emails explicitly marked as test documents. Use addresses you control.

## How a request becomes a test request

Two ways, and they agree:

1. **The key.** Any request with an `sk_test_` key is a test request, and nothing the caller sends can turn that off.
2. **The flag.** `test_mode: true` on a create makes that document a test document even with a live key.

There is nothing else to configure. If your code has an `if (env === 'staging')` branch deciding whether to set a flag, delete it and use a sandbox key instead.

Both routes need the plan entitlement that sandbox keys come with: Light and above. On Free, `test_mode: true` is refused.

## What test mode does

| | Test mode |
|---|---|
| Billing | Never counted. A test document never touches the monthly counters and can never be refused for being over them. |
| Email | Delivered to recipients with “This is a test document” in the message and `[TEST]` in the subject. |
| Signing | Works normally. Open the signing URL and sign. |
| Artifacts | Every page is watermarked “Not legally binding -- test mode,” including the completed PDF. |
| Webhooks | Delivered only to endpoints with `include_test_mode: true`. |
| Rate limit | The same buckets and the same numbers as live keys: 120/min general, 10/min for `POST`, `PUT` and `PATCH`, 120/min for `POST /files`. |
| Document limits | Unlimited. |

## Real delivery in test mode

Invitations, reminders, passcodes, and completed copies go to the intended recipients. Test emails include an explicit notice, and test documents are not legally binding. Invalid recipient addresses can bounce just as they do in live mode.

## What a sandbox key cannot reach

A sandbox key is not merely filtered to test rows; it is confined to a list of route families, and everything else answers `403 sandbox_key_not_allowed`. Documents, templates, files, bulk sends, webhook endpoint configuration, the event catalog, its own API keys and `/me` are allowed. The address book, the suppression list, webhook delivery logs and replay, the debug inbox, data exports, members, billing, workspace settings and OAuth applications are not — they hold live data with no test-mode column to filter on.

Webhook endpoints are allowed but partitioned: a sandbox key sees and can change only the endpoints a sandbox key registered, so the production callback is a `404` to a staging credential. Delivery is not partitioned — an endpoint a sandbox key registered still receives the live events it subscribed to.

A sandbox key also creates only sandbox keys. Asking it for a live key is a `422` on `mode`, and a live key reached by id is a `404`.

## Sending test events

Every webhook endpoint has a "send test event" action for each event type: `POST /webhook_endpoints/{id}/ping` with an `event_type` sends a realistic sample of that event, synchronously, and never counts towards the endpoint's health. Creating an endpoint with `verify: true` sends a plain `ping` first and activates the endpoint only if your receiver answers `2xx`. Both let you exercise a receiver before there is a real document to exercise it with.

## Moving to live

1. Create a live key — from the app or with another live key, since a sandbox key cannot mint one — and put it wherever your sandbox key was.
2. Register your production webhook endpoint with the live key. A sandbox key's endpoints stay visible only to sandbox keys.
3. Check `include_test_mode` on your webhook endpoints — most production endpoints should have it off.
4. Nothing else changes. The paths, bodies, statuses, and event names are identical.

## Related

- [Authentication and keys](https://signclad.com/docs/authentication/)
- [Webhooks](https://signclad.com/docs/webhooks/)
- [Migrating to Signclad](https://signclad.com/docs/migration/)
