# media0

> Open Graph image & certificate rendering API. Publish an HTML template
> as a single JSON document; every combination of query parameters
> becomes an immutable, heavily cached webp rendered by locked-down
> headless Chromium.

media0 is agent-first: the whole lifecycle is JSON over HTTP, template
validation is a free dry-run, and agents can self-signup via proof of
work — no human, no email. Base origin: https://media0.eu

## Core reading

Two documents cover everything; read the docs first.

- [Docs](https://media0.eu/docs.md): THE document to read —
  account access (human + AI signup, claim, sign-in), the complete
  template authoring guide (spec schema, sandbox rules, validation,
  publishing, rendering) and the full API reference for every
  endpoint.
- [Legal](https://media0.eu/legal.txt): governs ALL terms, legal
  and compliance questions — terms of service, privacy policy,
  compliance answers, data processing agreement, subprocessor list.

Also: [landing page](https://media0.eu/) (human-facing overview)
and the [console](https://media0.eu/app/) (passkey sign-in;
humans claim agent-created accounts at the claim_url from signup).

## Quick reference

- `POST /auth/pow/challenge` → `{challenge, bits}`; find an ASCII nonce
  so `sha256(challenge + ":" + nonce)` has `bits` leading zero bits
- `POST /auth/agent/signup` `{challenge, nonce}` → tenant id, write API
  key (`m0_…`), 10 single-use recovery codes, and a `claim_url` to hand
  to your human
- Template library (no auth): `GET https://media0.eu/library.json`
  lists every public library template with its `page` and raw-spec
  `json` URL; append `.json` to any library detail page for the exact
  `spec` + known-good `sample_params` — fork it instead of starting
  blank (`GET /library/t/{id}.json` is a stable id-only alias)
- `POST /api/v1/templates` (Bearer `m0_…`) creates a template; every
  publish mints an immutable ascending version. `POST
  /api/v1/templates/validate` is free and does not count against quota.
- `POST /api/v1/templates/preview` `{spec, params}` renders a draft
  spec to webp without publishing anything — changed previews consume
  render quota, unchanged repeats are free cache hits
- Rendering has 3 modes via template `visibility`: public (default,
  open), private + signed URL, private + `Authorization: Bearer m0_…`.
  Signature: `&m0-sig=hex(hmac_sha256(hex(sha256(api_key)),
  "tenant={tenant-id}" + "".join(sorted("{k}={v}" params))))` — docs
  have a copy-paste signer
- `PUT /api/v1/aliases/{name}` points a friendly name at a template
- Render: `GET https://{tenant-id}.media0.eu/image/{alias}?p=…`
  → 302 → `/image/t/{templateID}/{versionID}/webp?p=…` (immutable,
  `Cache-Control: public, max-age=86400, immutable`)

## Limits

- 50 templates per tenant, unlimited immutable versions each
- 10,000 renders/month, counted on cache-miss render attempts
  (successful or failed — a rate limit, not billing)
- 3 s render budget per image; canvas ≤ 4096 px (default 1200×630 @2×)
