Errors, pagination and limits
The error shape and codes, cursor pagination, rate limits and idempotency keys of the Outqube API.
Errors
Every error has the same shape. The request_id is also in the request-id response header. Quote it when you ask for help.
{ "error": { "code": "not_found", "message": "Run not found.", "request_id": "0f6c2b1e-8d3a-4a57-9a1c-7e5d2b4c8f90" } }| Status | Code | When |
|---|---|---|
| 400 | invalid_request | A query parameter, body or cursor is not valid. The message names the first problem. |
| 401 | unauthorized | The key is missing, unknown, revoked or expired, or the organisation is suspended. |
| 403 | forbidden | The key's scope is too low. |
| 404 | not_found | No such id or path, or it belongs to another app. |
| 405 | method_not_allowed | The path does not take that method. The Allow header lists the ones it does. |
| 409 | conflict | The state does not allow it, for example rerunning a live run, or a name that matches more than one suite or environment. |
| 422 | unprocessable | The request is valid but cannot be done. Also idempotency_mismatch, no_tests and invalid_base_url. |
| 429 | rate_limited | Too many requests. See Retry-After. |
| 500, 503 | internal, unavailable | Something failed on our side. Retry with backoff. |
Pagination
List endpoints take limit (1 to 100, default 20) and cursor, and answer { "data": [...], "next_cursor": "..." }. Pass next_cursor back as cursor for the next page. It is null on the last page. Treat cursors as opaque strings.
curl "https://app.outqube.com/api/v1/runs?status=completed&limit=50" \
-H "Authorization: Bearer $OUTQUBE_API_KEY"GET /runs also filters by outcome, source, branch, commit_sha, pr_number and created_after.
Rate limits
Each key may make 120 requests a minute by default, and each IP address has a higher limit of its own. Over the limit you get 429 with a Retry-After header in seconds. Wait that long, then continue. Polling a run every few seconds is well within the limit. A call to the MCP server counts as one request.
Idempotency
POST /runs and POST /runs/{runId}/rerun accept an Idempotency-Key header: 8 to 200 printable ASCII characters. Use something that names the trigger, such as the commit and job.
curl -X POST https://app.outqube.com/api/v1/runs \
-H "Authorization: Bearer $OUTQUBE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: deploy-4f1c2a9" \
-d '{ "suite": "smoke", "metadata": { "commit_sha": "4f1c2a9", "branch": "main" } }'- The same key with the same request, within 24 hours, returns the first response again and starts nothing new.
- The same key with a different request answers 422
idempotency_mismatch. - A duplicate sent while the first request is still running answers 409
conflict. Retry shortly. - Keys are per API key.
Next steps
- Core concepts: runs, statuses and results.
- Authentication: which scope an endpoint needs.
- API reference: every endpoint.