The sandbox HTTP API is a complete subset of the production API, cookie-scoped per visitor. All routes run on Cloudflare Pages’ edge runtime atDocumentation Index
Fetch the complete documentation index at: https://docs.enfinitos.com/llms.txt
Use this file to discover all available pages before exploring further.
https://sandbox.api.enfinitos.com and respect a
per-IP rate limit of 10 req/10s (burst) + 200 req/hour (sustained).
Auth
Every route afterPOST /api/sandbox/tenant requires the
enf_sandbox_tenant cookie set by that initial call. The cookie
value is <tenantId>.<hmac>; tampering breaks the HMAC and the
cookie is rejected.
Tenant lifecycle
POST /api/sandbox/tenant
Provision a fresh tenant with the standard seed scenario (3 bases, 4 rights across DOOH, CTV, mobile, messaging). Idempotent — if a valid cookie is present and the tenant exists, returns the existing tenant. Response:GET /api/sandbox/tenant
Read-only tenant summary. 404 if no tenant; 410 if tenant evicted (Worker isolate eviction).POST /api/sandbox/reset
Drop the tenant + clear the cookie. Idempotent.Rights bounded context
POST /api/sandbox/rights/issue
Body:{ basisId, substrate, scope, effectiveFrom, effectiveUntil?, parentRightId? }
Issue a new right under an existing basis.
POST /api/sandbox/rights/suspend
Body:{ rightId, reason?, action?: "suspend" | "resume" }
Suspend a right (default) or resume a suspended one.
POST /api/sandbox/rights/revoke
Body:{ rightId, reason? }
Terminal — cannot be undone.
Offers
POST /api/sandbox/offers/propose
Body:{ rightId, toOrgId, scope, termsRef?, expiresAt? }
Propose an offer to share / cede / sublet a right. Default expiry
is 7 days from now.
POST /api/sandbox/offers/accept
Body:{ offerId }
Issues a derived right whose parentRightId points at the original
right and contentHash references the accepted offer.
POST /api/sandbox/offers/counter
Body:{ offerId, scope, termsRef?, expiresAt? }
Counter-offer with revised terms. Original transitions PROPOSED →
COUNTERED; a new offer goes the opposite direction with
termsRef: "counter_of:<originalOfferId>".
POST /api/sandbox/offers/withdraw
Body:{ offerId, action?: "withdraw" | "reject", reason? }
Withdraw (proposer) or reject (recipient). Both move PROPOSED to
WITHDRAWN/REJECTED respectively.
Challenges
POST /api/sandbox/challenges/open
Body:{ rightId, challengerOrgId?, reason }
Open a challenge against an active right. Default challengerOrgId
is org_thirdparty_sandbox.
POST /api/sandbox/challenges/resolve
Body:{ challengeId, upheld?, resolution?, action?: "resolve" | "withdraw" }
Resolve as upheld (revokes the right) or overturned (right stays
ACTIVE). action: "withdraw" resolves as WITHDRAWN — the challenger
backed down.
Delivery + proof
POST /api/sandbox/run-demo
Body:{ eventCount?: number (1..100, default 12), seed?: number }
Fire N synthetic delivery events with substrate-realistic dwell
times. Seals a fresh SignedProofPack containing every receipt
plus the projected metering and reconciled settlement.
POST /api/sandbox/constraint-demo
Body:{ scenario: "messaging-optout" | "automotive-speed" | "drone-remote-id-missing" }
Deliberately configure a delivery that fails the pre-render
constraint gate. Returns structured violations; no receipt is
signed. Demonstrates real compliance enforcement.
GET /api/sandbox/proof-packs
List sealed packs (summaries only). Newest last.GET /api/sandbox/proof-packs/[packId]
Full pack JSON plus the sandboxVerificationKey. The verification
key is embedded so an offline auditor can verify without a second
round-trip.
Provenance + inspector
GET /api/sandbox/provenance?rightId=…
Returns the lineage chain — basis → root right → derived rights → target right.GET /api/sandbox/inspect
Full read-only tenant snapshot — every basis, right, offer, challenge, event, pack header. Consumed by the Tenant Inspector UI.Verification keys
GET /api/sandbox/runtime-keys
Public, unauthenticated. Returns the sandbox’s verification-key directory. The auditor SDK consumes this to verify sandbox-issued packs.Error responses
Every error returns the same envelope:| Code | Meaning |
|---|---|
NO_TENANT | Cookie missing — call POST /api/sandbox/tenant first. |
TENANT_EVICTED | Worker isolate evicted the tenant. Hit Reset and start fresh. |
INVALID_BODY | Body wasn’t valid JSON. |
MISSING_FIELDS | Required body fields not supplied. |
RATE_LIMITED | Per-IP quota hit. Respect the Retry-After header. |
HANDLER_ERROR | Server-side exception (e.g. state-machine refusal). The message carries the structured cause. |
UNKNOWN_SCENARIO | constraint-demo scenario string isn’t recognised. |