The Vigilbase CLI reads your Vigilbase One account over HTTP, and scripts and integrations can call the same endpoints with an organisation API key. These pages describe those endpoints as they behave today: what each one needs, what it accepts and what it returns.
The API host is https://api.vigilbase.com/one/v1 for the v1 operations: customers, contracts, billing, monitoring, reports, support, Cloudflare, change requests and tool runs. Everything else is still on One's own host, under https://one.vigilbase.com/api. See hosts.
Hosts
| Host | What it serves | Errors | Lists |
|---|---|---|---|
https://api.vigilbase.com/one/v1 | The v1 operations in the API reference | Problem details | Cursor pages |
https://one.vigilbase.com/api | Every operation not in v1 yet, and the deprecated older paths of the v1 operations | One's older shapes | Per endpoint |
Each v1 operation also answers at an older path on one.vigilbase.com, for example GET https://one.vigilbase.com/api/customers for GET https://api.vigilbase.com/one/v1/customers. These older paths are deprecated aliases. For now they still answer, with the same tokens and API keys and their older response and error shapes, and each response carries a Deprecation header and a successor-version Link to the v1 operation. They will be retired: a Sunset header announces the date first, and from then on token and API key calls get 410 Gone. The session-cookie calls from One's own pages aren't affected. The older paths are never redirected. Each reference page names the older path of its operation. New scripts must use the v1 host.
curl https://api.vigilbase.com/one/v1/customers \
--header "Authorization: Bearer $VIGILBASE_TOKEN"
The area pages below describe each operation by its v1 path where it has one, and by its /api path on one.vigilbase.com otherwise. The API reference documents every operation with its fields and response shapes. The v1 operations are also an OpenAPI 3.1 document at https://api.vigilbase.com/one/v1/openapi.json, which needs no sign-in.
Areas
Sign in and send the token
One accepts two kinds of credential, both sent as a bearer token: an access token from Vigilbase Identity at auth.vigilbase.com, which acts as you, or an organisation API key, which acts for your organisation with a role an owner or admin chose. We recommend signing in (OAuth) wherever a person can, and keeping keys for jobs nothing can sign in to. For an access token:
Authorization: Bearer <access_token>
The CLI gets this token for you:
Run
vigilbase login. The CLI starts a device sign-in with Vigilbase Identity and openshttps://auth.vigilbase.com/device.Approve the device. On Confirm CLI access, choose the organisation the sign-in is for and click Approve device.
Use the CLI. It saves the sign-in, sends the token on every One request and renews it before it expires.
An access token lasts at most five minutes. The CLI renews it with the refresh token it saved at sign-in, and retries a request once with a new token when One answers 401. See Install and sign in for where the sign-in is stored.
To try requests without a terminal, use Try it on the API reference pages: Sign in with Vigilbase there gives the page a token for the organisation you choose, and the page sends each request to the host its operation is on. The page renews it while the tab is open, never saves it, and can't send changes that need a recent sign-in. Use an API key instead sends a key you paste; the page keeps it in memory only and forgets it when you close the tab.
One accepts tokens only from Vigilbase's own apps, such as the CLI and the docs, with the one:api scope and One as the audience. One has two audiences, https://api.vigilbase.com/one and the older https://one.vigilbase.com, and a token names one of them. One accepts either on both hosts. You can't register your own OAuth application for One: for your own scripts, sign in with the CLI when a person runs them, and use an organisation API key only for jobs that run unattended. Developer API keys (vb_dev_…) are for the Agent API on vigilbase.com and don't work on One.
GET https://api.vigilbase.com/.well-known/oauth-protected-resource/one describes this setup for the v1 host: it names https://api.vigilbase.com/one as the resource, https://auth.vigilbase.com as the authorization server and one:api as the scope. GET https://one.vigilbase.com/.well-known/oauth-protected-resource describes the older resource the same way.
Organisation API keys
An organisation API key lets a script, a scheduled job or another system call these endpoints without a person signing in. Keys work on both hosts, api.vigilbase.com/one/v1 and one.vigilbase.com/api, with the same access on each. Keys start with vb_one_ and are sent like a token:
Authorization: Bearer vb_one_<key>
Sign in instead where you can. A key is a long-lived secret: anyone who copies it can use it until it expires or is revoked. When a person runs the requests, use vigilbase login or Sign in with Vigilbase on the reference pages instead. Those sign-ins use OAuth, act as that person, and their tokens last minutes. Use a key only for scheduled jobs and integrations that run without a person.
Open API keys. In Vigilbase One, go to Settings, then API keys. Only owners and admins see it.
Create a key. Click Create API key, give it a name, and choose its role, its access and when it expires. Creating a key needs a recent sign-in, so One may ask you to confirm it's you.
Copy the key. One shows the full key once. Store it in your secrets manager; One keeps only a fingerprint and can't show it again.
curl https://api.vigilbase.com/one/v1/customers \
--header "Authorization: Bearer $VIGILBASE_API_KEY"
What a key can do:
- One organisation. A key belongs to the organisation it was created in and only ever acts there.
- A role you choose. A key's permissions are the defaults of its role, checked on every request, like a member's. You can't give a key a role above your own, and only owners can create owner keys.
- Read-only unless you choose otherwise. A read-only key can send
GETandHEADrequests only; anything else gets403with the coderead_only_key. Choose Read and write when the key has to make changes its role allows. - An expiry. Every key expires, after 30, 90 (the default), 180 or 365 days. No key lasts longer than a year: create a new key and switch to it before the old one expires.
Keys can't call every endpoint. One refuses a key, with 403 and a code, when an endpoint does one of the following. On the v1 host, the refusal is a problem, and not_in_catalog and api_key_inactive arrive as forbidden with the reason in detail, and unsupported_content_type as 415 with unsupported_media_type.
| Code | Why |
|---|---|
step_up_required | It needs a recent sign-in. Only a person can sign in. |
not_for_api_keys | It acts for a signed-in person rather than the organisation, such as your own organisation list, your training record, Vigil conversations or signing an agreement, or it changes single sign-on. |
unsupported_content_type | It takes a file upload. |
staff_only | It's for Vigilbase staff. |
not_in_catalog | It isn't in the API reference, such as managing API keys themselves. |
Each endpoint page in the reference says whether a key can call it, and whether the key needs write access.
A key stops working, with 401 and a code, when it's revoked (api_key_revoked), when it expires (api_key_expired), or when it's inactive (api_key_inactive): its organisation is suspended or offboarded, or the person who created it has left the organisation, been banned or no longer holds the key's role. A key that leaves with its creator can't be revived: an owner or admin creates a new one. An unknown key gets invalid_api_key.
The API keys page lists every key with its role, access, creator, when it was last used (updated at most every five minutes) and whether it still works. Revoke stops a key on its next request. Creating and revoking keys and every change a key makes are recorded in the audit log, as are requests One refuses because a key is read-only, revoked, expired or inactive. Changes a key makes are recorded against the person who created it, with the key named, and the key's creator is shown in the list.
Each key can send 120 requests a minute, on top of the per-address rate limits; over that, One answers 429 with the code rate_limited (rate_limit_exceeded on the v1 host) and Retry-After: 60.
Your organisation and permissions
A token belongs to one organisation: the one you chose when you approved the sign-in. Every request acts as you in that organisation. To work in another organisation, run vigilbase login again and choose it. An organisation API key acts in its own organisation with its own role instead.
What a request can read follows your role in that organisation, checked on every request, so a role change applies straight away. See Members and roles. If your organisation has set custom permissions for you, those apply instead; owners always have the full owner set.
Each endpoint page names the permission it needs. A refusal names it too, for example Permission denied: requires one of read:services. The permissions these endpoints use, by role:
| Permission | Owner | Admin | Member | Read Only | Billing Only |
|---|---|---|---|---|---|
read:customers | Yes | Yes | Yes | Yes | No |
read:services | Yes | Yes | Yes | Yes | No |
write:services | Yes | Yes | No | No | No |
read:billing | Yes | Yes | Yes | Yes | Yes |
write:billing | Yes | Yes | No | No | No |
read:contracts | Yes | Yes | Yes | Yes | No |
read:organizations | Yes | Yes | Yes | Yes | Yes |
manage:organizations | Yes | Yes | No | No | No |
read:monitoring | Yes | Yes | Yes | Yes | No |
read:partner_customers | Yes | Yes | Yes | No | No |
read:partner_monitoring | Yes | Yes | Yes | No | No |
support:access | Yes | Yes | No | Yes | No |
Partner organisations also have partner roles with their own sets of permissions.
Many endpoints work on your organisation's own customer record and take no customer ID. Endpoints that do take one, in the path or as customerId, accept your own customer's ID, and for a partner organisation, the IDs of the customers it manages where the page says so. GET/api/account returns your customer ID as customer.id, and GET/customers on the v1 host lists the customers you can read.
Changes that need a recent sign-in
Requests that change billing or services, such as opening the billing portal or starting a Cloudflare Checkup, need a sign-in from the last 10 minutes. Renewing the token doesn't count as signing in. An older sign-in gets 401:
{
"error": "Fresh Identity authentication required",
"reauthenticate": "/api/oidc/login?prompt=login&max_age=0",
"isEffectStarted": false
}
Nothing has changed when you get this answer. Run vigilbase login again, then retry. Reads never need a recent sign-in.
The docs' Try it panel and organisation API keys can't send these changes: neither is ever treated as a recent sign-in, and One answers 403 with the code step_up_required instead. Use the CLI or cURL with a fresh sign-in for them.
Rate limits
One counts requests per client IP address in fixed one-minute windows, by group of paths:
| Paths | Requests per minute per IP |
|---|---|
/api/auth/orgs/… | 20 |
Other /api/auth/… paths | 60 |
Every other /api/… path in these pages | 200 |
Each organisation API key also allows 120 requests a minute, and support tickets have their own limits per organisation and per person.
The v1 host counts requests the same way, against the same per-IP limit. Over it, the v1 host answers a 429 problem with the code rate_limit_exceeded and Retry-After (seconds). If One can't check the limit, it answers a 503 problem with service_unavailable and Retry-After: 5.
On one.vigilbase.com, over a limit, One answers 429 with Retry-After (seconds), X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (an ISO 8601 time):
{ "error": "Rate limit exceeded", "retryAfter": 42 }
These headers appear only on the refusal, not on successful responses. If One can't check the limit, it answers 503 with {"error":"Service temporarily unavailable","retryAfter":5} and Retry-After: 5. The CLI exits with code 2 on a 429 and doesn't retry on its own.
Responses and errors
On the v1 host, a successful response is the declared JSON object itself, with no success or data wrapper. Each reference page shows the object's fields. Every response carries X-Request-Id, and successful ones also API-Version: 1. To trace a request, send your own X-Request-Id: 8 to 128 letters, digits, - and _, starting with a letter or digit. One uses it when it's well-formed and makes a new one otherwise.
Pagination
v1 operations that list things are cursor-paginated. They take two query parameters:
| Parameter | Description |
|---|---|
limit | 1 to 200; default 50 |
cursor | The nextCursor of the previous page. Leave it out for the first page |
The response is { "items": [ … ], "nextCursor": "…" }. While nextCursor is present there are more items: send it back as cursor, with the same other parameters, to get the next page. The last page has no nextCursor. A cursor is opaque and belongs to the organisation and filters it was made for; don't build or change one.
{
"items": [{ "id": "…", "name": "…" }],
"nextCursor": "eyJ…"
}
Errors
Every v1 error is a problem details object (RFC 9457) with Content-Type: application/problem+json:
{
"type": "about:blank",
"title": "Forbidden",
"status": 403,
"detail": "Permission denied: requires one of read:services",
"code": "forbidden",
"requestId": "6f1c…",
"docs": "https://docs.vigilbase.com/one/api"
}
Rely on status and code, which are stable snake_case names such as validation_failed, unauthorized, forbidden, read_only_key, not_found and rate_limit_exceeded. Each reference page lists the codes of each status. detail is for people and its wording isn't fixed. A 400 with validation_failed lists each invalid field in errors, as pointer and message. Quote requestId when you contact support. Writes also take an Idempotency-Key header (1 to 255 characters); One checks its format but doesn't replay earlier answers yet, so check before you retry a write that may have gone through.
Older error shapes
The /api paths on one.vigilbase.com don't use application/problem+json, and their body depends on the endpoint. You'll see one of these shapes:
{ "error": "Authentication required" }
{ "error": "Forbidden", "message": "Permission denied: requires one of read:services", "statusCode": 403 }
{ "success": false, "error": "Tool run not found" }
The first is One's answer to a request with no token. The second comes from the shared permission check and from most account endpoints. For any 5xx in that shape, the body is always {"error":"Internal Server Error","message":"Internal server error","statusCode":…}. The third is used by tool runs, Cloudflare Checkups, support and Stripe reads; a few add a code, such as browser_session_required or scan_unassessed.
Rely on the status code, and on code where an endpoint documents one. The wording of messages isn't fixed.
The status codes mean the same on both hosts:
| Status | Meaning |
|---|---|
400 | A missing or invalid parameter or body, or a customer ID the endpoint needs |
401 | No token, or an invalid, expired or revoked token or API key; or a change that needs a recent sign-in |
403 | Your role (or the key's) lacks the permission, the customer, account or zone isn't yours, or an API key can't call the endpoint |
404 | The record doesn't exist or isn't visible to you |
409 | The change isn't possible right now, for example while your customer record is changing |
422 | A scan ran but failed or couldn't assess the target |
429 | A rate limit is used up |
500 | Something went wrong in One |
503 | A service One depends on is unavailable; retry later |
The CLI prints its own short messages for these, not One's text. See Troubleshooting.