Skip to main content
The Vault API stores credentials that your interns send to third-party APIs. Each secret is bound to an exact list of hostnames, and the intern runtime releases the value only to requests bound for one of those hostnames. Your code never handles the plaintext after the store call, and the API never returns it. All routes live under https://openrouter.ai/api/v1/vault and take an API key as a bearer token. The full route reference is in the Vault API reference. Every vault route, including GET, requires access to the Intern API programme. Outside the programme every route answers 404, the same response the dashboard gives when interns are not enabled. Writes are enabled separately inside the programme, see Writes are enabled per account. An intern’s own API key, the one OpenRouter creates for the intern when it is provisioned, can always read that intern’s secrets and effective secrets, whatever the programme says for its owner. That key is confined to its own intern: another intern’s routes and the workspace routes answer 404 to it, reads and writes alike. Its writes to its own intern follow the same rules as any other key.

Scope is selected by the API key

A secret belongs to either a workspace or one intern inside that workspace.
  • Workspace secrets live at /api/v1/vault/secrets. They are the pool you copy from when you give an intern a credential.
  • Intern secrets live at /api/v1/vault/interns/{internId}/secrets. They are the secrets that intern can use.
The workspace is always the active workspace of the API key that makes the request. You cannot pass a workspace ID, there is no default workspace, and a key never falls back to another scope. An intern route additionally requires internId to be an intern in that same workspace that the key may see, otherwise the request fails with 404. A key created by an organization member who is not an admin sees only the interns that member created and the interns in workspaces they administer, as on the Interns page and in the Interns API. Keys created by an organization admin, and keys with no creator, see every intern in the workspace. Vault routes are served on the global hostname only. A request to a regional hostname such as eu.openrouter.ai is refused with 403.

Responses carry metadata only

Every successful response describes secrets without their values.

Store a secret

PUT the value and its hosts to the secret’s name. Storing a name that already exists replaces the value and hosts.
Use PUT /api/v1/vault/interns/{internId}/secrets/{name} with the same body to store a secret for one intern directly. Names are 1 to 255 characters, start with a lowercase letter, and contain only lowercase letters, digits, and single underscores. A name cannot end with an underscore or contain __. github_token and db2_password are valid, GitHub-Token, _token, and a__b are not. Values are 1 to 65,536 characters. The whole request body must stay under 425,000 bytes or the request fails with 413. Hosts must be present with 1 to 100 entries. The rules are in Host rules. Unknown fields in the body fail the request with 400.

List secrets

Results are sorted by name. limit is 1 to 100 and defaults to 100. offset is 0 to 10,000 and defaults to 0. has_more is true when another page exists after this one, so keep adding limit to offset until it is false. A value outside those bounds fails with 400. Use GET /api/v1/vault/interns/{internId}/secrets with the same parameters to list one intern’s secrets. Both lists include secrets stored from the dashboard, or by OpenRouter when the intern was provisioned, before workspace-scoped storage. When a name exists both there and in a secret stored through this API, the list shows the one stored through this API, which is also the one the intern receives. Those older secrets can be read here but not deleted or copied; store the same name through this API to replace one.

See what an intern receives

An intern can receive a secret from three places: its own secrets, a vault attached to it, and the workspace. GET /api/v1/vault/interns/{internId}/effective-secrets lists, one entry per name, the secret the intern’s requests receive. It is computed by the same lookup the intern’s outbound requests use, so the two agree.
scope says where the entry comes from: intern, attached, or workspace. When more than one place holds a name, the intern’s own secret wins over the attached vault, and the attached vault wins over the workspace. The intern receives the listed secret only on requests to a hostname in its hosts, or on any request when hosts is null. A request to any other hostname receives nothing under that name, even when a lower scope holds a secret bound to that hostname. Paging works as in List secrets. The route returns 404 when the intern’s attached vault is no longer available. The intern receives no secrets until the vault is attached again or detached.

Copy workspace secrets to an intern

Copying is how you hand a workspace credential to an intern without sending the value again. Each copy keeps the source value and hosts, and replaces any intern secret with the same name.
names holds 1 to 100 distinct workspace secret names. A repeated name fails with 400. Every name must exist in the workspace, otherwise the request fails with 404 and nothing is copied. Conflicts. The request fails with 409 and the message Vault request conflicts with existing secrets when a named workspace secret has hosts: null, or when the intern is in the middle of a transfer to another workspace. Nothing is copied. For a null-host secret, store it again with hosts and retry. For a transfer, retry once the transfer has finished.

Delete a secret

A successful delete returns 204 with no body. Deleting a name that does not exist in that scope returns 404. Deleting a workspace secret does not touch copies already made to interns, and deleting an intern’s copy does not touch the workspace secret. Use DELETE /api/v1/vault/interns/{internId}/secrets/{name} to remove one intern’s secret.

Host rules

A host is an exact DNS hostname. The API normalizes each entry and then checks it.
  • Hostnames are lowercased and a trailing dot is removed, so API.Example.com. is stored as api.example.com.
  • Schemes, ports, paths, wildcards, and empty strings are rejected. https://api.example.com, api.example.com:443, api.example.com/v1, and *.example.com all fail with 400.
  • Each label is 1 to 63 characters of letters, digits, and hyphens, and cannot start or end with a hyphen. The whole hostname is at most 253 characters.
  • An array holds 1 to 100 hosts. Entries that are equal after normalization are collapsed into one.
Matching at release time is exact. A secret bound to api.example.com is never released to example.com, www.api.example.com, or any other hostname. Bind every hostname the intern needs to call.

Errors

Errors use the standard OpenRouter shape.

Writes are enabled per account

Inside the Intern API programme, writes (PUT, DELETE, and POST) are enabled per account during the Ori rollout. Until they are enabled for yours, every write returns 503 with the message Vault writes are not enabled, while GET requests keep working for accounts in the programme.