# dockage.ai

**S3 for AI agents, minus the signup.** Blob storage on [Walrus](https://walrus.xyz),
paid in USDC over [x402](https://x402.org). No account, no API key, no session —
a keypair and a balance is the entire setup.
*A [mindfulagents](https://github.com/mindfulagents) project.*

> **Storage here is a lease, not a bucket.** You buy epochs — 14 days each on
> mainnet, up to 53 in a single purchase, about two years — then renew before
> expiry or the data is gone. Reads stay free for the whole lease, from anywhere.

> Running on **Sui mainnet + Walrus mainnet** — payments are real USDC. One epoch = 14 days.

## Try it now — no wallet, no signup

Pricing is free. It needs no account, no key, and none of your bytes:

```sh
curl -s -X POST https://dockage.ai/v1/quote \
  -H 'content-type: application/json' \
  -d '{"files":[{"size":2048}],"epochs":10}'
```

You get HTTP **402** carrying a signed quote and x402 payment requirements. The
402 is the success case here — the quote *is* the payment challenge.

Reading is free too, and it does not have to go through us. Every receipt carries
`read.aggregatorUrlTemplate`; put your `blobId` in it and fetch straight from a
public Walrus aggregator:

```sh
curl -s https://aggregator.walrus-mainnet.walrus.space/v1/blobs/YOUR_BLOB_ID
```

Same bytes, dockage.ai out of the path entirely. That is the whole lock-in story:
we sell quoting, payment plumbing and ergonomics — never custody of your data.

## What it costs

On mainnet, **$0.25 stores anything up to about 10 MiB for one epoch — or for ten.**

Walrus encodes every blob across 1,000 shards, which adds a fixed overhead of
roughly 61 MiB before your own bytes are counted. Below ~10 MiB your actual size
barely moves the price, and nearly every small store lands exactly on the $0.25
mainnet floor (testnet's floor is $0.01). So batch: 100 small files in one quilt
cost about what one small file costs.

Never guess — `POST /v1/quote` is free and authoritative. Live rates and worked
examples: [/stats](/stats).

## Is this for you?

**Good fit** — agent memory and artifacts, datasets, model outputs, build
outputs, anything content-addressed, anything you want readable without your own
infrastructure running.

**Look elsewhere if** you need to change or delete an object after writing (blobs
are immutable and public until they expire), you need private-by-default (encrypt
client-side first, or use something else), you need storage that never needs
renewing, or you are writing many tiny objects one at a time — the floor will
dominate your bill.

## Start

Two independent choices: **which rail you pay on**, and **which way you drive the
API**. The rail decides what you have to hold.

### Pick a rail

**Base — gasless.** Hold USDC on Base and nothing else: no gas token, ever.
Declare a Sui `owner` in the quote, because an EVM address means nothing on Sui.
Ask for it with `"payWith":"base"`. Reachable over **HTTP only**, today.

**Sui — the default.** Hold USDC on Sui *plus a little SUI*, because you sign and
pay for your own payment transaction. The blob owner defaults to you. This is the
only rail the SDK and the MCP tools can reach.

Quotes are rail-bound: the token fixes which rail you may pay, and paying the
wrong one fails before any money moves. Full comparison, wire formats and failure
semantics: [/docs](/docs).

### Pick a way in

**MCP — hosted, zero install.** Claude Desktop: Settings → Connectors → *Add
custom connector* → `https://dockage.ai/mcp`. Claude Code:
`claude mcp add --transport http dockage https://dockage.ai/mcp`. Cursor:
`{"mcpServers":{"dockage":{"url":"https://dockage.ai/mcp"}}}`. `quote`,
`fetch` and `list` need no wallet at all. `store`, `store_batch` and
`extend` need an agentic wallet holding **USDC on Sui plus a little SUI for
gas**: the tool returns a quote and signing instructions, your wallet signs
locally, you call again with `quote` + `payment`.

**HTTP — any language, either rail.** The only route to Base. Quote with
`"payWith":"base"` and a Sui `owner`, sign the EIP-712
`TransferWithAuthorization`, submit it base64 in `PAYMENT-SIGNATURE`. Wire
formats for both rails: [/docs](/docs).

**TypeScript SDK — `@dockage/sdk`.** `new DockageClient({baseUrl,
signer:{secretKey, network:"mainnet"}})`, then `.store()` / `.extend()` /
`.list()` — it runs the whole x402 dance. Ships from the repo, not npm. Sui
rail only.

## How it works

1. `POST /v1/quote` with declared file sizes and epochs. Back comes a signed
   quote token and x402 payment requirements (HTTP 402). No bytes needed to
   price — cost is a deterministic function of size.
2. Sign a USDC payment matching one of the `accepts` entries. Quotes last ~45
   seconds and are single-use.
3. `POST /v1/store` as multipart: the bytes, the signed **quote token** in a
   `quote` field, and your payment in the `PAYMENT-SIGNATURE` header. We store
   on Walrus and mint a `SharedBlob` plus a `StorageReceipt` **to your
   address** — those storage transactions are gas-sponsored by us.
4. You get a fat receipt. Cache it: `blobId` reads back free from any
   aggregator until `endEpoch`, and `suiObjectId` is your renewal handle.

## Things you should know

- **The receipt is the database.** We keep zero rows about you. "What did I
  store?" is a Sui query for objects your address owns —
  `GET /v1/receipts?owner=0x…`.
- **Renewal is permissionless.** Anyone who knows a `suiObjectId` can pay to
  extend it, so you can never be locked out of renewing your own data.
- **Lost keypair = lost renewal rights, not lost data.** Reads keep working until
  expiry because the `blobId` is public. Nobody, including us, can transfer
  ownership.
- **Quilts share one expiry.** Files batched in one call become one object with
  one end epoch; extension is all-or-nothing across the quilt. Batch by
  lifecycle.
- **We never encrypt and never hold keys.** Walrus content is public — encrypt
  client-side before upload if that matters.
- **Retries are safe.** Store is idempotent on the quote and on the content. If a
  payment settles but storage fails, you are **auto-refunded** on Sui, or issued
  a durable credit on Base to redeem with `X-DOCKAGE-CREDIT`.

## API surface

| Method | Path | What |
|---|---|---|
| POST | /v1/quote | Price files from declared sizes → signed quote + x402 requirements |
| POST | /v1/store | Bytes + quote token + payment → receipt (N files → one quilt) |
| POST | /v1/extend/quote | Price extending a blob or quilt → signed quote |
| POST | /v1/extend | Pay the extend quote → storage extended |
| GET | /v1/blobs/{blobId} | Read a blob — free, redirects to a public aggregator |
| GET | /v1/quilts/{quiltId}/{identifier} | Read one file from a quilt — free |
| GET | /v1/receipts?owner=0x… | Your holdings, rebuilt live from Sui |
| GET | /v1/credits?payer=0x… | Open credits from a failed Base-paid store |
| GET | /v1/health | Network, current WAL rate, epoch info |
| GET | /v1/stats | Live price sheet, treasury, recent activity |

Full reference with request and response shapes: [/docs](/docs).

## For agents

- **Auth: none.** No key to register, no header to obtain. Identity is a Sui
  address; authorization is a signed payment.
- **To pay on Sui** hold USDC on Sui plus a little SUI for your payment
  transaction's gas. **To pay on Base** hold only USDC and declare a Sui
  `owner` — Base is gasless, but HTTP-only today.
- x402 network ids to match against `accepts`: `sui:mainnet` and
  `eip155:8453` on mainnet; `sui:testnet` and `eip155:84532` on testnet.
- This page as markdown: `GET /` with any non-HTML `Accept`, or
  `GET /llms.txt`. Full reference: `GET /docs`.
- Errors are structured JSON — `{code, message, retryable}`, e.g.
  `QUOTE_EXPIRED`, `SIZE_MISMATCH`, `PAYMENT_INVALID`,
  `STORE_FAILED_REFUNDED`.
- Limits: 100 MB per file, 500 files and 500 MB per quilt, 1–53 epochs, quotes
  expire in 45 seconds.
