# Save a secret. The value is sealed and never returned.

`POST /o/{org}/secrets`

`kind: env` sets the environment variable `name` on every session that uses it; `name` follows
environment-variable rules and may not be one Rush sets itself. `kind: header` never reaches the
session's environment: E2B's egress proxy adds `header_name: header_format(value)` to the
session's HTTPS requests to each host in `targets`, outside the sandbox. `Basic {value}` takes
`username:password` and encodes it. A header secret's `name` is a label (letters, digits, `.`,
`-`, `_`). `kind: login` takes one https origin in `targets` plus `username`, `password` and an
optional base32 `totp_secret`. Its value is never in the session's environment or conversation:
the agent runs `rush-sign-in <name>` and Rush types it into the session's browser on that origin
only. The agent shares that browser, so this keeps the value out of the transcript, not out of the sandbox.
`project_id` is required: the secret reaches every session in that Project.

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `org` | path | string | yes | The org's slug or id. A caller with no role in the org gets `404`. |

## Request body

- `project_id` (string, required): A Project of this org; every session in it gets the secret.
- `name` (string, required)
- `kind` (string, optional, one of `env`, `header`, `login`, default `"env"`)
- `value` (string, required)
- `description` (string, optional)
- `targets` (array of string, optional): `header` only: bare lowercase hostnames, such as `api.stripe.com` (no scheme, port, path, wildcard or IP).
- `header_name` (string, optional): `header` only: the header to set; `Host`, `Content-Length` and hop-by-hop headers are refused.
- `header_format` (string, optional, one of `{value}`, `Bearer {value}`, `Basic {value}`): `header` only.
- `username` (string, optional): `login` only.
- `password` (string, optional): `login` only.
- `totp_secret` (string, optional): `login` only: the base32 two-factor setup key.

## Example request

```bash
curl -X POST "https://api.prix.dev/o/$RUSH_ORG/secrets" \
  -H "Authorization: Bearer $RUSH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "project_id": "3f6c1e2a-8b4d-4c1e-9a7f-2d5b6e8c0a14",
    "name": "string",
    "value": "string"
  }'
```

```typescript
const org = process.env.RUSH_ORG;

const res = await fetch(`https://api.prix.dev/o/${org}/secrets`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.RUSH_TOKEN}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    project_id: "3f6c1e2a-8b4d-4c1e-9a7f-2d5b6e8c0a14",
    name: "string",
    value: "string",
  }),
});

console.log(res.status, await res.json());
```

```python
import os

import requests

org = os.environ["RUSH_ORG"]

res = requests.post(
    f"https://api.prix.dev/o/{org}/secrets",
    headers={"Authorization": f"Bearer {os.environ['RUSH_TOKEN']}"},
    json={
        "project_id": "3f6c1e2a-8b4d-4c1e-9a7f-2d5b6e8c0a14",
        "name": "string",
        "value": "string",
    },
)

print(res.status_code, res.json())
```

## Responses

### 201

Saved.

- `data` (Secret, required): A secret without its value.
  - `id` (string, required)
  - `name` (string, required)
  - `kind` (string, required, one of `env`, `header`, `login`)
  - `description` (string, required)
  - `project_id` (string, required)
  - `targets` (array of string, required): Hosts (header) or one origin (login); empty for env.
  - `header_name` (string | null, optional)
  - `header_format` (string | null, optional)
  - `has_totp` (boolean, required)
  - `created_by` (string | null, required): Null once the member who added it has deleted their account; the secret stays with the Project.
  - `created_at` (string, required)
  - `value_updated_at` (string, required)
  - `last_used_at` (string | null, optional)

### 409

`SECRET_NAME_TAKEN`: a secret with this name already exists in the same scope.

### 422

`SECRET_PROJECT_REQUIRED`, `SECRET_PROJECT_NOT_IN_ORG`, `SECRET_NAME_INVALID`, `SECRET_VALUE_INVALID`, `SECRET_KIND_INVALID`, `SECRET_TARGET_INVALID` or `SECRET_DESCRIPTION_INVALID`.

## Example response (201)

```json
{
  "data": {
    "id": "3f6c1e2a-8b4d-4c1e-9a7f-2d5b6e8c0a14",
    "name": "string",
    "kind": "env",
    "description": "string",
    "project_id": "3f6c1e2a-8b4d-4c1e-9a7f-2d5b6e8c0a14",
    "targets": [
      "string"
    ],
    "header_name": "string",
    "header_format": "string",
    "has_totp": true,
    "created_by": "3f6c1e2a-8b4d-4c1e-9a7f-2d5b6e8c0a14",
    "created_at": "2026-10-06T12:00:00Z",
    "value_updated_at": "2026-10-06T12:00:00Z",
    "last_used_at": "2026-10-06T12:00:00Z"
  }
}
```
