# deed.page docs

Publish a deed: one request turns files into a permanent public URL. Built for agents; no human step anywhere.

Publish a folder or a few files to a live, permanent HTTPS URL with one PUT or POST. No account, no email code, no claim link, no 24-hour expiry. The agent chooses the slug. Use when asked to "publish this", "host this", "deploy this", "share this on the web", "make a website", "put this online", "create a webpage", or "generate a URL", or when a 24-hour anonymous link is not enough.

base_url: https://deed.page
openapi: https://deed.page/openapi.json
mcp: https://deed.page/mcp
skill: https://deed.page/skill.md

## Quick start

    echo '<!doctype html><h1>Hello</h1>' > index.html
    curl -T index.html "https://deed.page/v1/sites?slug=hello"

Response (201 on create, 200 on update):

    {"ok":true,"url":"https://hello.deed.page/","path_url":"https://deed.page/s/hello/","slug":"hello","version":"v1","unchanged":false,"permanent":true,"expires_at":null,"bytes":31,"files":1,"plan":"free","token":"deed_tok_...","token_note":"Shown once..."}

`url` is the subdomain form when you publish through deed.page; `path_url` (/s/{slug}/) always works.

## Authentication

- None to publish. No account, email code, or claim link.
- The first publish without a token mints one and returns it once as `token`. Save it (for example `export DEEDPAGE_TOKEN=deed_tok_...`).
- Send `Authorization: Bearer $DEEDPAGE_TOKEN` to update, list, delete, or upgrade. Publishing new slugs with the same token keeps them under one owner.
- Lose the token and you cannot update that slug. There is no recovery by email because we never collect one.

## Publishing

`PUT` and `POST` are the same operation on `/v1/sites` and `/v1/sites/{slug}` (also under `/api/v1/`).

Bodies:

- gzip tarball or plain tar (`curl -T site.tar.gz`). One wrapper directory is stripped.
- a single HTML file (`curl -T index.html`) becomes index.html.
- `multipart/form-data`: one archive, or many files (field filename = path).
- `application/json`: `{"files":{"index.html":"<h1>hi</h1>","logo.png":{"base64":"iVBOR..."}}}`

Headers (or query params):

| Header | Query | Meaning |
| --- | --- | --- |
| X-Slug | slug | Slug to publish to (1-63 chars, a-z 0-9 -). Random if omitted. |
| Authorization | | Bearer token for updates. |
| X-Merge | merge | 1 = add these files to the current version instead of replacing it. |
| X-Spa | spa | 1 = serve index.html for unknown paths. |
| X-Ttl | ttl | Seconds until the site expires. Omit for permanent. |
| Idempotency-Key | | Replays the same response for retries. |
| X-Client | | Your harness name (cursor, claude-code, codex...). |

Directory tarball:

    tar -C ./site -czf /tmp/site.tar.gz .
    curl -T /tmp/site.tar.gz "https://deed.page/v1/sites?slug=my-app" -H "Authorization: Bearer $DEEDPAGE_TOKEN"

JSON:

    curl -X POST "https://deed.page/v1/sites" -H 'content-type: application/json' \
      -d '{"slug":"my-app","files":{"index.html":"<!doctype html><h1>hi</h1>"}}'

### Large sites

Each request body is capped at 4 MB (a serverless platform limit). Send the first chunk normally, then the rest with `X-Merge: 1` and your token; each merge publish adds or overwrites paths and bumps the version. Total size per site is set by your plan.

## Serving

- `https://{slug}.deed.page/` and `https://deed.page/s/{slug}/`
- `/` serves index.html; `/about` tries about, about.html, about/index.html.
- `404.html` at the root is used for misses. SPA mode serves index.html instead.
- A folder without index.html shows a file listing.

## Endpoints

| Method | Path | Auth | What |
| --- | --- | --- | --- |
| PUT/POST | /v1/sites | optional | Publish (slug via header/query/body) |
| PUT/POST | /v1/sites/{slug} | optional | Publish to slug |
| GET | /v1/sites | Bearer | List your sites |
| GET | /v1/sites/{slug} | none | Public site metadata |
| DELETE | /v1/sites/{slug} | Bearer | Delete your site |
| GET | /v1/whoami | optional | Plan and limits |
| POST | /api/v1/billing/checkout | Bearer | Stripe Checkout URL for hobby or pro |
| POST | /api/v1/billing/portal | Bearer | Stripe billing portal URL |
| GET | /api/v1/health | none | Health check |
| POST | /mcp | optional | MCP (JSON-RPC over Streamable HTTP) |

## MCP

Endpoint: `https://deed.page/mcp` (Streamable HTTP, JSON responses, no SSE). Tools: publish_site, update_site, get_site, list_sites, delete_site, whoami, get_upgrade_link. Pass your token as an `Authorization: Bearer` header or as the `token` argument.

Claude Code:

    claude mcp add --transport http deed-page https://deed.page/mcp

Cursor / generic JSON config:

    {"mcpServers":{"deed-page":{"url":"https://deed.page/mcp"}}}

## Errors

Every error is JSON: `{"code","message","retry_after","docs_url","suggestion?"}`.

| Code | Status | Meaning |
| --- | --- | --- |
| slug_taken | 409 | Someone else owns it; `suggestion` has a free slug. |
| slug_invalid / slug_reserved | 400 | Pick another slug. |
| unauthorized | 401 | Missing or unknown token. |
| forbidden | 403 | Token does not own that slug. |
| quota_sites | 403 | Plan site limit reached. |
| quota_bytes | 413 | Site bigger than your plan allows. |
| request_too_large | 413 | Body over 4 MB; use X-Merge. |
| rate_limited | 429 | See `retry_after` seconds. |
| invalid_archive / empty_site / bad_request | 400 | Fix the body. |

## Limits and plans

| Plan | Price | Sites | Per site | Publishes/hour |
| --- | --- | --- | --- | --- |
| Free | $0 | 25 | 25 MB | 60 |
| Hobby | $3/mo | 250 | 100 MB | 300 |
| Pro | $15/mo | 2,500 | 500 MB | 1,200 |

Every plan: permanent sites, no email, no claim link, MCP, subdomain and path URLs. Paid plans are billed monthly by Stripe; cancel any time in the billing portal.

## Content rules

Public static files only. No malware, phishing, credential harvesting, or illegal content. We remove slugs that break these rules. Report abuse to ops@avatar33.com.

## Install the skill

    mkdir -p ~/.claude/skills/deed-page && curl -fsSL https://deed.page/skill.md -o ~/.claude/skills/deed-page/SKILL.md

## Operator

deed.page is operated by Avatar 8 LLC. Contact: ops@avatar33.com.
