API
Two surfaces, one source of truth. GraphQL is the primary interface; REST is generated from the same schema for clients that prefer it. Both honour the same auth, residency, and field-level RBAC rules.
Picking a surface
GraphQL is the default. It returns exactly what the caller asks for, batches efficiently with a single round-trip per page, and the schema introspection drives type generation in @estokad/sdk. Use it from any TypeScript app.
REST exists for clients that don't want a GraphQL transport — webhooks subscribers, server-to-server integrations written in languages without strong GraphQL tooling, simple curl scripts. The endpoints are documented as OpenAPI 3.1; download the spec from /v1/<workspace>/openapi.json.
For framework-specific helpers (auto-tagging components, draft-mode helpers, EstokadProvider), use @estokad/next — it re-exports the SDK and ships self-contained. Or generate types straight from the OpenAPI spec.
Auth
Every request needs an API key in Authorization: Bearer estk_…. Keys are issued per workspace from /settings/api-keys in the Studio with one of four scopes:
| Scope | Reads | Writes | Manages |
|---|---|---|---|
| read | published only | — | — |
| read_draft | published + drafts | — | — |
| write | yes | content entries | — |
| management | yes | content + schema | yes |
management keys can push schema, change billing, mint preview tokens. Treat them like database credentials.
Draft mode
Draft entries are invisible to read-scope keys. A read_draft key sees both. Create a client with draft: true when Next.js draft mode is on, backed by a read_draft key:
import { draftMode } from 'next/headers'
import { createClient } from '@estokad/next'
const { isEnabled } = await draftMode()
const cms = createClient({
workspace: process.env.ESTOKAD_WORKSPACE!,
apiKey: process.env.ESTOKAD_READ_DRAFT_KEY!, // read_draft scope
draft: isEnabled,
})
const article = await cms.entry('article', slug).fetch()
On a statically generated or ISR site, the draft render must bypass the caches the published render uses. Draft mode already opts the route out of the full-route cache; also pass cache: 'no-store' on the fetches your client makes and skip any build-time snapshot or per-process memo while isEnabled — otherwise the preview shows stale published content.
Preview tokens — used by visual edit and editorial preview links — are short-lived tokens signed per region (RS256, verifiable via the workspace's published JWKS) or by a shared HMAC secret. See Visual edit for the full flow.
Rate limits
Free-tier rate limits are 100 req/sec per workspace. Paid tiers raise that to 1000 req/sec. Hard ceilings are configurable on the Sovereign tier. The API returns standard X-RateLimit-* headers.
Residency
Every request lands in the workspace's chosen region. The hostname api.estokad.com resolves to a regional gateway via Cloudflare; if your workspace is provisioned in eu-bru-1 (Belgium), the request never leaves Belgium. Cross-region reads are not possible — by design.