API guides

Sandbox

A seeded counterparty to practice against — reads, writes, both sides.

The API isn’t switched on in this environment yet. Everything below is accurate; the examples come from the published contract rather than a live read.

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:

Provision (idempotent — one pair per organization)
From the published contract
curl -X POST "https://api.rivet.network/v1/sandbox" \
  -H "Authorization: Bearer rk_live_…"
SandboxState
FieldTypeNotes
status*stringready, provisioning or resetting.
sandbox_org_id*string"{Your org} Sandbox" — the organization your rk_test_ keys act as.
demo_org_id*stringRiveted Demo Co, the seeded counterparty.
connection_id*stringThe pair's connection.
counts*objectDocuments and catalog items currently in the pair.
quota*objectdocuments_used / documents_max — reset clears it.
created_at*stringWhen the pair was provisioned.
last_reset_at*string | nullThe 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.

The counterparty acts
From the published contract
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/reset wipes 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_quota with the reset hint.
  • Test keys draw from a lower rate bucket than live keys.
  • DELETE /v1/sandbox tears 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:read scope on a test key answers capability_unavailable with a message that says why.
Keys minted before this rule existed are 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.