//08 — Dev Snippets API  ·  v1.0  ·  /products/dev-api/docs

API live · 6 endpoints

Six HTTP endpoints, one key.

Markdown → OG image, HTML → PDF, mermaid → SVG, URL → screenshot, URL → sitemap, OpenAPI YAML → hosted mock. All POSTs, all application/json (except YAML on /openapi-mock), all authenticated with an X-API-Key header.

Base URL

/api/dev/v1

elofyn.com

Auth header

X-API-Key

ek_live_<32 hex>

Endpoints

6

POST · all

Free tier

500

calls / month

// 01 — Overview

What this API does.

The Dev Snippets API is six small services every developer keeps re-implementing, exposed behind one HTTP surface and one authentication header. Send JSON, get a binary or a JSON response back. There is no SDK to install and no client library to wait for — every endpoint is a single curl call.

All requests go to https://elofyn.com/api/dev/v1. Responses include X-Request-Id (ULID, log it), X-RateLimit-Remaining, and X-RateLimit-Reset so client code can self-throttle without polling.

// 02 — Authentication

One key. One header.

Every request authenticates via an X-API-Key header. Keys are prefixed ek_live_ (production) or ek_test_ (sandbox, watermarked output, no quota burn). Issue one by POSTing your email to /v1/keys:

Issue an API key

# Sign up and receive an `ek_live_<32 hex>` key
curl -sS -X POST https://elofyn.com/api/dev/v1/keys \
  -H "Content-Type: application/json" \
  -d '{"email":"you@example.com"}'

# → 201 Created
# {
#   "ok": true,
#   "email": "you@example.com",
#   "api_key": "ek_live_a1b2c3d4e5f60718293a4b5c6d7e8f90",
#   "tier": "free",
#   "created_at": "2026-05-16T07:31:36Z"
# }

Treat the returned key like a password. It is shown once, then hashed against an indexed unique column in our SQLite store. If you lose it, rotate via the dashboard contact form — self-serve rotation lands with the dashboard in P8.13.

// 03 — Rate limits

Monthly quotas, calendar UTC.

Quota is per calendar month, UTC. A 429 response carries Retry-After in seconds until the next month boundary, plus the standard X-RateLimit-* trio so you can hold off without polling.

TierPriceQuota / moBurstEndpoints
free$05002 req/sog · diagram · sitemap
pro$4925,00010 req/sall six
scale$199250,00050 req/sall six

// 04 — Errors

One envelope, stable codes.

Non-2xx responses share one JSON shape, even when the success body is binary. Codes are snake_case and stable across versions — safe to switch on in client code.

HTTPerror.codeWhen
400invalid_requestBody shape failed validation.
401missing_api_keyX-API-Key header absent.
401invalid_api_keyKey not found or malformed.
403tier_forbiddenEndpoint unavailable on caller's tier.
408render_timeoutRenderer exceeded its budget.
413payload_too_largeBody over the endpoint cap.
415unsupported_media_typeContent-Type not in allowlist.
422render_failedSource rejected by the renderer.
429rate_limitedMonthly quota or burst exhausted.
451domain_forbiddenTarget URL matches the denylist.
502upstream_failedRenderer subprocess crashed.

// 05 — Endpoint

OG image from markdown.

POSThttps://elofyn.com/api/dev/v1/ogfree + pro + scale

Render a 1200×630 PNG suitable for og:image from a markdown title + optional eyebrow. Renders against the same lib/og.tsx machinery that paints Elofyn’s own social previews.

FieldTypeRequiredNotes
markdownstringyesMax 8 KB. First H1 + first paragraph render as title + subtitle.
theme"dark" | "light"noDefault dark (#0A0F1A bg + #E07B3A accent).
eyebrowstring | nullnoOptional mono eyebrow line, max 64 chars.
footerstringnoDefault "elofyn.com". Max 64 chars.
widthintegerno1200 (OG) · 1500 (Twitter) · 800 (square).
font"geist" | "instrument-serif"noTitle typeface. Default geist.

Example request

curl -sS -X POST https://elofyn.com/api/dev/v1/og \
  -H "X-API-Key: $ELOFYN_DEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "markdown": "# How we ship every week\n\n*A Friday cadence beats a quarterly heroic.*",
    "eyebrow": "// 01 — Journal",
    "theme": "dark"
  }' \
  -o og.png

Response · 200 · image/png · binary body

// 06 — Endpoint

PDF from HTML.

POSThttps://elofyn.com/api/dev/v1/pdfpro + scale

Print-ready PDFs from raw HTML, rendered headlessly by Playwright in an isolated context with all network requests blocked. Use it for invoices, contracts, weekly digests — anything that needs a fixed-layout artifact rather than a screenshot.

FieldTypeRequiredNotes
htmlstringyesMax 4 MB. Must include <!doctype html>.
formatenumnoLetter, Legal, Tabloid, Ledger, A0–A6. Default A4.
marginobjectno{ top, right, bottom, left } as CSS length strings.
landscapebooleannoDefault false.
print_backgroundbooleannoDefault true.
header_htmlstring | nullnoPlaywright header template. Max 8 KB.
footer_htmlstring | nullnoPlaywright footer template. Max 8 KB.
wait_for_selectorstring | nullnoRender after this selector appears (max 5 s).
wait_for_timeout_msintegernoAdditional fixed delay after load. 0–5000 ms.

Example request

