Skip to content

Getting 401 Unauthorized

Symptom: a request to VectorStep — a webhook POST, a curl to the API, the UI itself — comes back 401 Unauthorized, even though you’re sure you’re sending a token. The two most common causes are: the wrong token for that specific route, or the wrong token for the job entirely (VectorStep ships three separately-purposed tokens whose names all start with VECTORSTEP_).

First: which token is this route asking for?

Section titled “First: which token is this route asking for?”

Every route needs a token from auth.tokens in config/vectorstep.yaml, and each configured token carries exactly one role:

Role Can do
webhook POST /webhook only — nothing else
viewer Read-only: browse the UI, list runs/pipelines, GET endpoints
operator Everything viewer can, plus Run now, rerun, replay, feedback, approvals
admin Everything operator can, plus editing pipelines/steps and POST /reload

The one genuinely surprising part: admin/operator/viewer form a hierarchy — an admin token can do anything a viewer token can — but webhook is not part of that ladder. POST /webhook accepts a webhook-role token only. An admin token, which can do literally everything else in the system, still 401s on /webhook — that’s not a bug, it’s the role boundary working as designed. If a webhook call is 401ing and you’re confident the token is valid, check its role first, not whether the token itself is right.

auth:
tokens:
- name: admin
token: ${VECTORSTEP_ADMIN_TOKEN}
role: admin
- name: webhook
token: ${VECTORSTEP_WEBHOOK_TOKEN}
role: webhook

Every tutorial in this docs series uses exactly this shape: $ADMIN_TOKEN for /reload and anything in the UI, $WEBHOOK_TOKEN for /webhook. If you’re getting 401s while following along, that pairing — right token for this specific call — is the first thing to check.

Second: are you reaching for the right token at all?

Section titled “Second: are you reaching for the right token at all?”

VectorStep’s default install seeds three environment variables that all start with VECTORSTEP_ and are easy to mix up, because they solve three unrelated problems:

Variable What it actually is
VECTORSTEP_ADMIN_TOKEN An auth.tokens entry — proves your identity to VectorStep. Used for /reload, editing pipelines, logging into the UI.
VECTORSTEP_WEBHOOK_TOKEN Also an auth.tokens entry — proves an external caller’s identity to VectorStep, for /webhook specifically.
VECTORSTEP_GATEWAY_TOKEN Not an auth.tokens entry at all. This is executors.gateway.token — the credential VectorStep itself presents outbound, to authenticate to the Gateway when running a step. It has nothing to do with who’s allowed to call VectorStep.

The first two authenticate incoming requests to VectorStep; the third authenticates an outgoing request VectorStep itself makes. A 401 from a step failing to reach the Gateway is a VECTORSTEP_GATEWAY_TOKEN problem (wrong value, or it doesn’t match what’s configured on the Gateway side — see Gateway authentication); a 401 on /webhook or /reload is an auth.tokens problem. If you’re not sure which one you’re looking at, check which service returned the 401 and which URL you called — VectorStep’s own routes want an auth.tokens value; a step failing mid-run wants the Gateway token.

If you’re not sure what’s actually configured

Section titled “If you’re not sure what’s actually configured”

auth.tokens lives in ~/.vectorstep/config/vectorstep.yaml, and every ${ENV_VAR} in it resolves from ~/.vectorstep/.env. Read both together — a token name existing in one file with no matching value in the other is a common cause, especially after copying a config from elsewhere.

MCP servers (Claude Code / Claude Desktop) need their own admin token

Section titled “MCP servers (Claude Code / Claude Desktop) need their own admin token”

If you’re getting 401s from the VectorStep Service MCP or Gateway MCP rather than from VectorStep directly, the same principle applies one level up: VECTORSTEP_TOKEN (Service MCP) and GATEWAY_OPERATOR_TOKEN (Gateway MCP) each need to be an admin-role credential from the respective service — a lower-role token will 401 on most of what these servers do, since authoring pipelines/steps/agents is inherently a write operation. See each server’s own Configuration section on the MCP servers page for exactly where that token comes from.

  • Service configuration reference — the full auth: block, including allow_unauthenticated for a trusted local machine.
  • Team attribution — the team field on a webhook-role token, for attributing spend/notifications per team.
  • MCP servers — token configuration for both standalone MCP servers.