API and tokens
Every workspace has a REST API at its own address,
https://<workspace>.vulkro.com. The routes live under /api/v1/ (issues,
triage, orgs) and /api/core/ (code repositories, branches, quality gates
and scans).
The API reference
GET https://<workspace>.vulkro.com/api/v1/openapi.json
This public OpenAPI 3.1 document lists every /api/v1 and /api/core
route, with the access each one needs, the token scope a change needs
(x-vulkro-token-scope), its plan feature, and whether it is open to a
signed-in browser only. It is generated from the workspace's own route
table, so it always matches the routes your workspace serves.
Two kinds of token
Both are sent as a bearer token:
curl -H "Authorization: Bearer $VULKRO_TOKEN" \
"https://<workspace>.vulkro.com/api/v1/queue?view=open&severity=critical"
A token works on /api/v1/* and /api/core/* only. Workspace Settings,
members, roles and notification destinations are never open to a token.
Member tokens (vkws_...)
A member token comes from a device sign-in: vulkro-sf cloud connect (see
vulkro-sf cloud) shows a code, and the
member approves it in a signed-in browser.
- It acts as the member who approved it, with their role, rights and scope, checked on every request.
- It lasts 90 days, and stops working when it is revoked or the member leaves the workspace.
- On
/api/core/it reads only, unless it was issued with thecore:writescope. - Members see and revoke their tokens under My account > vulkro-sf connections.
Workspace API tokens (vkws_svc_...)
A workspace API token belongs to the workspace, not to a person, so CI and automation keep working when people leave. Owners and Maintainers create and revoke them in Workspace Settings > API Tokens, in a signed-in browser.
-
Scopes. Every token has
read. Add the others as needed:Scope Label Allows readRead Read issues, orgs, repositories, scans and quality gates. Every token has it. core:writeChange Code Repositories Connect and configure repositories and branches, change quality gates and start scans. triage:writeWork on Issues Change status, assign, comment and create Jira tickets. A false positive or an accepted risk still waits for a person's approval. There is no admin scope. A change without its scope is refused with 403
token_scope, naming the scope it needs. -
Which orgs and repositories. A token can be limited to a list of orgs and repositories, or see every one.
-
Expiry. 1 to 365 days, or no expiry, unless the workspace caps token lifetime (then an expiry is required).
-
Shown once. The token is shown when you create it and stored only as a SHA-256 hash.
-
Who it acts as. It acts as a service actor: the activity log, issue history and comments read
Service token <name>. It is not a member and takes no seat, so removing any member, including the one who created it, leaves it working. It stops when it is revoked or expires.
Workspace policy
In Workspace Settings > Sign-In & Security a workspace can:
- cap token lifetime below 90 days (this also applies to existing tokens),
- require an admin to approve each new device connection, and
- restrict access to an IP allowlist, which applies to tokens too.
Errors
Errors come back as {"error": "<what went wrong and what to do>", "code": "..."}.
The codes a token can get:
| Status | Code | Meaning |
|---|---|---|
| 401 | token_invalid, token_revoked, token_expired | The token is not valid any more. |
| 403 | token_scope | The route is not open to tokens, or the change needs a scope this token lacks. |
| 403 | token_pending_approval | The workspace requires an admin to approve this connection first. |
| 403 | ip_blocked | The request came from outside the workspace's IP allowlist. |
Example: CI
List open Critical issues, then mark one in progress (the token needs
triage:write for the second call):
curl -H "Authorization: Bearer $VULKRO_TOKEN" \
"https://<workspace>.vulkro.com/api/v1/queue?view=open&severity=critical"
curl -X POST -H "Authorization: Bearer $VULKRO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"state": "in_progress"}' \
"https://<workspace>.vulkro.com/api/v1/findings/<fingerprint>/triage"