# Secrets

Manage encrypted project secrets

OpenAPI: [api.spice.ai/openapi.json](https://api.spice.ai/openapi.json)

- [`GET /v1/projects/{projectId}/secrets`: List secrets](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-secrets#get-v1-projects-projectid-secrets)
- [`POST /v1/projects/{projectId}/secrets`: Create or update a secret](https://spice.ai/docs/cloud/api/management/secrets/post-v1-projects-projectid-secrets#post-v1-projects-projectid-secrets)
- [`GET /v1/projects/{projectId}/secrets/{secretName}`: Get a secret](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-secrets-secretname#get-v1-projects-projectid-secrets-secretname)
- [`DELETE /v1/projects/{projectId}/secrets/{secretName}`: Delete a secret](https://spice.ai/docs/cloud/api/management/secrets/delete-v1-projects-projectid-secrets-secretname#delete-v1-projects-projectid-secrets-secretname)
- [`GET /v1/projects/{projectId}/org-secrets`: List the organization secrets linked to a project](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-org-secrets#get-v1-projects-projectid-org-secrets)
- [`PUT /v1/projects/{projectId}/org-secrets/{secretName}`: Link an organization secret to a project](https://spice.ai/docs/cloud/api/management/secrets/put-v1-projects-projectid-org-secrets-secretname#put-v1-projects-projectid-org-secrets-secretname)
- [`DELETE /v1/projects/{projectId}/org-secrets/{secretName}`: Unlink an organization secret from a project](https://spice.ai/docs/cloud/api/management/secrets/delete-v1-projects-projectid-org-secrets-secretname#delete-v1-projects-projectid-org-secrets-secretname)
- [`GET /v1/orgs/{orgId}/secrets`: List organization secrets](https://spice.ai/docs/cloud/api/management/secrets/get-v1-orgs-orgid-secrets)
- [`POST /v1/orgs/{orgId}/secrets`: Create or update an organization secret](https://spice.ai/docs/cloud/api/management/secrets/post-v1-orgs-orgid-secrets)
- [`GET /v1/orgs/{orgId}/secrets/{secretName}`: Get an organization secret](https://spice.ai/docs/cloud/api/management/secrets/get-v1-orgs-orgid-secrets-secretname)
- [`DELETE /v1/orgs/{orgId}/secrets/{secretName}`: Delete an organization secret](https://spice.ai/docs/cloud/api/management/secrets/delete-v1-orgs-orgid-secrets-secretname)
- [`GET /v1/orgs/{orgId}/projects/{projectId}/secrets`: List secrets](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-secrets#get-v1-orgs-orgid-projects-projectid-secrets)
- [`POST /v1/orgs/{orgId}/projects/{projectId}/secrets`: Create or update a secret](https://spice.ai/docs/cloud/api/management/secrets/post-v1-projects-projectid-secrets#post-v1-orgs-orgid-projects-projectid-secrets)
- [`GET /v1/orgs/{orgId}/projects/{projectId}/secrets/{secretName}`: Get a secret](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-secrets-secretname#get-v1-orgs-orgid-projects-projectid-secrets-secretname)
- [`DELETE /v1/orgs/{orgId}/projects/{projectId}/secrets/{secretName}`: Delete a secret](https://spice.ai/docs/cloud/api/management/secrets/delete-v1-projects-projectid-secrets-secretname#delete-v1-orgs-orgid-projects-projectid-secrets-secretname)
- [`GET /v1/orgs/{orgId}/projects/{projectId}/org-secrets`: List the organization secrets linked to a project](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-org-secrets#get-v1-orgs-orgid-projects-projectid-org-secrets)
- [`PUT /v1/orgs/{orgId}/projects/{projectId}/org-secrets/{secretName}`: Link an organization secret to a project](https://spice.ai/docs/cloud/api/management/secrets/put-v1-projects-projectid-org-secrets-secretname#put-v1-orgs-orgid-projects-projectid-org-secrets-secretname)
- [`DELETE /v1/orgs/{orgId}/projects/{projectId}/org-secrets/{secretName}`: Unlink an organization secret from a project](https://spice.ai/docs/cloud/api/management/secrets/delete-v1-projects-projectid-org-secrets-secretname#delete-v1-orgs-orgid-projects-projectid-org-secrets-secretname)
- [`GET /v1/apps/{appId}/secrets`: List secrets](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-secrets#get-v1-apps-appid-secrets) (deprecated)
- [`POST /v1/apps/{appId}/secrets`: Create or update a secret](https://spice.ai/docs/cloud/api/management/secrets/post-v1-projects-projectid-secrets#post-v1-apps-appid-secrets) (deprecated)
- [`GET /v1/apps/{appId}/secrets/{secretName}`: Get a secret](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-secrets-secretname#get-v1-apps-appid-secrets-secretname) (deprecated)
- [`DELETE /v1/apps/{appId}/secrets/{secretName}`: Delete a secret](https://spice.ai/docs/cloud/api/management/secrets/delete-v1-projects-projectid-secrets-secretname#delete-v1-apps-appid-secrets-secretname) (deprecated)
- [`GET /v1/apps/{appId}/org-secrets`: List the organization secrets linked to a project](https://spice.ai/docs/cloud/api/management/secrets/get-v1-projects-projectid-org-secrets#get-v1-apps-appid-org-secrets) (deprecated)
- [`PUT /v1/apps/{appId}/org-secrets/{secretName}`: Link an organization secret to a project](https://spice.ai/docs/cloud/api/management/secrets/put-v1-projects-projectid-org-secrets-secretname#put-v1-apps-appid-org-secrets-secretname) (deprecated)
- [`DELETE /v1/apps/{appId}/org-secrets/{secretName}`: Unlink an organization secret from a project](https://spice.ai/docs/cloud/api/management/secrets/delete-v1-projects-projectid-org-secrets-secretname#delete-v1-apps-appid-org-secrets-secretname) (deprecated)

## List secrets

`GET /v1/projects/{projectId}/secrets`

Returns all secrets for the specified project. Secret values are always masked.

### Path parameters

- `projectId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/projects/<projectId>/secrets" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/projects/<projectId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

List of secrets

Content type: `application/json`

- `secrets` (array of object)
  - `id` (integer): Unique identifier for the secret
  - `name` (string): Name of the secret
  - `value` (string): Always masked with asterisks
  - `created_at` (string (date-time)): Timestamp when the secret was created
  - `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or viewer role cannot perform write operations

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Create or update a secret

`POST /v1/projects/{projectId}/secrets`

Creates a new secret or updates an existing secret with the same name. The secret value is encrypted at rest.

### Path parameters

- `projectId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Request body

Required.

Content type: `application/json`

- `name` (string, required): Secret name (must start with a letter or underscore, alphanumeric and underscores only). Pattern: `^[a-zA-Z_][a-zA-Z0-9_]*$`.
- `value` (string, required): Secret value (will be encrypted at rest)

### Example request

```bash
curl -X POST "https://api.spice.ai/v1/projects/<projectId>/secrets" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "value": "string"
  }'
```

```http
POST /v1/projects/<projectId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
Content-Type: application/json
Content-Length: 43

{
  "name": "string",
  "value": "string"
}
```

### Responses

**200 OK**

Secret created or updated successfully

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid request body or project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Get a secret

`GET /v1/projects/{projectId}/secrets/{secretName}`

Returns a specific secret by name. The secret value is always masked.

### Path parameters

- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/projects/<projectId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/projects/<projectId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

Secret details (value is masked)

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or admin or owner role required

**404 Not Found**

Project or secret not found

**500 Internal Server Error**

Internal server error

## Delete a secret

`DELETE /v1/projects/{projectId}/secrets/{secretName}`

Permanently deletes a secret by name.

### Path parameters

- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X DELETE "https://api.spice.ai/v1/projects/<projectId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
DELETE /v1/projects/<projectId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**204 No Content**

Secret deleted successfully

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope

**404 Not Found**

Project or secret not found

**500 Internal Server Error**

Internal server error

## List the organization secrets linked to a project

`GET /v1/projects/{projectId}/org-secrets`

Returns the organization secrets this project receives at deploy time. Values are always masked. `shadowed` is true when a project secret has the same name; the project secret is the one delivered.

### Path parameters

- `projectId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/projects/<projectId>/org-secrets" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/projects/<projectId>/org-secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The linked organization secrets, masked

Content type: `application/json`

- `org_secrets` (array of object)
  - `id` (integer): Unique identifier for the secret
  - `name` (string): Name of the secret
  - `value` (string): Always masked with asterisks
  - `created_at` (string (date-time)): Timestamp when the secret was created
  - `updated_at` (string (date-time)): Timestamp when the secret was last updated
  - `shadowed` (boolean)

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:read) or the viewer role

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Link an organization secret to a project

`PUT /v1/projects/{projectId}/org-secrets/{secretName}`

Makes the named organization secret available to the project at deploy time. Linking a secret that is already linked changes nothing. The project's own secrets are not changed; a project secret with the same name takes precedence.

### Path parameters

- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the organization secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X PUT "https://api.spice.ai/v1/projects/<projectId>/org-secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
PUT /v1/projects/<projectId>/org-secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The secret was already linked

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**201 Created**

The secret was linked

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID or secret name

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write) or the viewer role

**404 Not Found**

Project or organization secret not found

**409 Conflict**

The project already links the maximum of 1000 organization secrets (code: `org_secret_link_limit`)

**429 Too Many Requests**

Another link change is in progress for this project. Try again.

**500 Internal Server Error**

Internal server error

**503 Service Unavailable**

Failed to link the organization secret. Try again.

## Unlink an organization secret from a project

`DELETE /v1/projects/{projectId}/org-secrets/{secretName}`

Stops delivering the named organization secret to the project from its next deploy. The secret itself is kept.

### Path parameters

- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the organization secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X DELETE "https://api.spice.ai/v1/projects/<projectId>/org-secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
DELETE /v1/projects/<projectId>/org-secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**204 No Content**

The secret was unlinked

**400 Bad Request**

Invalid project ID or secret name

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write) or the viewer role

**404 Not Found**

Project or organization secret not found, or the secret is not linked to the project

**429 Too Many Requests**

Another link change is in progress for this project. Try again.

**500 Internal Server Error**

Internal server error

**503 Service Unavailable**

Failed to unlink the organization secret. Try again.

## List organization secrets

`GET /v1/orgs/{orgId}/secrets`

Returns the organization's secrets. Values are always masked. Platform-managed secrets are not listed. An organization secret reaches a project only through a link (see /v1/projects/{projectId}/org-secrets).

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/orgs/<orgId>/secrets" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/orgs/<orgId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The organization's secrets, masked

Content type: `application/json`

- `secrets` (array of object)
  - `id` (integer): Unique identifier for the secret
  - `name` (string): Name of the secret
  - `value` (string): Always masked with asterisks
  - `created_at` (string (date-time)): Timestamp when the secret was created
  - `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`)

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:read), the viewer role, or the caller is not a member of the organization (`org_forbidden`), a machine credential named an organization other than its own (`org_assertion_mismatch`), or the organization a machine credential is bound to has been deleted (`org_deleted`)

**500 Internal Server Error**

Internal server error

## Create or update an organization secret

`POST /v1/orgs/{orgId}/secrets`

Creates an organization secret, or replaces the value of the one with the same name. The value is encrypted at rest and never returned. A name reserved by a platform-managed secret is refused.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Request body

Required.

Content type: `application/json`

- `name` (string, required): Maximum length: `255`. Pattern: `^[a-zA-Z_][a-zA-Z0-9_]*$`.
- `value` (string, required): Maximum length: `10000`.

### Example request

```bash
curl -X POST "https://api.spice.ai/v1/orgs/<orgId>/secrets" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "value": "string"
  }'
```

```http
POST /v1/orgs/<orgId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
Content-Type: application/json
Content-Length: 43

{
  "name": "string",
  "value": "string"
}
```

### Responses

**200 OK**

The existing secret's value was replaced

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**201 Created**

The secret was created

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid org id (`invalid_org_id`), X-Org-Name does not name that org (`org_path_mismatch`), or the JSON body is not valid

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write), the viewer role, or the caller is not a member of the organization (`org_forbidden`), a machine credential named an organization other than its own (`org_assertion_mismatch`), or the organization a machine credential is bound to has been deleted (`org_deleted`)

**409 Conflict**

The name is reserved by a platform-managed secret (code: `secret_name_reserved`)

**413 Content Too Large**

Request body too large

**500 Internal Server Error**

Internal server error

## Get an organization secret

`GET /v1/orgs/{orgId}/secrets/{secretName}`

Returns one organization secret's metadata. The value is always masked.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/orgs/<orgId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/orgs/<orgId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The secret, masked

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid org id (`invalid_org_id`), X-Org-Name does not name that org (`org_path_mismatch`), or invalid secret name

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:read), the viewer role, or the caller is not a member of the organization (`org_forbidden`), a machine credential named an organization other than its own (`org_assertion_mismatch`), or the organization a machine credential is bound to has been deleted (`org_deleted`)

**404 Not Found**

Secret not found

**500 Internal Server Error**

Internal server error

## Delete an organization secret

`DELETE /v1/orgs/{orgId}/secrets/{secretName}`

Deletes an organization secret and every project link to it. Deployments that reference it stop receiving it on their next deploy.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X DELETE "https://api.spice.ai/v1/orgs/<orgId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
DELETE /v1/orgs/<orgId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**204 No Content**

Secret deleted

**400 Bad Request**

Invalid org id (`invalid_org_id`), X-Org-Name does not name that org (`org_path_mismatch`), or invalid secret name

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write), the caller is not an admin or owner, or not a member of the organization (`org_forbidden`), a machine credential named an organization other than its own (`org_assertion_mismatch`), or the organization a machine credential is bound to has been deleted (`org_deleted`)

**404 Not Found**

Secret not found

**500 Internal Server Error**

Internal server error

## List secrets

`GET /v1/orgs/{orgId}/projects/{projectId}/secrets`

The org is `orgId` in the path. Returns all secrets for the specified project. Secret values are always masked.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `projectId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/secrets" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/orgs/<orgId>/projects/<projectId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

List of secrets

Content type: `application/json`

- `secrets` (array of object)
  - `id` (integer): Unique identifier for the secret
  - `name` (string): Name of the secret
  - `value` (string): Always masked with asterisks
  - `created_at` (string (date-time)): Timestamp when the secret was created
  - `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or viewer role cannot perform write operations. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Create or update a secret

`POST /v1/orgs/{orgId}/projects/{projectId}/secrets`

The org is `orgId` in the path. Creates a new secret or updates an existing secret with the same name. The secret value is encrypted at rest.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `projectId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Request body

Required.

Content type: `application/json`

- `name` (string, required): Secret name (must start with a letter or underscore, alphanumeric and underscores only). Pattern: `^[a-zA-Z_][a-zA-Z0-9_]*$`.
- `value` (string, required): Secret value (will be encrypted at rest)

### Example request

```bash
curl -X POST "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/secrets" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "value": "string"
  }'
```

```http
POST /v1/orgs/<orgId>/projects/<projectId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
Content-Type: application/json
Content-Length: 43

{
  "name": "string",
  "value": "string"
}
```

### Responses

**200 OK**

Secret created or updated successfully

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid request body or project ID. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Get a secret

`GET /v1/orgs/{orgId}/projects/{projectId}/secrets/{secretName}`

The org is `orgId` in the path. Returns a specific secret by name. The secret value is always masked.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/orgs/<orgId>/projects/<projectId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

Secret details (value is masked)

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or admin or owner role required. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Project or secret not found

**500 Internal Server Error**

Internal server error

## Delete a secret

`DELETE /v1/orgs/{orgId}/projects/{projectId}/secrets/{secretName}`

The org is `orgId` in the path. Permanently deletes a secret by name.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X DELETE "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
DELETE /v1/orgs/<orgId>/projects/<projectId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**204 No Content**

Secret deleted successfully

**400 Bad Request**

Invalid project ID. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Project or secret not found

**500 Internal Server Error**

Internal server error

## List the organization secrets linked to a project

`GET /v1/orgs/{orgId}/projects/{projectId}/org-secrets`

The org is `orgId` in the path. Returns the organization secrets this project receives at deploy time. Values are always masked. `shadowed` is true when a project secret has the same name; the project secret is the one delivered.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `projectId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/org-secrets" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/orgs/<orgId>/projects/<projectId>/org-secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The linked organization secrets, masked

Content type: `application/json`

- `org_secrets` (array of object)
  - `id` (integer): Unique identifier for the secret
  - `name` (string): Name of the secret
  - `value` (string): Always masked with asterisks
  - `created_at` (string (date-time)): Timestamp when the secret was created
  - `updated_at` (string (date-time)): Timestamp when the secret was last updated
  - `shadowed` (boolean)

**400 Bad Request**

Invalid project ID. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:read) or the viewer role. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Link an organization secret to a project

`PUT /v1/orgs/{orgId}/projects/{projectId}/org-secrets/{secretName}`

The org is `orgId` in the path. Makes the named organization secret available to the project at deploy time. Linking a secret that is already linked changes nothing. The project's own secrets are not changed; a project secret with the same name takes precedence.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the organization secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X PUT "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/org-secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
PUT /v1/orgs/<orgId>/projects/<projectId>/org-secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The secret was already linked

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**201 Created**

The secret was linked

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID or secret name. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write) or the viewer role. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Project or organization secret not found

**409 Conflict**

The project already links the maximum of 1000 organization secrets (code: `org_secret_link_limit`)

**429 Too Many Requests**

Another link change is in progress for this project. Try again.

**500 Internal Server Error**

Internal server error

**503 Service Unavailable**

Failed to link the organization secret. Try again.

## Unlink an organization secret from a project

`DELETE /v1/orgs/{orgId}/projects/{projectId}/org-secrets/{secretName}`

The org is `orgId` in the path. Stops delivering the named organization secret to the project from its next deploy. The secret itself is kept.

### Path parameters

- `orgId` (integer, required): The org id from GET /v1/orgs. Minimum: `1`.
- `projectId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the organization secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): When present, X-Org-Name must name the same org as orgId. Otherwise the request returns org\_path\_mismatch (400). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X DELETE "https://api.spice.ai/v1/orgs/<orgId>/projects/<projectId>/org-secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
DELETE /v1/orgs/<orgId>/projects/<projectId>/org-secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**204 No Content**

The secret was unlinked

**400 Bad Request**

Invalid project ID or secret name. orgId is not a valid org id (`invalid_org_id`), or X-Org-Name does not name that org (`org_path_mismatch`).

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write) or the viewer role. The caller is not a member of the org (`org_forbidden`). A machine credential named a different org (`org_assertion_mismatch`). The org is deleted (`org_deleted`).

**404 Not Found**

Project or organization secret not found, or the secret is not linked to the project

**429 Too Many Requests**

Another link change is in progress for this project. Try again.

**500 Internal Server Error**

Internal server error

**503 Service Unavailable**

Failed to unlink the organization secret. Try again.

## List secrets

`GET /v1/apps/{appId}/secrets` (deprecated)

Legacy alias of `/v1/projects/{projectId}/secrets`. Projects were previously called apps. Returns all secrets for the specified project. Secret values are always masked.

### Path parameters

- `appId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/apps/<appId>/secrets" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/apps/<appId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

List of secrets

Content type: `application/json`

- `secrets` (array of object)
  - `id` (integer): Unique identifier for the secret
  - `name` (string): Name of the secret
  - `value` (string): Always masked with asterisks
  - `created_at` (string (date-time)): Timestamp when the secret was created
  - `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or viewer role cannot perform write operations

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Create or update a secret

`POST /v1/apps/{appId}/secrets` (deprecated)

Legacy alias of `/v1/projects/{projectId}/secrets`. Projects were previously called apps. Creates a new secret or updates an existing secret with the same name. The secret value is encrypted at rest.

### Path parameters

- `appId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Request body

Required.

Content type: `application/json`

- `name` (string, required): Secret name (must start with a letter or underscore, alphanumeric and underscores only). Pattern: `^[a-zA-Z_][a-zA-Z0-9_]*$`.
- `value` (string, required): Secret value (will be encrypted at rest)

### Example request

```bash
curl -X POST "https://api.spice.ai/v1/apps/<appId>/secrets" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string",
    "value": "string"
  }'
```

```http
POST /v1/apps/<appId>/secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
Content-Type: application/json
Content-Length: 43

{
  "name": "string",
  "value": "string"
}
```

### Responses

**200 OK**

Secret created or updated successfully

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid request body or project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Get a secret

`GET /v1/apps/{appId}/secrets/{secretName}` (deprecated)

Legacy alias of `/v1/projects/{projectId}/secrets/{secretName}`. Projects were previously called apps. Returns a specific secret by name. The secret value is always masked.

### Path parameters

- `appId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/apps/<appId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/apps/<appId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

Secret details (value is masked)

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope or admin or owner role required

**404 Not Found**

Project or secret not found

**500 Internal Server Error**

Internal server error

## Delete a secret

`DELETE /v1/apps/{appId}/secrets/{secretName}` (deprecated)

Legacy alias of `/v1/projects/{projectId}/secrets/{secretName}`. Projects were previously called apps. Permanently deletes a secret by name.

### Path parameters

- `appId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X DELETE "https://api.spice.ai/v1/apps/<appId>/secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
DELETE /v1/apps/<appId>/secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**204 No Content**

Secret deleted successfully

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope

**404 Not Found**

Project or secret not found

**500 Internal Server Error**

Internal server error

## List the organization secrets linked to a project

`GET /v1/apps/{appId}/org-secrets` (deprecated)

Legacy alias of `/v1/projects/{projectId}/org-secrets`. Projects were previously called apps. Returns the organization secrets this project receives at deploy time. Values are always masked. `shadowed` is true when a project secret has the same name; the project secret is the one delivered.

### Path parameters

- `appId` (integer, required): The ID of the project

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl "https://api.spice.ai/v1/apps/<appId>/org-secrets" \
  -H "Authorization: Bearer <token>"
```

```http
GET /v1/apps/<appId>/org-secrets HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The linked organization secrets, masked

Content type: `application/json`

- `org_secrets` (array of object)
  - `id` (integer): Unique identifier for the secret
  - `name` (string): Name of the secret
  - `value` (string): Always masked with asterisks
  - `created_at` (string (date-time)): Timestamp when the secret was created
  - `updated_at` (string (date-time)): Timestamp when the secret was last updated
  - `shadowed` (boolean)

**400 Bad Request**

Invalid project ID

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:read) or the viewer role

**404 Not Found**

Project not found

**500 Internal Server Error**

Internal server error

## Link an organization secret to a project

`PUT /v1/apps/{appId}/org-secrets/{secretName}` (deprecated)

Legacy alias of `/v1/projects/{projectId}/org-secrets/{secretName}`. Projects were previously called apps. Makes the named organization secret available to the project at deploy time. Linking a secret that is already linked changes nothing. The project's own secrets are not changed; a project secret with the same name takes precedence.

### Path parameters

- `appId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the organization secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X PUT "https://api.spice.ai/v1/apps/<appId>/org-secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
PUT /v1/apps/<appId>/org-secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**200 OK**

The secret was already linked

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**201 Created**

The secret was linked

Content type: `application/json`

- `id` (integer): Unique identifier for the secret
- `name` (string): Name of the secret
- `value` (string): Always masked with asterisks
- `created_at` (string (date-time)): Timestamp when the secret was created
- `updated_at` (string (date-time)): Timestamp when the secret was last updated

**400 Bad Request**

Invalid project ID or secret name

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write) or the viewer role

**404 Not Found**

Project or organization secret not found

**409 Conflict**

The project already links the maximum of 1000 organization secrets (code: `org_secret_link_limit`)

**429 Too Many Requests**

Another link change is in progress for this project. Try again.

**500 Internal Server Error**

Internal server error

**503 Service Unavailable**

Failed to link the organization secret. Try again.

## Unlink an organization secret from a project

`DELETE /v1/apps/{appId}/org-secrets/{secretName}` (deprecated)

Legacy alias of `/v1/projects/{projectId}/org-secrets/{secretName}`. Projects were previously called apps. Stops delivering the named organization secret to the project from its next deploy. The secret itself is kept.

### Path parameters

- `appId` (integer, required): The ID of the project
- `secretName` (string, required): The name of the organization secret

### Header parameters

- `Authorization` (string, required): `Bearer <token>`. [Authentication](https://spice.ai/docs/cloud/api/management#authentication) lists the tokens it accepts.
- `X-Org-Name` (string, optional): The organization to act on, by handle. Omit it to act on the organization the credential is bound to; sending it blank is a 400, not the same as omitting it. A user credential may name any organization its owner belongs to; a machine credential is pinned to its own. A portal session token is bound to none, so it must send this header on every route but `GET /v1/orgs` (400 `org_assertion_required` otherwise). Pattern: `^[A-Za-z0-9._-]{1,255}$`.

### Example request

```bash
curl -X DELETE "https://api.spice.ai/v1/apps/<appId>/org-secrets/<secretName>" \
  -H "Authorization: Bearer <token>"
```

```http
DELETE /v1/apps/<appId>/org-secrets/<secretName> HTTP/1.1
Host: api.spice.ai
Authorization: Bearer <token>
```

### Responses

**204 No Content**

The secret was unlinked

**400 Bad Request**

Invalid project ID or secret name

**401 Unauthorized**

Unauthorized

**403 Forbidden**

Insufficient scope (requires secrets:write) or the viewer role

**404 Not Found**

Project or organization secret not found, or the secret is not linked to the project

**429 Too Many Requests**

Another link change is in progress for this project. Try again.

**500 Internal Server Error**

Internal server error

**503 Service Unavailable**

Failed to unlink the organization secret. Try again.
