--- title: Authentication | Handinger description: Authenticate with the Handinger API using a bearer API key. --- Every request to the Handinger API must include an API key. Keys are scoped to a single organization and inherit the permissions of the user that created them. Treat your API key like a password. Never commit it to source control, paste it into client-side code, or share it in screenshots. Rotate keys you suspect have leaked. ## Get an API key 1. Sign in to the dashboard Open [handinger.com](https://handinger.com) and sign in to the organization you want to issue keys for. You need the **Admin** or **Owner** role on the organization. 2. Open the API keys page Go to **Settings → API keys**, then click **Create API key**. Give it a descriptive name (for example `production-backend`) so you can identify it in the audit log. 3. Copy the secret The full key (`hdg_live_…`) is only shown once. Store it in your secret manager immediately — closing the dialog throws the secret away. ## Use the key The API uses standard HTTP **Bearer** authentication. Send your key in the `Authorization` header on every request: Terminal window ``` curl https://handinger.com/api/workers \ -H "Authorization: Bearer $HANDINGER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "Brand voice analyzer", "prompt": "Compare a draft against our brand voice guide." }' ``` The SDKs read the key from the `HANDINGER_API_KEY` environment variable by default, so in most cases you do not pass it explicitly: - [ TypeScript](#tab-panel-0) - [ Python](#tab-panel-1) - [ cURL](#tab-panel-2) ``` import Handinger from '@ramensoft/handinger'; // Reads HANDINGER_API_KEY from the environment. const handinger = new Handinger(); // Or pass it directly, for example when running inside a worker that doesn't // expose the host env: const explicit = new Handinger({ apiKey: process.env.HANDINGER_API_KEY }); ``` ``` from handinger import Handinger # Reads HANDINGER_API_KEY from the environment. client = Handinger() # Or pass it directly: import os explicit = Handinger(api_key=os.environ["HANDINGER_API_KEY"]) ``` Terminal window ``` export HANDINGER_API_KEY="hdg_live_…" curl https://handinger.com/api/workers \ -H "Authorization: Bearer $HANDINGER_API_KEY" ``` ## Error responses The API returns standard HTTP status codes for auth failures. Every error body matches the `ErrorResponse` schema, with a human-readable `error` string. | Status | Meaning | | ------ | -------------------------------------------------------------------------------------------------- | | `401` | The `Authorization` header is missing, malformed, or the key has been revoked. | | `403` | The key is valid but it does not have access to the worker, task, or organization being addressed. | | `429` | You have exceeded the per-key rate limit. Back off using the `Retry-After` header. | Programmatic tasks (`POST /api/tasks` from an API key) are recorded with `triggeredBy: "api"`. UI traffic is logged as `"ui"`. Filter on this field when you build audit dashboards. ## Rotating and revoking keys Rotate keys regularly and any time you suspect a compromise. The dashboard supports both immediate revocation and a 24-hour grace window so you can roll keys without downtime: 1. Issue a replacement key Create the new key first and deploy it to your production secret store. 2. Wait for your fleet to roll Confirm your services have picked up the new key (no `401`s on the old one). 3. Revoke the old key Use **Settings → API keys** to revoke the old key. Revocations take effect within a few seconds globally.