Conventions & errors
Requests
- Base URL:
https://testvibe.app/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://testvibe.app
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. Other mutation responses vary by operation: some return{ "ok": true }, some the updated object, and load deletion returns{ "deleted": true, "featureId": … }.
Errors
Structured operation errors include an error code and a human-readable message:
{ "error": "conflict", "message": "This feature is already generating." }
| HTTP | Common code | Meaning |
|---|---|---|
| 400 | invalid_request, invalid_model | Malformed input, invalid file path, unsupported model id, or an operation-specific validation error. |
| 401 | unauthorized | Missing, invalid, revoked, or expired key, or its creator is no longer a member. |
| 402 | insufficient_credits | A credit-gated operation cannot reserve enough credits. Some run/generation dispatch refusals use 409 instead. |
| 403 | plan_forbidden | The cloud plan does not include API/CLI/MCP access. |
| 404 | not_found | Unknown route or resource outside this workspace/project. |
| 409 | conflict | Lifecycle or dispatch refusal. Specific routes can return confirmation_required, resume_unavailable, or secrets_unavailable. |
| 429 | rate_limited | Request budget exhausted; honor Retry-After. |
| 502 | provider_error | Non-retryable model-provider failure. |
| 503 | entitlement_unavailable, model_overloaded, capacity_unavailable | Retryable admission/provider/capacity problem; honor Retry-After. |
| 507 | storage_quota_exceeded | Storage quota prevents a new dispatch. |
This is a list of common codes, not a closed enum. Some errors include retryable and retryAfterSeconds. A capacity refusal explicitly reports creditsCharged: false. Do not turn a monitoring/network error into a failed-test verdict.
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.
Retrying a dispatch
For POST dispatches, send a unique Idempotency-Key (8–255 characters) and reuse it only when retrying the same method, route, and exact request body. Successful responses are replayed for 24 hours within the workspace, with Idempotent-Replay: true. A different request under the same key is a conflict. Failed dispatches are not stored as successful results.
This applies to generation, feature/load/automation/coverage run dispatches, suite runs, verify-change, and coverage scans. Other POST routes ignore the header and report Idempotency-Ignored: true. This is not a guarantee for arbitrary writes or every endpoint.