Authentication
Every call to the public API carries an organization API token — a credential that starts with atk_. There is no OAuth flow, no session and no user: the token is the identity, and it belongs to the organization, not to the person who created it.
1. Create a token
In Studio, open Settings → API tokens and click Create. Choose:
- a title you will recognize in the activity log (
site-build,import-script); - a scope —
read(default) orread + write(see Scopes); - a project — the token is narrowed to it, or All projects for an organization-wide token;
- an optional expiry — a date means valid through that day.
The full token is shown once. Copy it into your secret store; Studio keeps only a hash and the first characters for display. A lost token is regenerated (same title, scope and project; the old secret dies at once) or revoked.
Least privilege
Create one token per consumer, narrowed to the project it needs. A leaked site-build token should not be able to write, and a leaked import token should not reach every project.
2. Send it
Either header works; use one, not both:
curl https://api.hypervalent.io/v1/orgs/YOUR_ORG_ID/token \
-H "Authorization: Bearer atk_YOUR_TOKEN"curl https://api.hypervalent.io/v1/orgs/YOUR_ORG_ID/token \
-H "X-API-Key: atk_YOUR_TOKEN"The token travels in a header, never a cookie and never a query string. Public reads answer permissive no-credential CORS, so calling from a browser works — but a token in client-side code is visible to everyone who loads the page. Use a build step or a server for anything but a read token whose exposure you accept.
3. Check what it can do
GET /orgs/{org_id}/token answers the token's own view of itself:
{
"token": {
"prefix": "atk_3f9a1c2e",
"title": "site-build",
"scope": "read",
"projectUuid": "…",
"projectSlug": "marketing",
"expiresAt": null
},
"features": { "mcpServer": true, "apiTokensWrite": false, "removeBranding": false }
}features.apiTokensWrite is whether this token may write today — its scope is read_writeand the organization's plan still includes API writes. A read_write token on a downgraded plan keeps authenticating but every write answers 403 FEATURE_DISABLED with requiredPlan.
GET /orgs/{org_id}/projects lists the projects the token may name in a URL: every live project for an organization-wide token, exactly one for a narrowed token.
Scopes
| Scope | May | Plan |
|---|---|---|
read | Every GET — published content, structure, settings, design tokens | Every plan |
read_write | Everything read may, plus: create and edit documents and terms, publish / unpublish / trash documents, upload images, and read the working view (?status=draft) | Team and above |
Scope is enforced twice: the authenticator refuses a non-GET method from a read token (403 TOKEN_SCOPE_READ_ONLY), and every write route re-checks the scope and the plan at use.
A token never carries a user's permissions. What a Studio member may do has no bearing on what a token may do, and revoking a member does not revoke the tokens they created.
Organization and project scoping
The URL names an organization (org_id) and usually a project (projectSlug). The server checks, in this order:
- Credential — missing →
401 API_TOKEN_REQUIRED; unknown, revoked or expired →401 INVALID_API_TOKEN. This runs before the URL is resolved, so an anonymous caller cannot use 404-vs-401 to discover which org ids or project slugs exist. - Organization — the token must belong to the URL's organization →
403 TOKEN_ORG_MISMATCH. - Project — a narrowed token must match the URL's project →
403 TOKEN_PROJECT_MISMATCH. An unknown project slug is a plain404. - Delivery gate — a closed organization (
403 ACCOUNT_CLOSED), one whose delivery the platform has blocked (403 DELIVERY_BLOCKED), or one terminated for non-payment (402 BILLING_TERMINATED).
Only then does the read or write run.
Expiry, rotation and revocation
- An expired token is refused exactly like a revoked one (
401 INVALID_API_TOKEN). Owners and admins are emailed ahead of an expiry; watch the token list in Studio for theexpiredstate. - Regenerate rotates the secret in place — the token keeps its uuid, title, scope, project and expiry, so nothing but the secret in your config changes.
- Revoke is immediate and permanent. Create a new token rather than trying to reuse one.
- Every create, regenerate and revoke — and every write made with a token — is recorded in Studio → Activity, attributed to the token by title and prefix.