# Vigilbase One API > Calling the Vigilbase One API on api.vigilbase.com/one/v1 and one.vigilbase.com/api, with sign-in, API keys, pagination, rate limits and errors. Source: https://docs.vigilbase.com/one/api The Vigilbase CLI reads your Vigilbase One account over HTTP, and scripts and integrations can call the same endpoints with an [organisation API key](#organisation-api-keys). 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). > [!NOTE] > The v1 operations are versioned: the major version is in the path, and a breaking change gets a new version rather than changing `v1`. The `/api` paths on one.vigilbase.com aren't versioned. They're the endpoints One's own pages use, and they change with One. To script against One, use the v1 operations, or the [CLI](https://docs.vigilbase.com/tools/cli/install-and-sign-in) with `--json`. ## Hosts | Host | What it serves | Errors | Lists | | --- | --- | --- | --- | | `https://api.vigilbase.com/one/v1` | The v1 operations in the [API reference](https://docs.vigilbase.com/one/api/reference) | [Problem details](#errors) | [Cursor pages](#pagination) | | `https://one.vigilbase.com/api` | Every operation not in v1 yet, and the deprecated older paths of the v1 operations | [One's older shapes](#older-error-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. ```bash 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](https://docs.vigilbase.com/one/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 :::cards - [Account and billing](https://docs.vigilbase.com/one/api/account-and-billing) Your account, services, endpoints, billing summary and the Stripe billing portal. - [Organisations](https://docs.vigilbase.com/one/api/organizations) The organisations you belong to, their members and assignable roles. - [Tool runs](https://docs.vigilbase.com/one/api/tool-runs) Your organisation's scan history, and running a scan through One. - [Cloudflare](https://docs.vigilbase.com/one/api/cloudflare) Zones, DNS, WAF, audit logs, analytics and the Cloudflare Checkup. - [Watchdog and monitoring](https://docs.vigilbase.com/one/api/watchdog-and-monitoring) Watchdog targets, scans, uptime status and history. - [Customers](https://docs.vigilbase.com/one/api/customers) Customer records, contracts, invoices and subscriptions, for your own organisation or a partner's customers. - [Support](https://docs.vigilbase.com/one/api/support) Your organisation's support tickets: list, open and reply. - [API reference](https://docs.vigilbase.com/one/api/reference) Every customer endpoint: the v1 operations from One's API contract, and the operations not in v1 yet from One's API catalog. ::: ## 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](#organisation-api-keys), 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: ```http Authorization: Bearer ``` The CLI gets this token for you: :::steps 1. **Run `vigilbase login`.** The CLI starts a device sign-in with Vigilbase Identity and opens `https://auth.vigilbase.com/device`. 2. **Approve the device.** On **Confirm CLI access**, choose the organisation the sign-in is for and click **Approve device**. 3. **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](https://docs.vigilbase.com/tools/cli/install-and-sign-in) for where the sign-in is stored. To try requests without a terminal, use **Try it** on the [API reference](https://docs.vigilbase.com/one/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: ```http Authorization: Bearer vb_one_ ``` **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`](#sign-in-and-send-the-token) 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. :::steps 1. **Open API keys.** In Vigilbase One, go to **Settings**, then **API keys**. Only owners and admins see it. 2. **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. 3. **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. ::: ```bash 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 `GET` and `HEAD` requests only; anything else gets `403` with the code `read_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](#errors), 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](#changes-that-need-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](https://docs.vigilbase.com/one/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](#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](#organisation-api-keys) 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](https://docs.vigilbase.com/one/getting-started/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`: ```json { "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](#organisation-api-keys) also allows 120 requests a minute, and [support tickets](https://docs.vigilbase.com/one/api/support) 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](#errors) 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): ```json { "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. ```json { "items": [{ "id": "…", "name": "…" }], "nextCursor": "eyJ…" } ``` ### Errors Every v1 error is a problem details object (RFC 9457) with `Content-Type: application/problem+json`: ```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: ```json { "error": "Authentication required" } ``` ```json { "error": "Forbidden", "message": "Permission denied: requires one of read:services", "statusCode": 403 } ``` ```json { "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](https://docs.vigilbase.com/tools/cli/troubleshooting).