HTTP API
The OpenAPI 3.1 path is the canonical machine contract. It does not itself announce production availability; if prose differs, stop and report the mismatch to [email protected].
The durable origin is https://agentbox.link. Public paid-write availability is separately gated. The Worker, generated OpenAPI contract, companion Base Mainnet client, and 10,000-settlement calendar-month cap must be released together before these docs are deployable as production truth.
Payment contract
Section titled “Payment contract”Production creation uses x402 v2 exact on Base Mainnet (eip155:8453) with canonical Base USDC at 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913, six decimals, and exact amount 10000 atomic units. The production payee must be pinned by an approved release. The service never needs the payer private key.
The payment is bound to the canonical method, absolute resource, JSON body, idempotency key, network, asset, amount, and payee. A payment credential cannot create another box.
POST /v1/boxes
Section titled “POST /v1/boxes”First request headers:
Content-Type: application/jsonIdempotency-Key: 5ae38ce4-2f5d-4dae-863c-d0fc0e29476c{ "ciphertextSize": 1234, "ciphertextSha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"}The service validates before advertising payment. A valid unpaid request returns 402 with x402 v2 PAYMENT-REQUIRED. The paid retry repeats the exact request and adds:
PAYMENT-SIGNATURE: <x402-v2-payment-authorization>X-AGENTBOX-REQUEST-COMMITMENT: <payer-eip191-signature>The commitment signs the canonical create request, including method, absolute resource, exact canonical body, and idempotency key. A successful, independently evidenced payment returns 201, optional PAYMENT-RESPONSE, timestamps, and three independent capability objects: upload, download, and delete.
PUT /v1/boxes/{boxId}
Section titled “PUT /v1/boxes/{boxId}”Authorization: Bearer <write-capability>Content-Type: application/octet-streamContent-Length: <exact-ciphertext-byte-count>The body must be 1 byte through 10 MiB and match both the length and SHA-256 declared at creation. One successful upload returns 204. A ready box cannot be replaced or appended to.
HEAD /v1/boxes/{boxId}
Section titled “HEAD /v1/boxes/{boxId}”Use Authorization: Bearer <read-capability>. A ready box returns 200 with:
Content-LengthContent-Type: application/octet-streamX-Agentbox-Sha256X-Agentbox-Created-AtX-Agentbox-Expires-At
No payload body, filename, source media type, or recipient identity is returned.
GET /v1/boxes/{boxId}
Section titled “GET /v1/boxes/{boxId}”Use the read capability. A ready, unexpired box returns the exact ciphertext as application/octet-stream plus the same integrity and timestamp headers as HEAD. Downloads are repeatable before expiry, subject to rate limits.
DELETE /v1/boxes/{boxId}
Section titled “DELETE /v1/boxes/{boxId}”Use Authorization: Bearer <delete-capability>. Success returns 204 and makes the box immediately inaccessible at the logical service boundary. Physical object removal is asynchronous.
Limits
Section titled “Limits”| Limit | Durable value |
|---|---|
| Ciphertext | 1 byte to 10 MiB |
| Create JSON body | 16 KiB maximum |
| Lifetime | 24 hours from creation |
| Live capacity | 500 boxes |
| New creates | 60/minute per Cloudflare client IP |
| Signed capacity-reclaim retries | 84/minute per Cloudflare client IP |
| Capability operations | 120/minute per Cloudflare client IP |
| Successful production settlements | 10,000/calendar month hard ceiling |
When creation capacity, payment proof, storage state, or a control cannot be proven, creation fails closed. Existing authorized reads and deletes should remain available where safe.
Structured errors
Section titled “Structured errors”JSON error responses use:
{ "error": { "code": "stable_machine_code", "message": "safe summary", "requestId": "opaque identifier", "retryable": false }}| HTTP | Stable codes |
|---|---|
400 |
invalid_request |
401 |
invalid_capability, replay_credential_required |
402 |
payment_required, payment_invalid |
404 |
not_found |
409 |
idempotency_conflict, payment_pending, payment_replay, box_not_writable |
410 |
deleted, expired |
413 |
blob_too_large |
422 |
integrity_mismatch |
429 |
rate_limited, capacity_exhausted |
503 |
capacity_reclaiming, creation_disabled, facilitator_unavailable, payment_unavailable, storage_unavailable |
Honor the retryable field, but retry paid creation only with the identical request, idempotency key, ciphertext, and signed payment authorization. A retryable error does not make a changed request safe.