Storage

Backup blobs for agents, billed by the kilobyte for up to 90 days, read back by signing with the same wallet.

Livefrom $0.002 / MB / 90 daysAccepted assets: USDC, EURQ, USDQ, goBTC

Routes and prices

RouteWhat you getPrice
POST /api/v1/x402/storage/auth/challenge

Free (JSON body: wallet, plus the scope of the call it authorizes: action list / read / delete, backup_id for read and delete, optional version): mint a short-TTL, single-use nonce whose signing_message names that action, backup and site, proving control for exactly one following wallet-signature-authenticated GET/DELETE /storage/backups call (query params: wallet, nonce, signature_b64, optional proof_method). A delete needs a delete-scoped challenge. No session is ever created — sign the returned signing_message and present it fresh on the next call.

free
POST /api/v1/x402/storage/auth/nonce

Free (JSON body: wallet, plus the scope of the call it authorizes: action list / read / delete, backup_id for read and delete, optional version): mint a short-TTL, single-use nonce whose signing_message names that action, backup and site, proving control for exactly one following wallet-signature-authenticated GET/DELETE /storage/backups call (query params: wallet, nonce, signature_b64, optional proof_method). A delete needs a delete-scoped challenge. No session is ever created — sign the returned signing_message and present it fresh on the next call.

free
POST /api/v1/x402/storage/backups

Store one opaque backup blob (JSON body: base64 data, optional label; query param declared_size_bytes=<N>, capped at 10 MB, billed by the KB actually used, never rounded up to a whole MB; optional query param retention_days=<1-90>, default 90), priced at max($0.001, ceil(N/1KB) * $0.000001953125 per KB * retention_days/90). Overall remaining life is still capped at 90 days from now. Retrieve or delete it later by proving control of this same wallet again — no session. Stored content is OPAQUE: never scanned, indexed, or acted on by us. Not confidential from us, though — an operator can inspect or remove a specific backup for abuse/legal response (no other agent can read or list your backups). Encrypt sensitive data yourself before uploading if that matters to you. Need more than one version? The versions sub-route below adds a new version under this same backup_id without losing the old ones.

declared_size_bytes=2048 required
The backup's decoded size in bytes; the price is computed from it.
retention_days=90
Retention term in days.
$0.002 / MB / 90 days
GET /api/v1/x402/storage/backups

Free, wallet-signature-authenticated (query params: wallet, nonce, signature_b64, optional proof_method, from the challenge above; optional query param limit): this wallet's own active, unexpired backups, newest first.

wallet=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA required
Your address.
nonce=<nonce> required
From POST /api/v1/x402/storage/auth/nonce.
signature_b64=<base64 signature> required
Base64 signature of that response's signing_message by the wallet's key.
proof_method=signed_bytes
signed_bytes (default) or legacy_message.
limit=10
Result cap, clamped server-side.
free
GET /api/v1/x402/storage/backups/:backup_id

Free, wallet-signature-authenticated, owner-only: one backup's metadata (including current_version) plus its CURRENT version's restored bytes (base64), sha256-verified against the hash taken at upload time. See the versions sub-routes below to fetch an older version instead.

wallet=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA required
Your address.
nonce=<nonce> required
From POST /api/v1/x402/storage/auth/nonce.
signature_b64=<base64 signature> required
Base64 signature of that response's signing_message by the wallet's key.
proof_method=signed_bytes
signed_bytes (default) or legacy_message.
free
POST /api/v1/x402/storage/backups/:backup_id/renew

Extend an existing backup's retrieval window by one full 90-day term, capped at 90 days remaining from now (no request body; query param wallet=<the owning address>, a lookup hint only, never proof of ownership), priced from the backup's already-stored size at max($0.001, ceil(size/1KB) * $0.000001953125 per KB) — always a full term, never a caller-chosen shorter retention (that is create()/add-version()'s own parameter, not this route's). Works during the 2-day grace window after expiry. A backup already at the remaining-term ceiling is refused before payment. Only the wallet that created this backup may renew it: a payment from any other wallet settles but is refused and changes nothing.

wallet=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA required
The address that created this backup -- a lookup hint, never proof of ownership.
$0.002 / MB / 90 days
POST /api/v1/x402/storage/backups/:backup_id/versions

Store a NEW version's bytes under an EXISTING backup_id without discarding the versions already stored under it (query param declared_size_bytes=<N>, billed by the KB actually used; optional query param retention_days=<1-90>, default 90, priced identically to the initial store: max($0.001, ceil(N/1KB) * $0.000001953125 per KB * retention_days/90); JSON body: base64 data, optional label; wallet as a query param, same lookup-hint shape as renew above). This version becomes the backup's current content, on its own independent expiry sized by its own retention_days — older versions keep expiring on their own original schedule, and the backup's own overall retrieval window (capped at 90 days) is untouched by this call. Only the wallet that created this backup may add a version to it: a payment from any other wallet settles but is refused and changes nothing.

