RIG logo markRIG.
Install
Docs

RIG API

Every agent run returns a verdict and a refutable receipt. This page is the whole contract: four endpoints, one error model, zero happy-path-only examples. Base URL https://api.rig.run.

Quickstart

Zero to a verified run in four steps. Every command below is real — paste it, expect the output shown.

1

Authenticate — device flow

No browser dance on headless boxes. rig auth login prints a code, you approve it once, the CLI holds the session.

terminal
$ rig auth login
→ open https://rig.run/device and enter code WDXK-72Q4
waiting for approval…
✓ authenticated as ops@acme.dev (workspace: acme-prod)
session written to ~/.rig/session (0600)
2

Install an agent

Installs are pinned to a content hash. The workspace token printed here is what your services send as Authorization — it is shown once.

terminal
$ rig install prior
prior@2.4.1  hash a91f3e2  2.1 MB
✓ installed · 12,412 active installs · 99.4% sealed rate

workspace token (shown once, store it now):
  rig_ws_7Kd29mXq4FvN8bL0hJ3cP1sR
3

First invoke

Synchronous for runs under the timeout. The response always carries a proof_packet — that's the receipt, not a nice-to-have.

request
$ curl -s https://api.rig.run/v1/invoke \
    -H "Authorization: Bearer rig_ws_7Kd29mXq4FvN8bL0hJ3cP1sR" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: fc-2026-08-05-q3-rev" \
    -d '{
      "agent": "prior",
      "version": "2.4.1",
      "input": { "question": "Q3 revenue, services line, ±5% band" }
    }'
200 · response
{
  "run_id": "run_f41c8a2",
  "agent": "prior",
  "version": "2.4.1",
  "verdict": "APPROVED",
  "output": { "forecast": 4120000, "band": [3914000, 4326000], "brier": 0.041 },
  "proof_packet": {
    "id": "pkt_9d2b7c1",
    "hash": "9d2b7c1",
    "prev_hash": "e58a0d4",
    "sealed_at": "2026-08-05T14:22:07Z",
    "verifier": "gate@1.4.7"
  },
  "duration_ms": 1843
}
4

Verify the packet yourself

Don't take the API's word. Fetch the packet and re-check the hash chain — three lines of shell:

terminal
$ curl -s https://api.rig.run/v1/proof/pkt_9d2b7c1 \
    -H "Authorization: Bearer rig_ws_7Kd29mXq4FvN8bL0hJ3cP1sR"
{
  "id": "pkt_9d2b7c1",
  "hash": "9d2b7c1",
  "prev_hash": "e58a0d4",
  "payload_sha": "3f8c…",
  "status": "SEALED"
}

# chain check: hash must equal sha256(prev_hash + payload_sha)[:7]
$ echo -n "e58a0d43f8c…" | shasum -a 256 | cut -c1-7
9d2b7c1  ✓ matches — chain intact

If those 7 chars don't match, the packet was tampered with or the ledger forked. Either way: stop, don't ship.

Auth

One token type, sent one way:

header
Authorization: Bearer rig_ws_7Kd29mXq4FvN8bL0hJ3cP1sR
  • rig_ws_* workspace tokens — full API access, shown once at rig install, rotate with rig auth rotate.
  • Tokens are scoped per workspace; a token from acme-prod returns 401 against acme-staging resources, not a confusing empty list.
  • Last four characters are returned in every error body and log line for correlation — the rest never leaves the wire.
  • Rotation invalidates the old token after a 60s overlap window. In-flight runs finish; new invokes need the new token.

Errors

Every error body has the same shape: code, message, request_id, plus error-specific fields. The status code is never the whole story — read the body.

StatusCodeMeaning / extra fields
401invalid_tokenToken missing, expired, or wrong workspace. extra: token_last4
402limit_reachedMonthly run quota exhausted. extra: upgrade_url — go to /site/pricing.html or the runs hard-stop at the boundary
409idempotency_conflictSame Idempotency-Key, different payload. extra: original_run_id
422schema_violationInput failed the agent's schema. extra: pointer (JSON Pointer to the offending field)
423verifier_refutedThe run executed but the verifier refuted the output. extra: reason, packet_id
429rate_limitedToo many requests. extra: retry_after (seconds)
500runtime_faultOur side broke. extra: incident_id — quote it to support

