Skip to content
Docs · Start here

API keys & authentication

Every call carries a Bearer credential. API keys can be full or read-only, and workspace-wide or limited to one project; give each app the narrowest key that works.

View as Markdown
All topics
On this page

Send the credential in the Authorization header: Authorization: Bearer hk_live_…. The same header works for REST, the SDK, the CLI and the MCP connector.

Owners and admins create keys in Dashboard → Settings → API access. A key is shown once and stored only as a hash; it does not expire, and revoking it takes effect immediately.

Kinds of key

KeyActs asCan
Full, whole workspacedeveloperCreate, change and delete resources in every project, deploy, send mail, use AI, buy domains from the Balance. It can also delete projects.
Full, one projectdeveloperThe same, but only on that project's endpoints. Workspace-wide endpoints refuse it.
Read-only, whole workspaceviewerGET requests, plus reads sent as POST (vector query, memory search, storage download links). No environment variables, no SQL, no uploads.
Read-only, one projectviewerReads on that project only.

No API key can manage billing, members or other keys, or move money out: withdrawals, refunds and payout setup need the workspace owner signed in to the dashboard.

Which key to give what

UseKey
Your laptop, CI, setup scriptsFull, whole workspace
A deployed app that uses its database, storage, payments, vectors, memory or auth poolFull, one project
A deployed app that also sends mail or calls the AI GatewayFull, whole workspace (those endpoints are workspace-wide and refuse project keys today)
Dashboards, monitoring, read-only AI assistantsRead-only

Where a project key works

A project key passes every route that names its project: /api/projects/<id>/…, and item routes whose resource belongs to it — /api/databases/:id, /api/storage/:id, /api/functions/:id, /api/vectors/:id, /api/memory/:id, /api/agents/:id, /api/payments/:accountId, /api/auth-pools/:id, /api/deployments/:id.

It is refused, with 403 "This API key only works on project N", on workspace-wide routes: listing projects, /api/mail/send, /api/ai/*, /api/domains/*, /api/repos/*, /api/usage and billing.

Create a key with the API

curl (an owner or admin session or key)
curl -X POST https://harakumo.com/api/orgs/<workspaceId>/api-keys \
  -H "Authorization: Bearer $HARAKUMO_API_KEY" -H "content-type: application/json" \
  -d '{ "name": "notes-app production", "access": "full", "projectId": 12 }'
# 201 → { "key": { "id", "prefix", "access", "project_id" }, "secret": "hk_live_…" }   (secret shown once)

Creating keys needs the admin role, so an API key (developer or viewer) cannot mint more keys. Use the dashboard, or an admin's connector.

Other credentials

CredentialWhere it comes fromActs as
Browser sessionSigning in to the dashboard; an httpOnly cookie, 30 daysYou, with your role in the chosen workspace
Connector token (hk_mcp_…)Connecting Claude, ChatGPT or another MCP client (OAuth)You, read-only or read-and-manage, in one workspace or all of them
Auth-pool client secret (as_…)Enabling an auth poolOnly that pool's sign-in actions — never anything else
Auth-pool client id (ap_…)Enabling an auth poolPublishable: browser sign-in for that pool, when turned on

Choosing a workspace

A key belongs to one workspace. A session or an all-workspaces connector acts in the workspace named by ?org=<id> or the x-harakumo-org header, else the one last chosen in the dashboard.

When a key is refused

StatusMessageWhat to do
401UnauthorizedThe header is missing, or the key was revoked or mistyped.
403This API key is read-onlyUse a full key for writes.
403This API key only works on project NUse a key for that project, or a workspace key for workspace-wide routes.
403Your role (developer) does not allow this actionThe action needs an admin or owner (members, keys, billing).
404Not foundThe id does not exist or belongs to another workspace — the two look the same on purpose.

Reference

SDK
import Harakumo from '@harakumo/sdk';
const hk = new Harakumo({ apiKey: process.env.HARAKUMO_API_KEY });   // baseUrl defaults to https://harakumo.com
// Errors throw HarakumoError with .status and .body (the JSON the API sent).