curl -sS -X POST https://elofyn.com/api/dev/v1/pdf \
  -H "X-API-Key: $ELOFYN_DEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<!doctype html><html><body><h1>Invoice #2026-0001</h1></body></html>",
    "format": "A4",
    "print_background": true
  }' \
  -o invoice.pdf

Response · 200 · application/pdf · binary body, max 5 MB

// 07 — Endpoint

Mermaid → SVG.

POSThttps://elofyn.com/api/dev/v1/diagramfree + pro + scale

Convert a mermaid source string to SVG (or 2× PNG) in under 300 ms. Useful for auto-generating architecture diagrams in CI/CD, docs sites, and READMEs.

FieldTypeRequiredNotes
sourcestringyesMax 64 KB. Any mermaid syntax.
themeenumnodark · light · forest · neutral. Default dark.
background"transparent" | "canvas"noDefault transparent.
format"svg" | "png"noDefault svg. PNG rasterises at 2×.

Example request

curl -sS -X POST https://elofyn.com/api/dev/v1/diagram \
  -H "X-API-Key: $ELOFYN_DEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "sequenceDiagram\n  A->>B: hi\n  B-->>A: hello",
    "theme": "dark",
    "format": "svg"
  }' \
  -o seq.svg

Response · 200 · image/svg+xml or image/png

// 08 — Endpoint

URL → PNG.

POSThttps://elofyn.com/api/dev/v1/screenshotpro + scale

Take a Playwright screenshot of a public URL. Private IPs, cloud metadata endpoints, and localhost are denylisted server-side — DNS is resolved once and the resolved IP is checked before navigation to close the DNS-rebinding loophole.

FieldTypeRequiredNotes
urlstringyesMust be http(s)://.
viewport.widthintegerno320 – 1920. Default 1280.
viewport.heightintegerno320 – 1080. Default 800.
device_scale_factorintegerno1, 2, or 3 (3 only on scale tier). Default 2.
full_pagebooleannoScroll-stitched, capped at 8000 px tall.
wait_untilenumnoload · domcontentloaded · networkidle. Default networkidle.
block_adsbooleannoBlocks built-in regex of ad / analytics domains. Default true.
color_scheme"light" | "dark"noSets prefers-color-scheme. Default dark.
format"png" | "jpeg"noDefault png.

Example request

curl -sS -X POST https://elofyn.com/api/dev/v1/screenshot \
  -H "X-API-Key: $ELOFYN_DEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://elofyn.com",
    "viewport": { "width": 1280, "height": 800 },
    "device_scale_factor": 2,
    "color_scheme": "dark"
  }' \
  -o shot.png

Response · 200 · image/png or image/jpeg · binary body

// 09 — Endpoint

URL → sitemap.xml.

POSThttps://elofyn.com/api/dev/v1/sitemapfree + pro + scale

Crawl a public site’s same-origin links and return a standards-compliant sitemap.xml. 30-second wall-clock budget; robots.txt honoured by default.

FieldTypeRequiredNotes
start_urlstringyesMust be https://.
max_urlsintegerno1 – tier cap (free 100, pro 1k, scale 10k).
max_depthintegerno1 – 10. Default 4.
respect_robots_txtbooleannoDefault true. Pro+ may override.
include_subdomainsbooleannoFollow *.example.com from example.com.
include_patternsstring[] | nullnoRegex allowlist on pathname.
exclude_patternsstring[] | nullnoRegex denylist (applied AFTER include).
concurrencyintegerno1 – tier cap (free 4, pro 8, scale 16).

Example request

curl -sS -X POST https://elofyn.com/api/dev/v1/sitemap \
  -H "X-API-Key: $ELOFYN_DEV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "start_url": "https://elofyn.com",
    "max_urls": 50,
    "respect_robots_txt": true
  }' \
  -o sitemap.xml

Response · 200 · application/xml · UTF-8 body

// 10 — Endpoint

OpenAPI YAML → hosted mock.

POSThttps://elofyn.com/api/dev/v1/openapi-mockpro + scale

Accept an OpenAPI 3.x spec and provision a hosted mock server URL that responds to the spec’s routes with realistic example data. Mocks live for 24 hours on free, 30 days on pro, and 90 days on scale. The mock URL itself is keyless — revoke via DELETE /v1/openapi-mock/:mock_id if it leaks.

FieldTypeRequiredNotes
specstringyesOpenAPI document as a string. Ignored when CT is YAML — body IS the spec.
spec_format"yaml" | "json"noHint for the parser. Default yaml.
ttl_secondsintegerno60 – tier cap (free 86400, pro 2592000, scale 7776000).
corsbooleannoDefault true. Mock returns Access-Control-Allow-Origin: *.
dynamicbooleannoRandomise example responses per-call via JSON-Schema faker.

Example request

# YAML body: send the spec as the raw body with the YAML content-type
curl -sS -X POST https://elofyn.com/api/dev/v1/openapi-mock \
  -H "X-API-Key: $ELOFYN_DEV_API_KEY" \
  -H "Content-Type: application/x-yaml" \
  --data-binary @petstore.yaml

# → 201 Created
# {
#   "ok": true,
#   "mock_id": "mock_01HXYZ...",
#   "url": "https://mock.elofyn.com/m/01hxyz...",
#   "expires_at": "2026-05-17T07:31:36Z"
# }

Response · 201 · application/json · { url, expires_at, stats_url, delete_url }

// reference

The canonical spec lives at docs/dev-api-spec.md in the source repo. Bugs or schema gaps? Drop us a note with the X-Request-Id from the failing response.