Your sandbox comes with a counterparty. Provisioning creates a pair: “{Your org} Sandbox” — the organization your test keys act as — already connected to Riveted Demo Co, seeded with a small catalog, one incoming invoice (your first read is a Bill) and one draft to edit and issue. Documents in Rivet are bilateral; a sandbox without a counterparty would have nothing true to show you.
Sandbox — coming
The sandbox isn't switched on in this environment yet — the endpoints below answer not_enabled until it is. The contract they will keep:
curl -X POST "https://api.rivet.network/v1/sandbox" \
-H "Authorization: Bearer rk_live_…"| Field | Type | Notes |
|---|---|---|
| status* | string | ready, provisioning or resetting. |
| sandbox_org_id* | string | "{Your org} Sandbox" — the organization your rk_test_ keys act as. |
| demo_org_id* | string | Riveted Demo Co, the seeded counterparty. |
| connection_id* | string | The pair's connection. |
| counts* | object | Documents and catalog items currently in the pair. |
| quota* | object | documents_used / documents_max — reset clears it. |
| created_at* | string | When the pair was provisioned. |
| last_reset_at* | string | null | The last reset, if any. |
Being both sides
You drive your side with the sandbox organization's own rk_test_ key — every read and write endpoint behaves exactly as it does live. When it's the counterparty's turn, ask it to act: the advance endpoint has Riveted Demo Co perform its next legal action on a document (acknowledge, approve — whatever the document's own state machine offers that side), through the same service layer the app uses. No timers, nothing autonomous: it acts when you say so, and the response names what it did.
curl -X POST "https://api.rivet.network/v1/sandbox/counterparty/advance" \
-H "Authorization: Bearer rk_live_…" \
-H "Content-Type: application/json" \
-d '{"document_id":"6a5eed00000000000000d001"}'When the counterparty has no legal move, you get 409 conflict with details.allowed — possibly empty — instead of an invented action.
Reset and quotas
POST /v1/sandbox/resetwipes the pair's documents and catalog and reseeds the originals; the organizations, connection and keys survive. Safe to repeat.- The pair holds up to 500 documents; at the cap, creates answer
429 sandbox_quotawith the reset hint. - Test keys draw from a lower rate bucket than live keys.
DELETE /v1/sandboxtears the pair down completely — a fresh one can be provisioned after.
Isolation
Key prefixes follow the organization: a sandbox organization mints rk_test_, a live organization mints rk_live_, and the two are hard-isolated — a test key presented against live data (or a live key against a sandbox) is refused with 403 sandbox_isolation, before scopes, before anything.
- A sandbox never sends email — no notifications, no invites, nothing.
- It never touches billing: nothing a sandbox does is ever invoiced.
- Treasury is never available in sandbox — a
treasury:readscope on a test key answerscapability_unavailablewith a message that says why.
rk_test_ on live organizations; the isolation wall refuses them with sandbox_isolation — create a replacement key in Settings → Developers (or via the API) and swap it in.