/v1/projects*, authenticated with an
account API key (ck_acct_…) instead of a project key. Reach for it when your integration
needs to create and manage Craftkit projects itself — most commonly one project per customer
org in a multi-tenant backend — rather than rendering against a single project you set up by hand
in the dashboard.
If you only render against one fixed project, you don’t need this — a single
ck_live_…
project key is enough. See Server-to-server integration. Reach
for an account key only when your integration itself creates/lists/renames/deletes projects or
mints project keys programmatically.The credential
An account key looks likeck_acct_xxxxxxxxxxxxxxxxxxxxxxxx and is minted from the dashboard
(Account → API keys) — there is no endpoint that issues one. It is sent the same way as a
project key:
What an account key can do
Create a project
POST /v1/projectsList projects
GET /v1/projectsGet / rename / delete
GET, PATCH, DELETE /v1/projects/:idMint a project key
POST /v1/projects/:id/keysproject.userId must equal the
account resolved from the bearer token, and the project must not be soft-deleted — via a single
centralized ownership check reused by every route. A project id that belongs to a different
account behaves identically to one that doesn’t exist: 404, never 403, never a peek at the
other account’s data (OWASP API1:2023 — Broken Object Level Authorization).
An account key cannot render, read templates, poll renders, or reach signatures directly —
those still require the project’s own ck_live_… key, minted via the endpoint above.
Multi-tenant pattern: one project per customer
1
Hold one account key
Store
ck_acct_… once, server-side, for your whole integration — not per customer.2
Create a project per customer org (once)
POST /v1/projects with a name derived from the customer. Store the returned id /
slug against that customer in your own database.3
Mint and cache a project key for that customer (once)
POST /v1/projects/:id/keys. The plaintext ck_live_… key is returned exactly once — cache it
(e.g. in your existing getOrgApiKey / resolveApiKey-style lookup) keyed by customer id.4
Use the cached project key for everything else
Render, read templates, poll renders, and send signatures for that customer with their cached
ck_live_… key — the account key is not needed again until you provision the next customer.Errors
/v1/projects* uses the same error envelope as the rest of the API.
Next
Authentication
The three credential types and their scopes.
Server-to-server integration
The single-project render/poll playbook once you have a
ck_live_ key.