declared_size_bytes=2048 required
The backup's decoded size in bytes; the price is computed from it.
retention_days=90
Retention term in days.
wallet=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA required
The address that created this backup -- a lookup hint, never proof of ownership.
$0.002 / MB / 90 days
GET /api/v1/x402/storage/backups/:backup_id/versions

Free, wallet-signature-authenticated, owner-only (optional query param limit): metadata (version number, size, content_hash, created_at/expires_at) for every version of one backup, newest-version first.

wallet=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA required
Your address.
nonce=<nonce> required
From POST /api/v1/x402/storage/auth/nonce.
signature_b64=<base64 signature> required
Base64 signature of that response's signing_message by the wallet's key.
proof_method=signed_bytes
signed_bytes (default) or legacy_message.
limit=10
Result cap, clamped server-side.
free
GET /api/v1/x402/storage/backups/:backup_id/versions/:version

Free, wallet-signature-authenticated, owner-only: one specific version's metadata plus its restored bytes (base64), sha256-verified.

wallet=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA required
Your address.
nonce=<nonce> required
From POST /api/v1/x402/storage/auth/nonce.
signature_b64=<base64 signature> required
Base64 signature of that response's signing_message by the wallet's key.
proof_method=signed_bytes
signed_bytes (default) or legacy_message.
free
DELETE /api/v1/x402/storage/backups/:backup_id

Free, wallet-signature-authenticated, owner-only: delete one backup outright, every version included (row marked deleted, then connector bytes removed).

wallet=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA required
Your address.
nonce=<nonce> required
From POST /api/v1/x402/storage/auth/nonce.
signature_b64=<base64 signature> required
Base64 signature of that response's signing_message by the wallet's key.
proof_method=signed_bytes
signed_bytes (default) or legacy_message.
free

How paying works

  1. AskCall the route with no payment. It answers 402, and the PAYMENT-REQUIRED header carries the offer: amount, asset, network and the address to pay.
  2. SignSign an Algorand asset transfer for exactly that offer with your wallet. Nothing reaches the chain yet.
  3. RepeatRepeat the same call with the signed group in PAYMENT-SIGNATURE. The facilitator settles it and the response carries the result and the transaction id.

Call it

With curl you handle the 402, the signature and the retry yourself; the pxke_x402 Python client does all three inside one call.

# Store: declare the size so the price is fixed before the body is read
DATA=$(base64 -w0 state.json); SIZE=$(stat -c%s state.json)
curl -si -X POST "https://algorand-api.pxke.me/api/v1/x402/storage/backups?declared_size_bytes=$SIZE&retention_days=90" \
  -H 'Content-Type: application/json' \
  -d "{\"data\": \"$DATA\", \"label\": \"my-agent-state-backup\"}"
# -> 402 with the offer; sign it, resend the same request with PAYMENT-SIGNATURE

# Read back (free): ask for a nonce, sign it with the same wallet, present it once
curl -s -X POST 'https://algorand-api.pxke.me/api/v1/x402/storage/auth/challenge' \
  -H 'Content-Type: application/json' -d '{"wallet": "'$WALLET'"}'
curl -s "https://algorand-api.pxke.me/api/v1/x402/storage/backups/$BACKUP_ID?wallet=$WALLET&nonce=$NONCE&proof_method=signed_bytes&signature_b64=$SIG"

What comes back

A successful POST /api/v1/x402/storage/backups answers 200 with this JSON. settlement_tx_id is the Algorand transaction that paid for it.

{
  "backup_id": "7f3a9c2e-5b1d-4e8f-9a6c-2d4b8e1f0a3c",
  "size_bytes": 24576,
  "content_hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
  "label": "my-agent-state-backup",
  "created_at_epoch": 1788968366,
  "expires_at_epoch": 1796744366,
  "status": "active",
  "settlement_tx_id": "JQ3G…R5YA",
  "current_version": 1
}

Limits and notes

  • One blob per backup, up to 10 MB, sent as base64 in the JSON body. Declare its size in declared_size_bytes so the price is fixed before the body is read.
  • Priced per KB actually used, for 1 to 90 days of retention, with a small floor per write. Renewing adds a full 90-day term, capped at 90 days remaining.
  • Reads, listings and deletes are free but need a fresh signature each time: request a challenge, sign it with the same wallet, present it once.
  • Content is opaque to us and never scanned or indexed, but not confidential from an operator. Encrypt anything sensitive before uploading.

Read your backups from your wallet

List the backups your wallet stored here. Free: you sign a one-time message with the same wallet, nothing is paid and no session is kept.