API and Tokens
The VoxelBench API lets a script or an agent read your reports, servers, monitoring and auto-bench runs, and make the everyday changes an owner makes. This page explains how to create a token, what each plan allows, what can and cannot be written, and what the errors mean.
What the API Is For
The API answers at https://voxelbench.com/api/v1/… in JSON. Typical uses:
- follow your servers' reports and monitoring from a script or your own dashboard;
- launch an auto-bench run from a deployment pipeline, then read its result;
- give an AI agent access to your account (for Claude, see Connect Claude to Your Account).
Public reports and the hosting offers catalogue can be read without a token. Everything else needs one:
curl -H "Authorization: Bearer vb_…" "https://voxelbench.com/api/v1/reports?mine=true&limit=10"
A token never sees more than your account does. What it may do is recomputed on every request: the scopes it carries, limited to what your account may do today. If your plan lapses, access follows within the second, with nothing to revoke.
Creating a Token
Open Settings (Profile & settings in the dashboard menu), tab Security, card API tokens:
- Give the token a Name (up to 80 characters), so you know later what uses it.
- Set Expires in (days): from 1 to 365, 90 by default.
- Tick at least one scope, then click Create.
- Copy the token at once. It starts with
vb_and is shown only once: VoxelBench keeps only its fingerprint. A lost token cannot be recovered; revoke it and create another.
Tokens can only be created from a signed-in browser: a token can never create another one. The same card lists your tokens with their scopes and last use, shows how many API calls you made today, and has a Revoke button on each row.
Scopes
Tick only the scopes you need: a token saved in a configuration file should not be able to do anything you did not intend.
| Scope | What it opens |
|---|---|
reports:read | Benchmark reports, their diagnosis, comparisons, tuning advice and before/after verdicts |
unit-tests:read | Single-test results |
servers:read | Your linked servers, your server groups, and whether a server's performance has dropped |
auto-bench:read | Your auto-bench targets and their runs |
monitoring:read | Everything the monitoring of your servers records: live status, metric series, events, the overview of all your servers, performance profiles and memory reports with their comparisons, maintenance windows, alert rules and alerts |
offers:read | The hosting offers catalogue |
servers:write | Rename a server, change its visibility, manage groups and sort servers into them |
servers:link | Link a new server with the 8-character code the plugin prints |
reports:write | Change a report's visibility, description and private notes |
monitoring:write | Create, edit and pause alert rules, send a test notification, acknowledge alerts, start and end maintenance |
auto-bench:write | Launch, cancel and reschedule runs on targets you already have |
auto-bench:write and monitoring:write can be ticked on any plan. The screen marks them pro when your plan does not include auto-bench or monitoring: the token is created, but those calls answer plan_required until the plan changes.
How Many Tokens
| Plan | Active tokens |
|---|---|
| Free | 1 |
| Pro | 5 |
| Hosting provider | 10 |
| Enterprise | 20 |
A connector you authorized for Claude or another MCP client counts as one token. The limit is checked when you create a token and again on every call: if your plan lapses, only your most recent tokens up to the new limit keep working, and the others answer token_quota_exceeded. Listing and revoking tokens always works, on every plan.
Quotas
Every response says how much is left, with X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; X-RateLimit-Window tells which of the two limits below is the closer one (day or hour).
Daily Calls
| Plan | API calls per day |
|---|---|
| Free, and callers without a token | 10 |
| Pro | 50 |
| Hosting provider | 150 |
| Enterprise | 500 |
- The quota belongs to the account: all its tokens and connectors share it. Five tokens do not buy five quotas.
- Reads and writes both count.
- Without a token, the quota applies per IP address.
- Browsing voxelbench.com while signed in does not count: only calls made with a token do.
- The day is a 24-hour window that starts with your first counted call; the refusal says when it ends.
GET /api/v1/token, which tells what the calling token may do, does not count.
Hourly Limit
Each token may also make up to 600 calls per hour. Past that, the API answers rate_limited with a Retry-After header.
Auto-bench Runs
Launching runs has its own quota, counted over the last 24 hours:
| Plan | Runs per 24 hours |
|---|---|
| Free | 0 |
| Pro | 10 |
| Hosting provider | 30 |
| Enterprise | 100 |
Each run of a target counts (a target with 3 runs per job counts 3), scheduled runs included. See Auto-bench on the Website.
What You Can Read
Lists answer { data, page: { cursor, has_more } }. Send page.cursor back as ?cursor= to get the next page, unchanged; limit sets the page size, 25 by default and 100 at most.
| Scope | Endpoints |
|---|---|
reports:read | GET /api/v1/reports, /reports/{id}, /reports/{id}/diagnosis, /reports/{id}/tuning, /reports/compare, /reports/before-after |
unit-tests:read | GET /api/v1/unit-tests, /unit-tests/{id} |
servers:read | GET /api/v1/servers, /server-groups, /servers/{id}/regression |
auto-bench:read | GET /api/v1/auto-bench/targets, /auto-bench/jobs |
monitoring:read | GET /api/v1/monitoring/overview, /servers/{id}/status, /servers/{id}/metrics, /servers/{id}/events, /servers/{id}/alert-rules, /servers/{id}/event-alert-rules, /alert-events, /servers/{id}/maintenance, and the profiles and memory reports of your servers |
offers:read | GET /api/v1/offers |
The reports, unit tests and offers endpoints also answer without a token, with public content only: a list gives public and certified reports, and an unlisted report opens only when you name it by its id. With a token, a list adds your own reports and those of your verified linked servers, whatever their visibility, and ?mine=true keeps only yours; another account's unlisted reports appear in no list. A private report or a unit test opens for its author, for whoever holds its server once verified, and for administrators; for anyone else it is not_found.
A server's metrics and events need a plan that includes monitoring, and the period you ask for must fit in what your plan lets you view (otherwise retention_exceeded).
What You Can Write
Each write has its own scope, and each route accepts a fixed list of fields.
| Action | Endpoint | Scope | Fields |
|---|---|---|---|
| Rename a server, change its visibility | PATCH /api/v1/servers/{id} | servers:write | name, is_public, show_address_on_report, notify_on_report |
| Create a group | POST /api/v1/server-groups | servers:write | name, color |
| Rename, recolour or reorder a group | PATCH /api/v1/server-groups/{id} | servers:write | name, color, sort_order |
| Sort a server into a group | PUT /api/v1/servers/{id}/group | servers:write | group_id |
| Link a new server | POST /api/v1/servers/link | servers:link | code, name |
| Edit a report | PATCH /api/v1/reports/{id} | reports:write | visibility, description, private_notes |
| Create an alert rule | POST /api/v1/servers/{id}/alert-rules | monitoring:write | name, metric, condition, threshold, duration_minutes, cooldown_minutes, notify_email, notify_discord, notify_in_app |
| Edit, pause or mute an alert rule | PATCH /api/v1/alert-rules/{id} | monitoring:write | The same, plus enabled and mute_minutes |
| Send a test notification | POST /api/v1/alert-rules/{id}/test | monitoring:write | — |
| Acknowledge an alert | POST /api/v1/alert-events/{id}/acknowledge | monitoring:write | — |
| Start or extend maintenance | POST /api/v1/servers/{id}/maintenance | monitoring:write | duration_minutes, reason |
| End maintenance | POST /api/v1/servers/{id}/maintenance/end | monitoring:write | — |
| Launch a run | POST /api/v1/auto-bench/targets/{id}/run-now | auto-bench:write | — |
| Ask a run to stop | POST /api/v1/auto-bench/jobs/{id}/cancel | auto-bench:write | — |
| Reschedule a target | PATCH /api/v1/auto-bench/targets/{id} | auto-bench:write | enabled, schedule_cron, name, notes |
A field that a route does not accept is refused with field_not_allowed, which names the field and lists the accepted ones: it is never silently ignored. The rules are the dashboard's own: the API cannot do what the dashboard would refuse. For instance, only a report's author may change its visibility or private_notes (not the holder of its verified server), and making a report public or unlisted needs a verified email address.
Linking needs the code the plugin prints with /bench link: that code is the proof that you have access to the server, so a token can only link a server whose code it was given. A server already linked to your account answers already_linked: linking it again is done from the dashboard, and removes its verification. Only one run can be in flight per target: launching again answers already_running with the id of the run in progress, so replaying a launch is harmless. A stop is a request: the answer means "asked", and the run ends shortly after.
What Stays in Your Hands
Some actions are closed to tokens on purpose, and remain in the dashboard:
- every deletion (report, group, alert rule, auto-bench target);
- unlinking a server, or linking again a server that is already linked;
- creating an auto-bench target, because it engages a Microsoft account you lend;
- notification email addresses, Discord webhooks and webhooks, because they decide where your data goes;
- tokens, billing and the account itself.
Errors
Errors answer { error, message }, sometimes with details.
| Status | error | Meaning, and what to do |
|---|---|---|
| 400 | field_not_allowed | The body has a field this route does not accept; allowed_fields lists those it does |
| 400 | invalid_json, invalid_body, validation_error, invalid_cursor | The request itself is malformed; send the cursor back exactly as received |
| 401 | unauthorized | This endpoint needs a token |
| 401 | invalid_token, token_revoked, token_expired | The token is unknown, revoked or expired: create a new one |
| 403 | missing_scope | The token lacks the scope named in required_scope: create a token with it |
| 403 | plan_required | Your plan does not include the feature (auto-bench, monitoring): change the plan, not the token |
| 403 | token_quota_exceeded | Your plan no longer covers this token: revoke an older one or use a newer one |
| 403 | retention_exceeded | The period you asked for goes past what your plan lets you view |
| 404 | not_found | The resource does not exist, or you may not see it: the API never says which |
| 409 | already_running, already_linked, internal_target | A run is already in flight (job_id names it); the server is already linked to your account; the target is run by VoxelBench itself |
| 429 | daily_quota_exceeded | The account's daily quota is spent; the message says when it resets |
| 429 | rate_limited | The token's hourly limit is reached; wait for Retry-After |
| 429 | daily_run_quota_exceeded, cooldown | No auto-bench run left in the last 24 hours; or wait 60 seconds between two launches of the same target |
404 rather than 403. A resource you may not read answers exactly as if it did not exist: a 403 would confirm that it exists, and anyone could probe for other people's reports or servers. A 404 therefore means "not found, or not yours", never simply "wrong id".
missing_scope or plan_required? The scope says what a token may attempt; the plan says what the account may do. They are checked separately, so the refusal names the real cause.
Reference
- API reference: every endpoint, grouped by scope, with its parameters and whether it needs a token. It is generated from the list the server enforces, so it cannot describe an endpoint that does not exist.
- OpenAPI document: the same list in OpenAPI 3.1, to generate a client.
- Connect an agent: the MCP connector for Claude and other agents, over the same API.