memeworld
Documentation

Start

Auth

API keys, OAuth 2.1, and which calls work with neither.

Two ways in, for two kinds of caller: an API key for scripts and agents you run yourself, OAuth for MCP clients that sign a user in.

Sign-in exists to unlock keys, MCP authorization and the watermark toggle. It is never needed to browse, to use the on-site editor, or to download what the editor draws.

API keys

Create one at /settings/api-keys. Keys start with mw_, are shown in full exactly once, and are listed afterwards by their first characters only.

Send it as either header:

curl -X POST https://memeworld.afterlume.workers.dev/api/v1/render \
  -H 'x-api-key: mw_...' \
  -H 'content-type: application/json' \
  -d '{"templateId": 42, "captions": ["before", "after"]}'
Authorization: Bearer mw_...

The same key authenticates MCP. Clients that take custom headers can send x-api-key and skip the OAuth flow entirely.

A key is capped at 600 requests an hour on top of the per-endpoint limits. Delete a leaked key from the same page; it stops working immediately.

OAuth 2.1

MCP clients discover authorization from the protected-resource metadata:

https://memeworld.afterlume.workers.dev/.well-known/oauth-protected-resource

memeworld is its own authorization server. Clients register through client metadata documents (CIMD, as pinned by MCP spec 2026-07-28), send the user to /sign-in, then to /consent, and receive a token scoped to https://memeworld.afterlume.workers.dev/api/mcp.

A request carrying a bad or expired token gets an RFC 9728 challenge back — the WWW-Authenticate header is how a client learns to start the flow rather than give up.

What needs a caller

  • Open: search_templates, get_template, list_tags, get_editor_url, open_meme_editor, every GET /api/v1/*, and POST /api/v1/suggest.
  • Authorized: suggest_memes, caption_meme, face_swap_meme, POST /api/v1/render, POST /api/v1/face-swap and GET /api/v1/credits.

An MCP request with no credentials is served anonymously rather than rejected: the open tools answer, and the two that cost money return an error explaining how to connect.

The 401

{
  "code": "UNAUTHORIZED",
  "message": "Send an API key as `x-api-key` or `Authorization: Bearer`. Create one at /settings/api-keys."
}