Docs

One API. One plugin.

Quickstart

  1. Clone the repo and cd apps/web.
  2. Create resources: wrangler d1 create embedblocks and wrangler kv namespace create CACHE, then paste the IDs into wrangler.jsonc.
  3. Apply the schema: npm run db:migrate. Set a secret: wrangler secret put SESSION_SECRET.
  4. Deploy: npm run deploy. Point embedblocks.com at the worker.
  5. 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.

MethodPathDescription
GET/api/embedFull EmbedResult (data + ready HTML). The main endpoint.
GET/api/oembedSpec-compliant oEmbed JSON (for WP provider registration).
POST/api/auth/requestEmail a login code (used by the site).
POST/api/auth/verifyVerify code → session (used by the site).

Request

curl "https://embedblocks.com/api/embed?url=https://youtu.be/dQw4w9WgXcQ&key=eb_live_xxx"
ParameterDescription
urlURL to embed (required, URL-encoded).
keyAPI key (required) — or X-Api-Key / Authorization: Bearer.
maxwidth / maxheightSize hints for responsive iframes (px).
click_to_play=1Defer the video player; load it on click (faster pages).
media=0Force a summary card instead of rich media.
card=smallCompact card layout.
languageAccept-Language for localized page metadata (e.g. fr-FR).
title=1Add title attributes to iframes (accessibility / WCAG).
refresh=1Bypass 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

FieldMeaning
urlFinal/canonical URL after redirects + <link rel=canonical>
typevideo | audio | photo | rich | link
title / descriptionBest available title and description
author_name / author_urlCreator, when known
provider_name / provider_urlSource site (e.g. YouTube)
thumbnail_url (+ _width/_height)Preview image
faviconProvider favicon
htmlReady-to-embed, responsive HTML (present for every type)
width / heightIntrinsic media size (drives aspect ratio)
sourceHow it resolved: oembed | opengraph | media | fallback
cache_ageSuggested cache lifetime, seconds

WordPress

  1. Install the EmbedBlocks plugin (upload the zip under Plugins → Add New).
  2. Open Settings → EmbedBlocks and paste your API key.
  3. 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.