Conventions & errors
Requests
- Base URL:
https://YOUR-TESTVIBE-SERVER/api/v1/ops - Authentication:
Authorization: Bearer tvb_…on every request (details). - Bodies are JSON (
application/json); a malformed body is rejected with400 invalid_request. {project}in paths is the project's public id (a GUID, fromlist_projects).{feature}accepts a numeric id or the feature name (case-insensitive).
The cURL examples throughout the reference assume:
export TESTVIBE_SERVER=https://YOUR-TESTVIBE-SERVER
export TESTVIBE_API_KEY=tvb_XXXXXXXX…
export PROJECT=7f3c9a4e-2b1d-4e8a-9c6f-0d5b8a1e2f34
Responses
- JSON, with
camelCasekeys. - Timestamps are ISO-8601 UTC with a
Zsuffix:"2026-06-10T14:32:07Z". Fields that don't apply yet (e.g.finishedUtcon a running run) arenull. - Reads return
200. Creates return201. Dispatches (generate, run) return202with the id to poll. Mutations return200with{ "ok": true }.
Errors
Every error has the same shape:
{ "error": "conflict", "message": "This feature is already generating." }
| HTTP | error | When |
|---|---|---|
400 | invalid_request | Malformed JSON, missing required field, write-allowlist violation, file too large. |
401 | unauthorized | Missing, invalid, or revoked API key. |
404 | not_found | Unknown route, or no such project / feature / run in this workspace. |
409 | conflict | Lifecycle conflicts: feature already generating, not runnable yet, dispatch rejected. |
info
message is human-readable and safe to surface directly — the MCP server and CLI both pass it through verbatim.
Versioning
The API is versioned in the path (/api/v1/). Additive changes (new fields, new routes) happen within v1; breaking changes get a new version. See Roadmap & changelog.