# Credentials

One key builds everything: projects, services and deploys, from your laptop, CI or your AI. Each app gets its own key automatically (`HARAKUMO_API_KEY`): it works for every service in that project, AI and email included, and nothing outside it. Everything else below is made by the platform or by a service, and the secrets among them are stored as the project's environment variables, sealed, so app code reads `process.env.NAME` (or `env.NAME` in an edge program) and never holds a value in its files.

## Keys

| Credential | Who makes it | Where it lives | Do you handle it? | How it is rotated |
| --- | --- | --- | --- | --- |
| Workspace key (hk_live_…) | An owner or admin, on the Connect page | Your laptop, CI or your AI (`HARAKUMO_API_KEY` there) | Yes: it is shown once | Make a new one, move to it, revoke the old one; pause or give it an end date meanwhile |
| App key (hk_live_…, the app's own) | The platform, for each app, at its first deploy | `HARAKUMO_API_KEY`, set at every deploy (a `HARAKUMO_API_KEY` of your own in Environment is used instead) | No: never shown. For local runs an owner or admin signed in to the dashboard can reveal it | `POST /api/projects/:id/app-key { action: 'rotate' }` (the SDK's `projects.rotateAppKey`): the app gets the new one at its next deploy and the old one keeps working 24 hours; `immediately: true` stops the old one now, for one that leaked |
| Project key (hk_live_…, one project) | A developer or a full key, on the Connect page or `POST /api/projects/:id/keys` | Code hosted elsewhere, as `HARAKUMO_API_KEY` | Yes: it is shown once | Make a new one and revoke the old one; it is never wider than the key that made it |
| Mail key (hk_live_… with mail access) | An owner or admin, signed in to the dashboard | Wherever inbox mail is read | Yes: it is shown once | As a workspace key; it loses mail access when its maker stops being an owner or admin |
| Connector token (hk_mcp_…) and its refresh token (hk_mcr_…) | Connecting Claude, ChatGPT or another AI client | The AI client | No | It renews itself; cut it off on the Connect page |
| Agent run key | The platform, for each agent run | Inside the run | No | Made for one run and revoked when it ends |

## Sign-in

| Credential | Who makes it | Where it lives | Do you handle it? | How it is rotated |
| --- | --- | --- | --- | --- |
| Client id (ap_…) | Turning sign-in on for a project | `HARAKUMO_AUTH_CLIENT_ID` | Yes, and it is public: browser and phone code may hold it | It does not change |
| Client secret (as_…) | Turning sign-in on for a project | `HARAKUMO_AUTH_CLIENT_SECRET` (server code only) | No: it is stored as the setting | An owner or admin rotates it on the project's Sign-in page; the old one keeps working for 24 hours |
| JWT secret | Turning sign-in on for a project | `HARAKUMO_AUTH_JWT_SECRET` (server code only) | No: it is stored as the setting | An owner or admin rotates it; the old one keeps checking tokens for 24 hours (`HARAKUMO_AUTH_JWT_SECRET_PREVIOUS`, until `HARAKUMO_AUTH_JWT_SECRET_PREVIOUS_UNTIL`) |
| A user's sign-in token and refresh token (hkrt_…) | Signing a user in | The app, for that user | Yes: the app keeps and refreshes them | Each refresh answers a new refresh token that replaces the old one |

## Webhooks and agents

| Credential | Who makes it | Where it lives | Do you handle it? | How it is rotated |
| --- | --- | --- | --- | --- |
| Sign-in webhook secret | Setting the sign-in webhook | `HARAKUMO_AUTH_WEBHOOK_SECRET` | No: it is stored as the setting | Rotate it on the webhook; the old one stops at once |
| Payment webhook secret | Setting the payment webhook | `HARAKUMO_PAYMENTS_WEBHOOK_SECRET` when your AI sets it (set_payment_webhook); otherwise answered once | Only when it is answered once: store it as that setting | Rotate it on the webhook; the old one stops at once |
| Agent events secret | Turning an agent's app events on | `HARAKUMO_AGENT_<id>_EVENTS_SECRET` when your AI turns them on; the agent's page shows it once otherwise | Only when it is shown once: store it as that setting | A new secret (events: "rotate"); the old one stops at once |
| Agent tools secret | Saving an agent's first function tool | `HARAKUMO_AGENT_TOOLS_SECRET` | No: the function reads it once redeployed | It is the project's, kept as the setting |
| Agent chat id (hkchat_…) | Turning visitor chat on | The page that embeds the chat | Yes, and it is public | A new id (chat: "rotate") |

## Links

| Credential | Who makes it | Where it lives | Do you handle it? | How it is rotated |
| --- | --- | --- | --- | --- |
| Signed storage link (upload or download) | Your server asks for one per file | Handed to a browser or phone | Yes: pass it on, never keep it | Each one ends on its own (an upload link within 15 minutes) |
| Video upload link and live stream key | Creating a video or live channel | The uploader, or the broadcaster | Yes: the stream key is a secret, shown on the project's Media page | A new upload link replaces an expired one; delete a channel to end its key |

## Set by the platform

- `HARAKUMO_PROJECT_ID`, the project's id, in every app, build, edge program and function.
- `HARAKUMO_API_KEY`, the app's own key (above), in every deploy of the project's site, app and functions.
- `HARAKUMO_DATABASE_ID`, `HARAKUMO_BUCKET_ID`, `HARAKUMO_AUTH_POOL_ID` and `HARAKUMO_AUTH_CLIENT_ID`, the ids `new Harakumo()` (SDK 0.5.0 or later) and the Build Standard read by default, when the project has exactly one database, bucket and sign-in pool. A variable of your own with one of these names in Environment is used instead.
- Your own third-party secrets (a GitHub token for a private repository, push keys for Apple and Google) are yours: set them as environment variables, and they are stored sealed like the rest.
