# Secrets

Secrets hold the values a cloud run needs. They are write only: no route ever returns a value. Every route here is session only and needs an owner or admin. API keys are refused with 403, and members cannot manage secrets. Responses carry `cache-control: no-store`. How runs use secrets is on [Organization secrets](/docs/cloud/secrets).

## The secret object

| Field                      | Type      | Meaning                                      |
| -------------------------- | --------- | -------------------------------------------- |
| `id`                       | UUID      |                                              |
| `organization_id`          | UUID      |                                              |
| `name`                     | string    | `^[A-Z][A-Z0-9_]*$`, at most 128 characters. |
| `created_at`, `updated_at` | date-time |                                              |

## List secrets

`GET /v1/secrets?organization=<slug>`

Response `200` `{ "secrets": [ ... ] }`: names and timestamps only.

## Set a secret

`PUT /v1/secrets`

| Field             | Type   | Meaning                                  |
| ----------------- | ------ | ---------------------------------------- |
| `organization_id` | UUID   | Required.                                |
| `name`            | string | Required. Upper snake case.              |
| `value`           | string | Required. At most 32,768 bytes of UTF-8. |

Creates the secret, or replaces its value when the name exists. Response `200`: the secret, without its value. Each set is audited by name, never by value.

## Delete a secret

`DELETE /v1/secrets/:id`

Response `200` `{ "deleted": true }`. Audited.

## OpenRouter

The organization's OpenRouter key is its `OPENROUTER_API_KEY` secret. These routes connect it by signing in with OpenRouter or by pasting a key. They are session only. Any member may read the status; connecting and pasting need an owner or admin. The key never appears in a response, error, or log.

| Method | Path                       | Body or query                                                   | Result                                                                                                             |
| ------ | -------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| GET    | `/v1/openrouter`           | query `organization` (slug)                                     | `{ "connection" }`, or `{ "connection": null }` when none is saved.                                                |
| POST   | `/v1/openrouter/grants`    | `{ "organization_id", "return_to": "secrets" or "onboarding" }` | 201 `{ "authorization_url" }`: send the user there to approve on OpenRouter. The sign-in expires after 10 minutes. |
| POST   | `/v1/openrouter/exchanges` | `{ "code", "state" }` from OpenRouter's redirect                | `{ "organization_slug", "return_to" }`. Saves the key OpenRouter issued.                                           |
| PUT    | `/v1/openrouter/keys`      | `{ "organization_id", "key" }`                                  | `{ "connection" }`. Saves a pasted key.                                                                            |

`connection` is:

| Field                  | Meaning                                                                                                     |
| ---------------------- | ----------------------------------------------------------------------------------------------------------- |
| `secret_id`            | The `OPENROUTER_API_KEY` secret.                                                                            |
| `saved_at`, `saved_by` | When and by whom it was saved.                                                                              |
| `label`                | The key's label on OpenRouter, or null. A key from sign-in is labelled `<organization name> - Workbenches`. |
| `credits`              | `{ "remaining_usd", "limit_usd" }` when OpenRouter reports them, or null.                                   |
| `key_hash`             | SHA-256 of the key, or null.                                                                                |
