POST /secrets stores a reusable hosted secret, such as a model API key or an environment variable a
task requires. This is the API equivalent of adding secrets through the Web UI.
The examples below use $BASE and $KEY. Get a key from
Harbor Hub API Key.
scope is user by default. Use job instead to scope a secret to a single job, which then
requires a job_id; job_id is rejected when the scope is user. You can pass an org_id to place
the secret in a specific organization, and an optional provider label of up to 64 characters.
The response returns metadata only, never the value:
Replacing a Secret
Storing a secret whoseenv_var already has an active secret does not silently overwrite it.
The request comes back as 409 replacement_required along with the record you are about to replace,
so you can see exactly what is being replaced:
"supersede_credential_id": "<existing.id>" to confirm. If that ID
no longer matches the active secret, because something changed in between, you get
409 replacement_stale instead and should re-read before retrying. Superseding
requires organization owner rights.
The same pattern applies to registry secrets below.
Listing and Revoking Secrets
GET /secrets lists your secrets as metadata only. Filter with scope, job_id, and status,
where status accepts active (the default), revoked, or all.
DELETE /secrets revokes a secret by environment variable name. Set purge to true only when the
stored record should be permanently deleted rather than marked revoked.
Checking Secrets Before Launching
POST /secrets/preflight is an advisory check that reports whether each agent in a config will
actually receive a credential its model can authenticate with. It never blocks a launch on its own.
secrets lists it and
it resolves, either to an active secret in the owning organization or to a name in
declared_env_vars. Send declared_env_vars for the one-off keys you plan to pass as
job_secrets, since preflight never sees their values.
The response reports an overall ok, per-provider results under providers, per-agent detail under
agent_requirements — each with its model, provider, missing_env_vars, and configured — and
task_requirements listing the environment variables the resolved tasks hard-require. The older
agents field is still returned for existing clients. A task requirement counts as met
only when the secret is configured and supplyable. Reserved infrastructure names — PATH,
LD_PRELOAD, anything starting with MODAL_, SUPABASE_, HOSTED_HARBOR_, or GCP_, and anything
ending in _PROXY — are never exported into a trial’s environment, so a task requiring one cannot be
satisfied by supplying your own key.