423 verifier_refuted — the error that is the product

Any agent framework can return 200 with plausible garbage. RIG returns 423 when the independent verifier replays the run and the output doesn't hold. The response tells you why, and hands you the packet that proves the refutation — so your pipeline fails closed instead of shipping a confident lie.

423 · response body
HTTP/1.1 423 Locked
Content-Type: application/json

{
  "code": "verifier_refuted",
  "message": "gate@1.4.7 refuted prior@2.4.1 output: forecast band excludes stated evidence range",
  "reason": "claimed band [3914000, 4326000] but cited source rng_7c2e914 reports [4031000, 4480000]; lower bound contradicts evidence",
  "packet_id": "pkt_4a7e1f0",
  "packet_hash": "4a7e1f0",
  "run_id": "run_b82d5c3",
  "request_id": "req_2f60aa9",
  "refuted_at": "2026-08-05T14:26:41Z",
  "dispute_url": "https://api.rig.run/v1/proof/pkt_4a7e1f0/dispute"
}
Handle this explicitly. A 423 is not a retry. Route it to a human or re-run with corrected input — the reason field is written for engineers, not logs. If you believe the verifier is wrong, POST to dispute_url; the dispute and its resolution are appended to the same hash chain.

/v1/invoke

POST Run an agent. Synchronous up to 120s; longer runs return 202 with a run_id to poll via /v1/status.

Parameters

FieldTypeRequiredDescription
agentstringrequiredAgent name: prior · judge · gate · route · harvest · guard · draft · mesh
versionstringoptionalPin, e.g. "2.4.1". Default: latest installed in workspace
inputobjectrequiredAgent-specific; must satisfy the agent's published schema or 422
timeout_msintegeroptional1,000–120,000. Default 30,000
Idempotency-KeyheaderrecommendedSafe retries; see Idempotency
request
$ curl -s https://api.rig.run/v1/invoke \
    -H "Authorization: Bearer rig_ws_7Kd2…" \
    -H "Idempotency-Key: daily-brief-2026-08-05" \
    -d '{"agent":"harvest","version":"0.8.3",
         "input":{"target":"competitor.io","since":"2026-07-29"}}'
200 · response (abridged)
{
  "run_id": "run_6e1c04b",
  "verdict": "APPROVED",
  "output": { "signals": 14, "sourced": 14 },
  "proof_packet": { "id": "pkt_7f3b9a2", "hash": "7f3b9a2", "prev_hash": "9d2b7c1" },
  "duration_ms": 2210
}

/v1/status

GET /v1/status/{run_id} — poll an async run. Poll no faster than 1/s; the packet appears exactly once, on the terminal state.

FieldTypeRequiredDescription
run_idpathrequiredFrom invoke, e.g. run_6e1c04b
request + response
$ curl -s https://api.rig.run/v1/status/run_6e1c04b \
    -H "Authorization: Bearer rig_ws_7Kd2…"
{
  "run_id": "run_6e1c04b",
  "state": "verifying",   // queued → running → verifying → sealed | refuted
  "elapsed_ms": 1104
}

/v1/proof

GET /v1/proof/{packet_id} — the receipt. Hash, parent hash, payload digest, verifier version, timestamps. Everything you need to verify without trusting us.

FieldTypeRequiredDescription
packet_idpathrequirede.g. pkt_9d2b7c1
formatqueryoptionaljson (default) · pem (signed bundle for audit archives)
response
{
  "id": "pkt_9d2b7c1",
  "hash": "9d2b7c1",
  "prev_hash": "e58a0d4",
  "payload_sha": "3f8c2a91d07e…",
  "agent": "prior@2.4.1",
  "verifier": "gate@1.4.7",
  "status": "sealed",
  "sealed_at": "2026-08-05T14:22:07Z",
  "chain_height": 184,207
}

POST /v1/proof/{packet_id}/dispute — contest a sealed or refuted packet. The dispute joins the chain; it is never edited in place.

/v1/export

GET /v1/export — bulk-dump packets for your own audit trail. Streams NDJSON; resume with the cursor.

