Concepts

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" } }
StatusCodeWhen
400invalid_requestA query parameter, body or cursor is not valid. The message names the first problem.
401unauthorizedThe key is missing, unknown, revoked or expired, or the organisation is suspended.
403forbiddenThe key's scope is too low.
404not_foundNo such id or path, or it belongs to another app.
405method_not_allowedThe path does not take that method. The Allow header lists the ones it does.
409conflictThe state does not allow it, for example rerunning a live run, or a name that matches more than one suite or environment.
422unprocessableThe request is valid but cannot be done. Also idempotency_mismatch, no_tests and invalid_base_url.
429rate_limitedToo many requests. See Retry-After.
500, 503internal, unavailableSomething 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

On this page