Skip to Content
Framework GuidesProject API Keys

Project API Keys

A project API key belongs to a project, not to a person. Your server code and your pipelines hold one instead of your personal account token, so a leaked key exposes one project’s application surface — not everything you can reach.

What they are

  • Project-owned. A key is created inside one project and never moves. It reaches that project’s resources and nothing else.
  • Prefixed gsk_. A key is 60 characters: gsk_, a random body, and a checksum that lets the API reject a truncated or mistyped key before it looks anything up. Lists show only the first 12 characters.
  • One per server or pipeline. Name a key after where it lives — production server, github actions — so revoking it never takes down more than the one thing you meant.
  • Shown once. The key is displayed when you create it and never again. If you lose it, roll it.

Create one

Open Project → Settings → API keys in the console :

FieldWhat it does
NameHow you recognize the key later, e.g. production server. Up to 100 characters.
PurposeApplication — server code: user administration for the project’s auth apps, plus storage and databases. CI/CD — deploys only, for GitHub Actions and other pipelines.
Advanced → Restrict to specific auth appsApplication keys only. Tick the apps this key may administer. Leave it empty and the key reaches every auth app in the project.
Advanced → Expires in (days)Optional. Empty means the key never expires.

Press Create key and copy the value straight away — it is not shown again.

Anyone with the read role on the project can see the list. Creating, rolling and revoking need admin or owner. A project API key can never manage keys, including itself: those routes answer 403 for a key.

Auth apps belong to the project, not to one site. An Application key can administer the users of every auth app in the project unless you restrict it under Advanced — worth doing when the project runs more than one app.

What a key can reach

Deny by default. A key reaches an explicit allowlist of routes and nothing else. The purpose you pick maps to capabilities, and each capability opens one part of that list.

Applicationauth, storage, databases

CapabilityThe key may
authList the project’s auth apps; read an app and its statistics; list, read, disable, enable and delete its end users; reset a user’s 2FA; set a user’s app_metadata; mint a password-reset link
storageList buckets; read a bucket and its S3 credentials; list, upload, download, inspect and delete objects, including batch and prefix deletes; mint presigned upload and download URLs
databasesList databases; read one; read its credentials; read its metrics

CI/CDdeploy

CapabilityThe key may
deployUpload a deploy; list a project’s deployments; read a deployment and its logs; roll a deployment back; read the project, its logs, its sites and one site

What it cannot

Everything that creates, destroys or reconfigures infrastructure stays with a human, in the console or the ghayma CLI:

  • Create, update or delete an auth app, rotate its signing keys, or touch its server key.
  • Create, roll or revoke API keys.
  • Create, delete, expose or unexpose a bucket, rotate its credentials, or edit its CORS rules.
  • Create, delete, stop, start, resize, retier, rotate, expose or unexpose a database, change which sites reach it, or take and restore backups.
  • Reach a database through the API’s data plane — collections, documents, queries, tables. An app talks to its database over the wire with the credentials, not through this API.
  • Billing, account, teams, account tokens and domains. A key is never granted those scopes.

Two refusals are worth recognizing: another project’s resource answers 404, and a route outside the allowlist answers 403. An allowlisted route the key has no capability for also answers 403, with insufficient token scope.

Managed keys

You do not create every key. The platform mints one for each site connected to a storage bucket, a database, or an auth app at level admin, and injects it into that site’s container as GHAYMA_API_KEY on every deploy — the hand-copy step disappears.

  • Named site:<site>. One per site, listed alongside the keys you created and marked managed.
  • Capabilities follow the connections. storage for a bucket, databases for a database, and auth for an auth app connected at admin — narrowed to those apps, so the project’s other auth apps are never swept in. Connect or disconnect a service and the key is re-minted to match; disconnect the site’s last one and the key is revoked with it. A change reaches the running pods without a redeploy.
  • Not yours to roll. Roll and revoke answer 409 for a managed key: rolling one by hand would leave the running app holding a dead credential, and the next deploy would mint a replacement beside it anyway. Disconnect the site instead.
  • Not stored as an env var. Like the database and storage variables, it is derived at deploy time, so it never appears in ghayma env list and there is nothing to edit.

A managed key carries auth only for the auth apps its site is connected to at level admin; at client — where a new connection starts — it carries none, and administering that app’s end users needs a key you create yourself. So does any server that runs outside Ghayma.

Use it

On your server, hand the key to the SDK:

import { Ghayma } from "@ghayma/sdk"; const ghayma = new Ghayma({ apiKey: process.env.GHAYMA_API_KEY });

Zero-argument new Ghayma() reads GHAYMA_API_KEY from the environment, so a site that already has the variable needs no argument at all — and a site connected to a bucket or a database already has it.

When you still set GHAYMA_API_KEY yourself. It is injected automatically only for a site connected to a bucket, a database, or an auth app at admin. For a server hosted outside Ghayma, create an Application key and set the variable by hand — in the console, or with ghayma env set GHAYMA_API_KEY=gsk_....

CLI support for project keys is not shipped yet. A CI/CD key authenticates the deploy API routes today, but ghayma deploy with a project key comes in a later CLI release. Keep your pipeline on an account token until then.

Roll and revoke

Roll issues a fresh key with the same name (suffixed (rolled)), the same capabilities, the same auth-app restriction and the same remaining lifetime. The old key keeps working until you revoke it, which is the point: deploy the new value, confirm it works, then revoke the old one. No downtime, no window where nothing authenticates.

Revoke takes a key out of service. The row is kept for audit and shows as revoked in the list. Keys are validated against a 30-second cache, so a revoke takes effect everywhere within 30 seconds.

Both refuse a managed key with a 409 — it is retired by disconnecting the site, not by hand.

Account tokens vs project keys

Account token (gh_…)Project API key (gsk_…)
Belongs toYouOne project
ReachesEvery project you can reach, plus your account routesThat project’s allowlisted application routes
Created inSettings → API TokensProject → Settings → API keys
Use it forThe ghayma CLI on your own machineYour app’s server code, and CI

An account token still authenticates @ghayma/sdk and logs one warning per process telling you to switch. Keep account tokens for the CLI on your own machine, where acting as you is exactly what you want.

Restricted keys

An Application key can be narrowed to a subset of the project’s auth apps. The console lists them with checkboxes; over the API, auth_app_ids takes the UUIDs of auth apps in the same project — an app’s slug is rejected with a 400, and so is an app from another project. Your code may still address an app by slug or UUID, because the restriction is checked against the app the request resolves to. An app outside the restriction answers 404.

Keys created before storage and databases were enabled keep their capabilities. The Application preset is expanded once, when the key is created, and rolling a key copies the capabilities it already has. Create a new Application key to pick up capabilities added since.