HTTP API
The OpenAPI 3.1 path is the canonical machine contract for the live public beta. If prose differs, stop and report the mismatch to [email protected].
The production origin is https://agtbox.dev. Check the troubleshooting guide before retrying an availability failure. Creation can be stopped independently while authorized reads and deletes remain available.
Payment contract
Section titled “Payment contract”Production creation uses x402 v2 exact on network eip155:8453 with canonical USDC at 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913, six decimals, exact amount 10000 atomic units, and payee 0xb5363EDDE479640886cf708BC596F2aED09806A8. Use the pinned public CLI to validate this tuple. 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-AGTBOX-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-agtbox-Sha256X-agtbox-Created-AtX-agtbox-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 client IP |
| Signed capacity-reclaim retries | 84/minute per client IP |
| Capability operations | 120/minute per 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.