---
title: "Update a secret"
method: PATCH
path: "/api/secrets/{id}"
---

# Update a secret

`PATCH /api/secrets/{id}`

## Request

- Base URL: `https://api.hyperbrowser.ai`
- URL: `https://api.hyperbrowser.ai/api/secrets/{id}`
- Auth: API key in header `x-api-key`
- TypeScript: <https://skmtc.dev/hyperbrowser/apis/hyperbrowser-api/docs/api/secrets/:id/patch.ts> (a function with typed inputs; its response is checked against the schema)

Updates a secret's description or metadata, such as its allowed origins, without uploading a new value. Metadata is merged by top-level member: each member you send replaces the stored one, and `null` removes it. Secrets are enabled for teams on request; please contact support to enable them (otherwise 403 SECRETS_FEATURE_DISABLED). Restricted API keys need the secrets.manage scope. When you're signed in rather than using an API key, you must be a team owner or admin (otherwise 403 SECRETS_ADMIN_REQUIRED).

## Path parameters

- `id` string, uuid, required

## Request body

- UpdateSecretParams: Provide at least one of `description` and `metadata`.
  - `description` string: Replaces the description. Trimmed before it's stored.
  - `metadata` object: Merged into the stored metadata by top-level member: each member you send replaces the stored one, `null` removes it, and members you don't send are kept. So `{"browser": {"allowedOrigins": [...]}}` replaces the allowed origins, and `{"browser": null}` clears them. `op_token` secrets accept only `{}`.
    - `browser` object, nullable: Replaces the secret's browser settings, or removes them with `null`, after which the secret can't be filled until origins are set again.
      - `allowedOrigins` string[], required: Origins a page or frame must be on before anything is typed, as `scheme://host[:port]`. The same rules as `SecretBrowserMetadata.allowedOrigins` apply.

## Response `200`

Success

- Secret: A secret. The API never returns its value.
  - `id` string, uuid, required
  - `name` string, required: 1-128 letters, digits, `_` or `-`, starting with a letter or digit. Unique within your team.
  - `description` string, required
  - `type` 'secret' | 'totp' | 'op_token', required: What the value is. Fixed at creation. `secret`: any string, set as an environment variable and, once it has allowed origins, typed into browser pages. `totp`: an authenticator seed (base32, or an `otpauth://totp/` URI); environment variables get the code current when the process starts, and fills type the code current at fill time. `op_token`: a 1Password service account token, used only to read the `onePassword` fields of a sandbox create, process start or browser credential fill; it's never an environment variable, a vault entry or a value typed into a page. Treat types you don't recognize as opaque: more may be added.
  - `metadata` SecretMetadata, required: Settings that aren't secret, returned by the API and editable without uploading a new value. A `secret` or `totp` secret can't be filled into browser pages until `browser.allowedOrigins` is set. An `op_token` secret accepts only `{}` (otherwise 400 SECRET_METADATA_INVALID).
    - `browser` SecretBrowserMetadata: Where the secret may be typed into browser pages. Allowed for `secret` and `totp`.
      - `allowedOrigins` string[], required: Origins a page or frame must be on before anything is typed, as `scheme://host[:port]` with no path, such as `https://github.com`. A leading `*.` matches any subdomain but not the domain itself, and must name at least two labels (`*.example.com`); you can't use a wildcard with an IP address. Origins must use https, except `http://localhost`, `http://127.0.0.1` and `http://[::1]`. Hyperbrowser lowercases origins, drops default ports and removes duplicates. An invalid entry returns 400 SECRET_METADATA_INVALID naming it.
  - `encryptionContext` string, required: Copy this verbatim into the `ctx` header of every envelope you upload for this secret. Don't build it yourself: it includes the secret's type for types other than `secret`, and an envelope sealed with another context returns 400 SECRET_ENVELOPE_INVALID.
  - `latestVersion` integer, nullable, required: The newest version number, or null until a value is uploaded.
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required
  - `protection` 'platform' | 'customer': `platform` (the default): the value is encrypted to the platform key. `customer`: each version is also wrapped with your own key, and each use passes the envelope you unwrapped. See [Customer-protected secrets](/sandboxes/customer-keys).

## Other responses

- `400`: Invalid request body, neither description nor metadata given, or SECRET_METADATA_INVALID.
- `401`: Authentication required.
- `403`: API_KEY_SCOPE_DENIED (the API key lacks a required scope), SECRETS_FEATURE_DISABLED, or SECRETS_ADMIN_REQUIRED.
- `404`: SECRET_NOT_FOUND: no secret with this ID in your team.
- `500`: Internal server error.

## Changes

- **2026-11-10** `94dc06948680`: 1 info
  - added the optional property `protection` to the response with the `200` status
- **2026-10-15** `6ca0b00ee564`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/hyperbrowser/apis/hyperbrowser-api/changes/api/secrets/:id/patch.md)

---

[API](https://skmtc.dev/hyperbrowser/apis/hyperbrowser-api.md) - [All operations](https://skmtc.dev/hyperbrowser/apis/hyperbrowser-api/llms.txt) - [OpenAPI document](https://skmtc.dev/hyperbrowser/apis/hyperbrowser-api/revisions/ef089024c533?raw)
