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

# Sandbox

> Build and test your integration with a test key that returns sample data and spends no credits

A test key calls the same endpoints as your live key and gets responses in the same shape. Nothing real happens behind it: no credits or plan quotas are used, nothing is sent to LinkedIn, and no search, list or enrichment is created in your account. When your integration works, swap the test key for your live key.

Test keys start with `pc_test_`. Every response to one carries the header `Pipecorn-Mode: test`.

## Try it without an account

The public demo key `pc_test_demo` works for everyone, so you or an agent can make a first call before signing up.

```bash theme={null}
curl https://app.pipecorn.com/api/v2/contacts/single_enrich \
  -H "X-API-KEY: pc_test_demo" \
  -H "Content-Type: application/json" \
  -d '{"firstname": "Emily", "lastname": "Carter", "domain": "northwind-analytics.example", "enrichment_type": ["email", "phone"]}'
```

```json theme={null}
{
  "enrichment_id": "9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a",
  "first_name": "Emily",
  "last_name": "Carter",
  "status": "pending",
  "status_url": "https://app.pipecorn.com/api/v2/contacts/9d8c7b6a-5f4e-4d3c-8b2a-1f0e9d8c7b6a"
}
```

The response also carries a `Location` header. Poll the `status_url` with the same key and you get the finished enrichment, with an email and a phone number.

## Your own test key

Your test key is on [Settings › API keys](https://app.pipecorn.com/settings/apis/keys), under the live key. Send it in the `X-API-KEY` header like a live key. You can rotate it there at any time; the old one stops working at once.

There is no test workspace key. Use your test key in `X-API-KEY` while you build, then move to `X-WORKSPACE-KEY` when you go live.

## What the sandbox returns

* **Every documented endpoint answers**, on `app.pipecorn.com/api/v2` and on `api.pipecorn.com/v2`, with sample data in the shape the live endpoint returns. The people and companies are invented: emails use the reserved `.example` domain and phone numbers come from fictional ranges.
* **The data source follows your request.** Endpoints that search LinkedIn by default (lead and account searches, previews, headcount) return the live shape unless you send `"live": false`, as in production. [`POST /locations`](/api-reference/endpoints/miscellaneous/location-ids) follows `source`.
* **It is stateless.** A `POST` returns a sample and stores nothing. A `GET` by id returns a sample whatever the id, so a list you create will not appear in `GET /lists`.
* **Request bodies are not validated.** A request the live API would reject with a `400` or `422` can succeed in the sandbox. Use [simulated errors](#simulate-errors) to test your error handling.
* **Nothing runs in the background.** Webhooks are not sent, and async endpoints hand back their acknowledgement with no job behind it. Poll the matching `GET` to read a finished sample.
* An endpoint the sandbox has no sample for answers `404` with a link to this page.

## Simulate errors

Add the `Pipecorn-Sandbox-Status` header to any request to get the error the live API sends for that status, with the same body.

```bash theme={null}
curl https://app.pipecorn.com/api/v2/contacts/single_enrich \
  -H "X-API-KEY: pc_test_demo" \
  -H "Pipecorn-Sandbox-Status: 402" \
  -H "Content-Type: application/json" \
  -d '{"firstname": "Emily", "lastname": "Carter", "domain": "northwind-analytics.example", "enrichment_type": ["email"]}'
```

| `Pipecorn-Sandbox-Status` | You get |
| - | - |
| `400` | `{"error": "Invalid webhook_url format"}` |
| `401` | `{"error": "Invalid API key"}` |
| `402` | `{"error": "Not enough enrichment credits left", "code": "insufficient_credits", "top_up_url": "…"}` |
| `403` | `{"error": "You have reached your weekly enrichment credit limit for this workspace", "code": "workspace_limit_exceeded"}` |
| `404` | `{"error": "Resource not found"}` |
| `409` | `{"error": "A request with this Idempotency-Key is still being processed", "code": "idempotency_key_in_use"}` with `Retry-After: 1` |
| `422` | `{"error": "Can't proceed with the request. Plan limit reached."}` |
| `429` | `{"error": "Rate limit exceeded. Please wait before retrying."}` with `Retry-After: 1` |

Any other value answers `400`. See [Errors](/api-reference/errors) for what each status means.

## Rate limit

A test key allows 60 requests per minute. The demo key allows 60 per minute for each IP address. Responses carry the same `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset` headers as the live API, and a `429` adds `Retry-After`. See [Rate limiting](/essentials/rate-limiting).

## Going live

1. Replace the test key with your live key or workspace key.
2. Check that responses no longer carry `Pipecorn-Mode: test`.
3. Keep your error handling: credit, quota and rate limit errors now come from your real balance and plan.

<Tip>
  To check what a search returns on real data before you spend anything, call a preview endpoint with your live key. [Lead](/api-reference/endpoints/leads/advanced_search_preview) and [account](/api-reference/endpoints/accounts/search_preview) previews are free and return the real count and the first profiles.
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.