FieldTypeRequiredDescription
sincequeryoptionalISO-8601, e.g. 2026-08-01T00:00:00Z
agentqueryoptionalFilter to one agent
statusqueryoptionalsealed · refuted · disputed
cursorqueryoptionalFrom previous page's next_cursor
limitqueryoptional1–1,000. Default 500
request
$ curl -s "https://api.rig.run/v1/export?since=2026-08-01T00:00:00Z&status=refuted&limit=100" \
    -H "Authorization: Bearer rig_ws_7Kd2…"
{"id":"pkt_4a7e1f0","hash":"4a7e1f0","prev_hash":"b31c8e6","status":"refuted",…}
{"id":"pkt_c90d2f4","hash":"c90d2f4","prev_hash":"4a7e1f0","status":"refuted",…}
# headers: X-RIG-Next-Cursor: cur_8841de2 · X-RIG-Chain-Head: 184,207

Webhooks

Register an endpoint with rig webhooks add <url>. Events delivered at-least-once, ordered per workspace, retried with backoff for 24h.

EventFires when
agent.completedRun reaches a terminal state (sealed or refuted)
verifier.refutedA 423 occurred — payload includes reason + packet_id
packet.sealedA packet joins the hash chain
drift.alertguard detects output drift beyond its determinism band
example payload · packet.sealed
POST /your-endpoint
X-RIG-Signature: t=1754413327,v1=8f2c1a4b…
X-RIG-Event: packet.sealed

{
  "event": "packet.sealed",
  "packet_id": "pkt_9d2b7c1",
  "hash": "9d2b7c1",
  "prev_hash": "e58a0d4",
  "agent": "prior@2.4.1",
  "sealed_at": "2026-08-05T14:22:07Z"
}

Verify the signature

Every delivery is HMAC-signed with your webhook secret (rig webhooks reveal). Four lines, no SDK required:

python
import hmac, hashlib
signed = f"{t}.{raw_body}".encode()
expect = hmac.new(SECRET, signed, hashlib.sha256).hexdigest()
assert hmac.compare_digest(expect, v1)  # reject if it raises
Reject old timestamps. Discard any t more than 5 minutes old before comparing — that's your replay protection.

SDKs

install
$ npm install @rig/sdk
$ pip install rig-sdk
typescript
import { Rig } from "@rig/sdk";

const rig = new Rig({ token: process.env.RIG_TOKEN! });

const run = await rig.invoke("prior", {
  version: "2.4.1",
  input: { question: "Q3 revenue, services line" },
  idempotencyKey: "q3-rev-2026-08-05",
});

if (run.verdict !== "APPROVED") {
  throw new Error(`refuted: ${run.refutation?.reason} (pkt ${run.refutation?.packetId})`);
}
await rig.verifyPacket(run.proofPacket.id); // re-checks the hash chain locally

The SDK never swallows a 423 — it surfaces as a typed RefutedError with reason and packetId. Retries with backoff are built in for 429/500 only.

Rate limits

  • 60 requests/min per workspace token; 10 concurrent invokes.
  • Every response carries X-RIG-RateLimit-Remaining and X-RIG-RateLimit-Reset (unix seconds).
  • On 429, honor retry_after in the body — it's exact, not advisory. Exponential backoff on top of it is fine; ignoring it gets the token throttled to 10/min for an hour.
  • Webhooks and /v1/export don't count against the invoke limit.

Idempotency

Send Idempotency-Key on every invoke. Keys are scoped to (workspace, agent) and live 24h.

  • Same key + same payload → the original response replayed, header X-RIG-Replay: true, no second run, no second charge.
  • Same key + different payload → 409 idempotency_conflict with the original_run_id. Never silently reuses your key.
  • A replayed response includes the original proof packet — the receipt is stable, that's the point.

Pagination

Cursor-based everywhere (/v1/export, run history, dispute lists). No offsets — offsets lie on a moving ledger.

terminal
$ curl -s "https://api.rig.run/v1/export?limit=2" \
    -H "Authorization: Bearer rig_ws_7Kd2…"
{"id":"pkt_9d2b7c1",…}
{"id":"pkt_7f3b9a2",…}
# → X-RIG-Next-Cursor: cur_8841de2

$ curl -s "https://api.rig.run/v1/export?limit=2&cursor=cur_8841de2" \
    -H "Authorization: Bearer rig_ws_7Kd2…"

An empty X-RIG-Next-Cursor header means you're at the chain head. Cursors expire after 1h — re-issue with since to resume.