One host for headless calls
Use https://api.craftkit.dev for everything a server-to-server integration does. That host
serves the API namespace (/v1, /health, /api/auth); any non-API traffic sent to it is
redirected to the dashboard host www.craftkit.dev.
| Operation | Call |
|---|
| Verify / read template | GET https://api.craftkit.dev/v1/templates/:slug |
| Create a render | POST https://api.craftkit.dev/v1/templates/:slug/render |
| Poll a render | GET https://api.craftkit.dev/v1/renders/:id |
| Create a share | POST https://api.craftkit.dev/v1/renders/:id/shares |
| Private download (stream) | GET https://api.craftkit.dev/v1/embed/renders/:id/download |
www.craftkit.dev is the dashboard and marketing host. Point all programmatic calls at
api.craftkit.dev.
Public vs private download
There are two ways to get the PDF bytes, both valid with your ck_live_ key:
- Public URL — the
downloadUrl returned on a succeeded render (permanent, public, no
presigning). See Render lifecycle.
- Private stream —
GET /v1/embed/renders/:id/download
authenticates with your ck_live_ key (as the partner secret — not a session JWT) and streams
the PDF from private storage. Use this when you do not want to rely on a public bucket.
The /v1/embed/renders/:id/download endpoint accepts a partner key, but the sibling
/v1/embed/renders/:id (metadata) requires an embed session JWT with strict session
ownership — a partner-key-only caller cannot use it. For headless metadata, poll
GET /v1/renders/:id instead.
Environments
API keys are environment-specific. A key minted in your local dashboard only authenticates against
http://localhost:3000; a production key only authenticates against https://api.craftkit.dev.
Always create the key in the environment you will call, and confirm the target template lives in
that key’s project — a valid key plus a missing template returns 404 template_not_found, not a
401. See Authentication.