> ## Documentation Index
> Fetch the complete documentation index at: https://hyperbrowser.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 1Password

> Read fields from your 1Password account into sandbox processes and browser login forms, without storing the values in Hyperbrowser.

If you keep credentials in 1Password, you can pass fields from it to a sandbox process as environment variables, or [fill them into a login form](#browser-sessions) in a browser session. You name the fields with each request, and the sandbox's or session's host reads them from 1Password when the process starts or the fill runs. The values are never stored by Hyperbrowser or returned by the API.

Hyperbrowser signs in with a [1Password service account](https://developer.1password.com/docs/service-accounts/) token that you store as a [secret](/docs/sandboxes/secrets) of type `op_token`. The token is only used to read the fields you name, and never reaches a process or page.

<Note>
  1Password fields are part of [Secrets](/docs/sandboxes/secrets), which are enabled for teams on request, and need the same access as passing secrets: a restricted API key needs the `secrets.use` scope. They work for sandbox processes, image startup commands and [credential fill](/docs/sessions/credentials#fill-from-1password) in browser sessions.
</Note>

## Store the token

Create a service account in 1Password with read access to the vaults you need, then store its token as an `op_token` secret. An `op_token` secret takes no allowed origins: a browser fill names them in the request.

<CodeGroup>
  ```typescript Node.js theme={null}
  import { Hyperbrowser } from "@hyperbrowser/sdk";

  const client = new Hyperbrowser({ apiKey: process.env.HYPERBROWSER_API_KEY });

  await client.secrets.create({
    name: "op-token",
    type: "op_token",
    value: process.env.OP_SERVICE_ACCOUNT_TOKEN!,
  });
  ```

  ```python Python theme={null}
  import os
  from hyperbrowser import Hyperbrowser

  client = Hyperbrowser(api_key=os.environ["HYPERBROWSER_API_KEY"])

  client.secrets.create({
      "name": "op-token",
      "type": "op_token",
      "value": os.environ["OP_SERVICE_ACCOUNT_TOKEN"],
  })
  ```

  ```bash CLI theme={null}
  printf '%s' "$OP_SERVICE_ACCOUNT_TOKEN" | hx secrets create op-token --type op_token --stdin
  ```
</CodeGroup>

Each request uses the token's latest version. To rotate the token, add a new version to the secret.

## Pass fields to a command

Pass `onePassword` when you run a command: the token secret's name, the 1Password vault's name or ID, and `fields`, which maps each environment variable to an item, an optional section, and a field.

<CodeGroup>
  ```typescript Node.js theme={null}
  const sandbox = await client.sandboxes.create({ imageName: "node" });

  const result = await sandbox.exec("node login.js", {
    onePassword: {
      token: "op-token",
      vault: "Dev Vault for Testing",
      fields: {
        SC_USER: { item: "scrapingcourse login", field: "username" },
        SC_PASS: { item: "scrapingcourse login", field: "password" },
      },
    },
  });
  console.log(result.exitCode, result.stdout);
  ```

  ```python Python theme={null}
  sandbox = client.sandboxes.create({"image_name": "node"})

  result = sandbox.exec(
      "node login.js",
      one_password={
          "token": "op-token",
          "vault": "Dev Vault for Testing",
          "fields": {
              "SC_USER": {"item": "scrapingcourse login", "field": "username"},
              "SC_PASS": {"item": "scrapingcourse login", "field": "password"},
          },
      },
  )
  print(result.exit_code, result.stdout)
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.hyperbrowser.ai/api/sandbox/SANDBOX_ID/processes \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "command": "node login.js",
      "onePassword": {
        "token": "op-token",
        "vault": "Dev Vault for Testing",
        "fields": {
          "SC_USER": {"item": "scrapingcourse login", "field": "username"},
          "SC_PASS": {"item": "scrapingcourse login", "field": "password"}
        }
      }
    }'
  ```

  ```bash CLI theme={null}
  hx vm exec <sandbox-id> --1password-token op-token --1password-vault "Dev Vault for Testing" \
    --1password-field SC_USER="scrapingcourse login/username" \
    --1password-field SC_PASS="scrapingcourse login/password" \
    -- node login.js
  ```
</CodeGroup>

For long-running processes, pass the same `onePassword` to `sandbox.processes.start`:

<CodeGroup>
  ```typescript Node.js theme={null}
  const worker = await sandbox.processes.start("node worker.js", {
    onePassword: {
      token: "op-token",
      vault: "Dev Vault for Testing",
      fields: { SC_USER: { item: "scrapingcourse login", field: "username" } },
    },
  });
  console.log(worker.secrets);
  ```

  ```python Python theme={null}
  worker = sandbox.processes.start(
      "node worker.js",
      one_password={
          "token": "op-token",
          "vault": "Dev Vault for Testing",
          "fields": {"SC_USER": {"item": "scrapingcourse login", "field": "username"}},
      },
  )
  print(worker.secrets)
  ```

  ```bash CLI theme={null}
  hx vm process start <sandbox-id> --1password-token op-token --1password-vault "Dev Vault for Testing" \
    --1password-field SC_USER="scrapingcourse login/username" 'node worker.js'
  ```
</CodeGroup>

In the CLI, `--1password-field` is repeatable and takes `ENV=item/[section/]field`.

## Pass fields to an image's startup command

When you create a sandbox from an image with a startup command, pass `onePassword` to give that command the fields:

<CodeGroup>
  ```typescript Node.js theme={null}
  await client.sandboxes.create({
    imageName: "my-image",
    onePassword: {
      token: "op-token",
      vault: "Dev Vault for Testing",
      fields: { SC_USER: { item: "scrapingcourse login", field: "username" } },
    },
  });
  ```

  ```python Python theme={null}
  client.sandboxes.create({
      "image_name": "my-image",
      "one_password": {
          "token": "op-token",
          "vault": "Dev Vault for Testing",
          "fields": {"SC_USER": {"item": "scrapingcourse login", "field": "username"}},
      },
  })
  ```

  ```bash cURL theme={null}
  curl -X POST https://api.hyperbrowser.ai/api/sandbox \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "imageName": "my-image",
      "onePassword": {
        "token": "op-token",
        "vault": "Dev Vault for Testing",
        "fields": {"SC_USER": {"item": "scrapingcourse login", "field": "username"}}
      }
    }'
  ```

  ```bash CLI theme={null}
  hx vm create my-image --1password-token op-token --1password-vault "Dev Vault for Testing" \
    --1password-field SC_USER="scrapingcourse login/username"
  ```
</CodeGroup>

Like [startup secrets](/docs/sandboxes/secrets#pass-secrets-to-an-images-startup-command), this works for image launches on Firecracker sandboxes only. Otherwise the create fails with `SECRET_STARTUP_UNSUPPORTED`: create the sandbox without `onePassword`, and pass it to `exec` or `processes.start`.

## References

Each field becomes a [secret reference](https://developer.1password.com/docs/cli/secret-reference-syntax/), `op://<vault>/<item>/[<section>/]<field>`. For example, this field:

```json theme={null}
"SC_OTP": { "item": "scrapingcourse login", "section": "Security", "field": "one-time password?attribute=otp" }
```

reads `op://Dev Vault for Testing/scrapingcourse login/Security/one-time password?attribute=otp`, the current one-time password of that TOTP field rather than its seed.

* The vault, item, section and field are names or IDs of 1–256 characters, without `/` or `?`, and not `.` or `..`. Use the ID for a name that contains `/` or `?`.
* A field may end with one query, such as `?attribute=otp` or `?ssh-format=openssh`. Keys are lowercase letters and `-`; join several with `&`.
* A whole reference is at most 512 bytes.
* `fields` names 1–32 variables, keyed by environment variable names: letters, digits and `_`, not starting with a digit.
* A request uses one token and one 1Password vault.

The API checks these rules before anything starts. Whether an item or field exists is only checked when the process starts or the fill runs.

## How values are delivered

The sandbox's host signs in to 1Password and reads the fields when the process starts. Each value is set only in that process's environment, like a stored secret, and isn't refreshed: a later change in 1Password, or a one-time password that expires, doesn't reach a running process. Hyperbrowser never stores the values, and no endpoint returns them.

You can pass `onePassword` together with `vault` and `secrets`, as long as no variable comes from two of them: a variable from 1Password can't also be set by `vault`, `secrets` or `env`, or the request fails with `SECRET_SOURCES_INVALID`. Together they can set at most 32 variables.

The response lists each 1Password variable with its `reference` and the `tokenSecret` it signed in with, in `secrets` for a process or `startupSecrets` for a sandbox create:

```json theme={null}
{
  "secrets": [
    { "env": "SC_USER", "reference": "op://Dev Vault for Testing/scrapingcourse login/username",
      "tokenSecret": "op-token", "source": { "type": "onePassword" } }
  ]
}
```

Unlike stored secrets, these variables have no `name`, `secretId` or `version`, and never `overrides`.

## Browser sessions

A browser session can type 1Password fields into a login form. Attach the token when you create the session with `credentials: [{ onePassword: "op-token" }]`, then fill with `onePassword`, the fields' `ref`s and the `allowedOrigins` the values may be typed on. See [Fill from 1Password](/docs/sessions/credentials#fill-from-1password). An `op_token` can't be attached as a plain credential or be a vault entry.

## Errors

When the token or a field can't be used, nothing starts and you get one of these. A browser fill returns these 1Password codes with its own details; see [Fill from 1Password](/docs/sessions/credentials#fill-from-1password).

| Code | Status | Meaning |
| - | - | - |
| `SECRET_NOT_FOUND` | 404 | No secret has the token's name. |
| `SECRET_VERSION_NOT_FOUND` | 404 | The token secret has no value. |
| `SECRET_TYPE_MISMATCH` | 409 | The token names a secret that isn't an `op_token`. |
| `SECRET_SOURCES_INVALID` | 400 | A 1Password variable is also set by `vault`, `secrets` or `env`, or together they set more than 32 variables. |
| `SECRET_STARTUP_UNSUPPORTED` | 400 | On sandbox create: the launch has no startup command to pass the fields to, such as a snapshot launch. |
| `SECRET_ONEPASSWORD_REFERENCE_FAILED` | 422 | 1Password couldn't resolve a field; `details.envs` and `details.reasons` name the variables. Fix the fields. |
| `SECRET_ONEPASSWORD_AUTH_FAILED` | 422 | 1Password rejected the token, or the token is malformed or signs in outside `1password.com`, `1password.ca` and `1password.eu` (or their subdomains), so it wasn't sent. Add a new version of the `op_token` secret. |
| `SECRET_ONEPASSWORD_RATE_LIMITED` | 429 | 1Password is rate limiting the service account. Retryable. |
| `SECRET_ONEPASSWORD_FAILED` | 502, 503 | 1Password couldn't be reached. Retryable. |

A field that breaks the [reference rules](#references) is rejected with a 400 before anything starts. See [Secrets](/docs/sandboxes/secrets#errors) for the errors any secret can return.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.