Sandbox
A published test key and a small fixed dataset, so a client can be built, tested and reviewed before anyone buys a plan — and so a customer can exercise a retry path without spending production quota. Same envelope, same field names, same error codes as the live API.
First call
No account, no signup, no key request. Paste this.
curl "https://commonelements.com/api/v1/meta/sandbox/associations" \
-H "Authorization: Bearer ce_test_sandbox"The key is public on purpose. ce_test_sandbox unlocks nothing but the records below, is attached to no organization, and does not work against the production API. It is safe to commit to your own repository and to put in a shared example.
Authentication is still real. A request with the wrong key gets the production invalid_api_key envelope, because the point of a sandbox is to prove your auth wiring works before it is pointed at a key that costs money.
The manifest is machine-readable too, at GET /api/v1/meta/sandbox — key, base URL, routes, test ids and simulation codes in one JSON document.
What is in it
Small and fixed. Values never move, so an assertion written against it today still passes next quarter. Every record is fabricated: no association, vendor, licensee or person in the sandbox corresponds to a real one.
| associations | 3 |
| vendors | 2 |
| statute sections | 2 |
| licences | 1 |
| change events | 3 |
Ids worth knowing
- association condo
- 00000000-0000-4000-8000-000000000001
- association hoa
- 00000000-0000-4000-8000-000000000002
- association coop null unit count
- 00000000-0000-4000-8000-000000000003
- association always 404
- 00000000-0000-4000-8000-000000000404
- vendor
- 00000000-0000-4000-8000-000000000101
00000000-0000-4000-8000-000000000404 always returns 404. The cooperative always returns a null unit_count, because the live API withholds a low-confidence count and a client that cannot handle that null will break in production rather than here.
Routes it mirrors
A representative subset, enough to exercise a list, a detail record, a sub-resource, a filter and a search. Paths below are relative to /api/v1/meta/sandbox.
- GET /associations
- GET /associations/lookup
- GET /associations/match?name=
- GET /associations/nearby
- GET /associations/{id}
- GET /associations/{id}/officers
- GET /associations/{id}/building-safety
- GET /associations/{id}/vendors
- GET /vendors
- GET /vendors/{id}
- GET /statutes/by-state?state=
- GET /statutes/search?q=
- GET /changes
- GET /changes/summary
- GET /professionals/search
- GET /licenses/verify?license_number=
Simulating failures
Append ?simulate=<code>to any sandbox path to get that error’s real envelope and status. Test a backoff without waiting for a real 429, and a plan-gate branch without buying two plans.
curl -i "https://commonelements.com/api/v1/meta/sandbox/associations?simulate=quota_exceeded" \
-H "Authorization: Bearer ce_test_sandbox"
# HTTP/1.1 429 Too Many Requests
# { "ok": false, "error": "quota_exceeded", "message": "…", "next_steps": "…" }| Status | simulate= | What it lets you test |
|---|---|---|
| 400 | validation_error | Invalid request |
| 401 | invalid_api_key | Key missing, malformed, or revoked |
| 403 | scope_not_allowed | Key lacks the required scope |
| 403 | tier_not_allowed | Plan does not include this endpoint |
| 404 | not_found | No such record |
| 429 | quota_exceeded | Monthly request quota used up |
| 500 | internal_error | Unexpected server error |
Going live
Two lines. Nothing else in your client changes.
- const BASE_URL = "https://commonelements.com/api/v1/meta/sandbox";
- const API_KEY = "ce_test_sandbox";
+ const BASE_URL = "https://commonelements.com/api/v1";
+ const API_KEY = process.env.CE_API_KEY; // ce_live_… from /settings/api-keysGet a live key at API keys settings, then read the endpoint reference for the full surface, or import the OpenAPI document and generate a client.