Docs
One API. One plugin.
Quickstart
- Clone the repo and
cd apps/web. - Create resources:
wrangler d1 create embedblocksandwrangler kv namespace create CACHE, then paste the IDs intowrangler.jsonc. - Apply the schema:
npm run db:migrate. Set a secret:wrangler secret put SESSION_SECRET. - Deploy:
npm run deploy. Pointembedblocks.comat the worker. - Log in, grab an API key, install the WordPress plugin.
Full steps with email setup are in DEPLOY.md.
API
Authenticate with your key via any of: ?key=, X-Api-Key header, or Authorization: Bearer.
| Method | Path | Description |
|---|---|---|
| GET | /api/embed | Full EmbedResult (data + ready HTML). The main endpoint. |
| GET | /api/oembed | Spec-compliant oEmbed JSON (for WP provider registration). |
| POST | /api/auth/request | Email a login code (used by the site). |
| POST | /api/auth/verify | Verify code → session (used by the site). |
Request
curl "https://embedblocks.com/api/embed?url=https://youtu.be/dQw4w9WgXcQ&key=eb_live_xxx" | Parameter | Description |
|---|---|
url | URL to embed (required, URL-encoded). |
key | API key (required) — or X-Api-Key / Authorization: Bearer. |
maxwidth / maxheight | Size hints for responsive iframes (px). |
click_to_play=1 | Defer the video player; load it on click (faster pages). |
media=0 | Force a summary card instead of rich media. |
card=small | Compact card layout. |
language | Accept-Language for localized page metadata (e.g. fr-FR). |
title=1 | Add title attributes to iframes (accessibility / WCAG). |
refresh=1 | Bypass the cache for this request. |
Response
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"requested_url": "https://youtu.be/dQw4w9WgXcQ",
"type": "video",
"title": "Rick Astley - Never Gonna Give You Up",
"description": null,
"author_name": "Rick Astley",
"provider_name": "YouTube",
"provider_url": "https://www.youtube.com",
"thumbnail_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg",
"favicon": "https://www.youtube.com/favicon.ico",
"html": "<div class=\"eb-embed\" ...><iframe ...></iframe></div>",
"width": 1280,
"height": 720,
"source": "oembed",
"cache_age": 86400,
"fetched_at": "2026-06-06T00:00:00.000Z"
} Responses also include a top-level rel, a grouped meta object, a rel-based links array, and a signed iframe URL (a hosted, sandboxed embed — auto-resize it with /embed.js).
Errors return { "error": { "code", "message" } } with a 4xx/5xx status. Rate limit: 120 requests/min/key.
Response fields
| Field | Meaning |
|---|---|
url | Final/canonical URL after redirects + <link rel=canonical> |
type | video | audio | photo | rich | link |
title / description | Best available title and description |
author_name / author_url | Creator, when known |
provider_name / provider_url | Source site (e.g. YouTube) |
thumbnail_url (+ _width/_height) | Preview image |
favicon | Provider favicon |
html | Ready-to-embed, responsive HTML (present for every type) |
width / height | Intrinsic media size (drives aspect ratio) |
source | How it resolved: oembed | opengraph | media | fallback |
cache_age | Suggested cache lifetime, seconds |
WordPress
- Install the EmbedBlocks plugin (upload the zip under Plugins → Add New).
- Open Settings → EmbedBlocks and paste your API key.
- Paste a URL on its own line in a post — it becomes an embed. Or use the block / shortcode:
[embedblock url="https://vimeo.com/76979871"] EmbedBlocks extends WordPress's native oEmbed flow, so existing links keep working if you remove it.
Hosting
EmbedBlocks runs on Cloudflare Workers, with D1 and KV for storage and caching. Prefer to run
your own instance? The repo's DEPLOY.md walks through it end to end.
Optional: Cloudflare Browser Rendering can be enabled as a fallback for JavaScript-only pages.