Public API

Free, read-only, no sign-up, no API key. JSON endpoints for data that's already public elsewhere on the site — plus everything you need to embed a cwtch.es tool directly on your own pages.

Basics

Every endpoint below is a GET request to https://cwtch.es/api/public-api.php with an endpoint query parameter, returning JSON. Responses are open to cross-origin requests (CORS enabled), so you can call this directly from client-side JavaScript on your own site — no server-side proxy needed.

There's no authentication, no account, and no API key — anyone can use it. In exchange, there's a rate limit of 120 requests per hour per IP address across all endpoints combined. Going over it returns a 429 status with a Retry-After header. If you need more than that, please cache responses on your end rather than polling — none of this data changes more than a few times a day.

Every response includes a success boolean. On an error, you'll also get an error string explaining what went wrong, alongside an appropriate HTTP status code.

Embedding a tool on your own site

Every tool on cwtch.es runs entirely in the browser (nothing gets uploaded to us), which is exactly what makes it embeddable — the iframe below is doing the full generation/conversion/whatever itself, client-side, same as if someone visited the real page directly. Pick a tool on the embed-code page for ready-made, copy-paste snippets; here's how it works generally.

Option 1 — the widget loader (recommended)

Handles building the iframe and auto-resizing it to fit the tool's real content — a fixed guessed height looks wrong the moment a generated result makes the page longer or shorter.

<div data-cwtch-tool="qrcode"></div>
<script src="https://cwtch.es/embed.js" async></script>

data-cwtch-tool takes a tool's id or filename (either works) — see the tools endpoint below for the full list. An optional data-height="900" sets the starting height before auto-resize kicks in.

Option 2 — a raw iframe

No script needed, but you're setting a fixed height yourself. Get the exact markup (and a sensible default height per tool) from the embed endpoint below, or just build it directly:

<iframe src="https://cwtch.es/qrcode.html?embed=1&credit=1" width="100%" height="700" style="border:0;border-radius:12px;" loading="lazy" title="QR Code Generator — cwtch.es"></iframe>

Add ?embed=1 to any tool page's own URL and it drops the site nav, footer, and ads. Add &credit=1 too and it leaves a small "cwtch.es" credit link in the corner — worth including when you're embedding a tool on your own site, since a visitor there might not otherwise know where it came from. Leave it off for a clean, credit-free view — that's what an OBS Browser Source link or similar wants. Listen for a {cwtchEmbed:true, height} message posted to window if you want auto-resize without embed.js.

Option 3 — oEmbed

Paste a tool's page URL into anything that already speaks oEmbed — WordPress, Notion, Discord/Slack unfurls — and it embeds automatically with zero setup, via the discovery link every tool page carries in its <head>. To call it directly yourself:

GET https://cwtch.es/api/oembed.php?url=https://cwtch.es/qrcode.html&format=json

{
  "version": "1.0",
  "type": "rich",
  "provider_name": "Cwtch.es",
  "provider_url": "https://cwtch.es/",
  "title": "Free QR Code Generator",
  "html": "<iframe src=\"https://cwtch.es/qrcode.html?embed=1&credit=1\" ...></iframe>",
  "width": 600,
  "height": 700
}

Also accepts format=xml, and maxwidth/maxheight to size the returned iframe.

Endpoints

GET ?endpoint=tools

Every currently-enabled, publicly-listed tool on the site — the same list the sidebar nav is built from. Disabled or unlisted tools are excluded automatically.

{
  "success": true,
  "count": 112,
  "tools": [
    {
      "id": "watermark-maker",
      "name": "Watermark Maker",
      "file": "watermark-maker.html",
      "url": "https://cwtch.es/watermark-maker.html",
      "category": "Image",
      "subcategory": null
    },
    ...
  ]
}

    
GET ?endpoint=embed

Ready-to-use embed markup for one tool — both the raw <iframe> and the data-cwtch-tool snippet for the embed.js loader, plus a sensible default height and a direct oEmbed URL. This is exactly what powers each tool page's own "Embed" panel.

ParamRequiredDescription
toolYesA tool id or filename, from the tools endpoint above.
{
  "success": true,
  "tool": { "id": "qrcode", "name": "Free QR Code Generator", "file": "qrcode.html", "url": "https://cwtch.es/qrcode.html", ... },
  "embed_url": "https://cwtch.es/qrcode.html?embed=1&credit=1",
  "default_width": "100%",
  "default_height": 700,
  "auto_resize": true,
  "iframe_html": "<iframe src=\"...\" width=\"100%\" height=\"700\" ...></iframe>",
  "script_html": "<div data-cwtch-tool=\"qrcode\"></div>\n<script src=\"https://cwtch.es/embed.js\" async></script>",
  "oembed_url": "https://cwtch.es/api/oembed.php?url=...&format=json"
}

    
GET ?endpoint=stats

Anonymous, all-time usage counts per tool — the same numbers shown on the public stats page. Keyed by tool id.

{
  "success": true,
  "stats": {
    "watermark-maker": 42,
    "gif-maker": 1830,
    ...
  }
}

    
GET ?endpoint=changelog

The same content shown on the changelog page, grouped by month, newest first.

ParamRequiredDescription
limitNoReturn only the N most recent months (1–100). Omit for the full history.
{
  "success": true,
  "months": [
    {
      "month": "September 2026",
      "title": "...",
      "sections": [ { "type": "launched", "label": "🚀 Launched", "items": ["..."] } ]
    },
    ...
  ]
}

    
GET ?endpoint=roadmap

Public entries from the roadmap / tool-request board — anything an admin has triaged past "pending", sorted by votes. Pending and declined requests are never included, matching what the board itself shows.

ParamRequiredDescription
statusNoOne of approved, planned, in_progress, shipped, or all (default).
{
  "success": true,
  "requests": [
    {
      "id": 14,
      "title": "Add dark mode toggle",
      "description": "...",
      "status": "planned",
      "votes": 23,
      "submitted_at": "2026-09-10T14:22:00+00:00"
    },
    ...
  ]
}

    

Example: fetch in JavaScript

fetch("https://cwtch.es/api/public-api.php?endpoint=tools")
  .then(res => res.json())
  .then(data => console.log(data.tools));

Something missing, or a question?

This API only exposes what's already public elsewhere on the site — if there's other public data you'd find useful as an endpoint, or something here doesn't behave as documented, let us know or add it to the roadmap board.