API Reference
The routes of the public API at /api/v1, with the scope each one needs, its parameters, request fields, responses and error codes. Generated from the API’s own OpenAPI document.
Result upload opens in a following release; keys can be created now. Until it opens,
POST /api/v1/ingest/resultsanswers503 INGEST_NOT_AVAILABLEwithRetry-After, after the key and its scope have been checked. When it is open, an accepted upload is recorded (202with aningest_id); turning its results into a test run arrives later.
Overview
The public, versioned API of TestOrchestrator. Authenticate with a workspace service key (Authorization: Bearer <key>); the key decides the workspace, so never send X-Tenant-Workspace. Each operation states the scope it needs (x-required-scope).
Projects are named by their public id (prj_ + 12 characters), never by a numeric id.
Errors share one shape: {errorCode, message, status, details, path, timestamp}.
Lists are cursor-paged: {data, next_cursor}; pass next_cursor back as ?cursor= until it is null. ?limit= sets the page size (1-100, default 50).
- Base URL:
https://api.testorchestrator.com - Document: OpenAPI 3.1.0, API version 1.0.0, served without a key at
GET /api/v1/openapi.json. This page is generated from a copy of it.
Authentication
serviceKey — HTTP bearer. A workspace service key (to_svc_...), sent as Authorization: Bearer <key>. Created by a Tenant Admin in Personal > API keys > Workspace service keys. Personal keys (MCP) are refused on this API. Keys and scopes are explained in API keys.
Routes
| Route | Scope | Summary |
|---|---|---|
POST /api/v1/ingest/results | ingest:results | Upload automated test results |
GET /api/v1/openapi.json | none | This document |
GET /api/v1/projects | read | List projects |
POST /api/v1/ingest/results
Upload automated test results. Send one results file (JUnit XML, Playwright JSON or TestOrchestrator JSON) as multipart/form-data. A project key needs no project parameter; an all-projects key passes project=prj_... Same Idempotency-Key within 24 hours returns the first response and writes nothing twice. Rate limit per key: a token bucket of 60 that refills at 1 per second (a burst of up to 60, so up to about 120 uploads in the first minute and 60 a minute after that); over it, 429 with Retry-After.
- Scope:
ingest:results(x-required-scope) - Authentication:
Authorization: Bearer <service key> - Operation id:
ingestResults
Parameters
| Name | In | Description |
|---|---|---|
Idempotency-Key | header · string | 1-255 visible ASCII characters, e.g. <ci run id>-<attempt>-<shard>. |
Request body
multipart/form-data, required — IngestResultsForm. multipart/form-data fields of an upload.
| Field | Type | Description |
|---|---|---|
file | string (binary) · required | The results file. Up to 25 MB; may be empty for a final complete=true call. |
format | string · required | File format. — one of junit-xml, playwright-json, to-results-json |
project | string | Only with an all-projects key: the project's public id. A project key may omit it; if sent it must be that key's own project. — pattern ^prj_[0-9a-hjkmnp-tv-z]{12}$; e.g. prj_8kd2hq0vxc1a |
run_key | string | Your stable id for the logical run (e.g. the CI run id). Uploads with the same key append to the same run. — up to 200 characters; e.g. gha-9876543210 |
run_name | string | Run name. Defaults to CI · <branch> · #<job>. — up to 255 characters |
environment | string | An Environment name or id for the whole upload. — up to 120 characters |
complete | string | true closes the run after this upload. — one of true, false |
tags | string | Comma-separated names of Automation tags. — up to 1000 characters; e.g. e2e,team-core |
ci_branch | string | CI fact: branch. — up to 255 characters; e.g. main |
ci_commit | string | CI fact: commit SHA. — up to 64 characters; e.g. 4f2c9a1 |
ci_actor | string | CI fact: who triggered the job. — up to 255 characters |
ci_job_url | string (uri) | CI fact: link to the job (http or https). — up to 2048 characters |
ci_provider | string | CI fact: provider (github, gitlab, circleci...). — up to 64 characters; e.g. github |
ci_build_number | string | CI fact: build or pipeline number. — up to 64 characters; e.g. 512 |
Responses
| Status | Meaning | Body |
|---|---|---|
202 | Accepted and recorded. A replay of an earlier Idempotency-Key carries the header Idempotent-Replay: true. | IngestAccepted |
400 |
| Error |
401 | API_KEY_UNAUTHORIZED: A valid workspace service key is required. | Error |
403 |
| Error |
413 | FILE_TOO_LARGE: The results file is over 25 MB. Split it by shard or drop stdout from the report. | Error |
422 | IDEMPOTENCY_KEY_REUSED: This Idempotency-Key was already used for a different upload. | Error |
429 | RATE_LIMIT_EXCEEDED: Too many uploads with this key. Wait for Retry-After, then upload once per CI job. Header: Retry-After. | Error |
503 | INGEST_NOT_AVAILABLE: Automated result upload is not available yet. Try again later. Header: Retry-After. | Error |
GET /api/v1/openapi.json
This document. The OpenAPI 3.1 description of the public API. No key required.
- Scope: none (
x-required-scope) - Authentication: none — no key required
- Operation id:
getOpenApiDocument
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | object |
GET /api/v1/projects
List projects. The projects this key can act on, by public id. A project key lists its one project; an all-projects key lists every project of its workspace. Never returns numeric ids.
- Scope:
read(x-required-scope) - Authentication:
Authorization: Bearer <service key> - Operation id:
listProjects
Parameters
| Name | In | Description |
|---|---|---|
cursor | query · string | Opaque cursor from a previous page's next_cursor. |
limit | query · integer (int32) | Page size, 1-100 (default 50). |
Responses
| Status | Meaning | Body |
|---|---|---|
200 | OK | ProjectPage |
400 |
| Error |
401 | API_KEY_UNAUTHORIZED: A valid workspace service key is required. | Error |
403 | SCOPE_REQUIRED: This key does not have the scope this endpoint requires. | Error |
Schemas
Error
The error body of every refusal on the public API.
| Field | Type | Description |
|---|---|---|
errorCode | string · required | Machine-readable error code. — one of API_KEY_UNAUTHORIZED, SCOPE_REQUIRED, TENANT_HEADER_NOT_ALLOWED, PROJECT_REQUIRED, INVALID_PROJECT_ID, KEY_PROJECT_MISMATCH, INVALID_FORMAT, FILE_REQUIRED, FILE_TOO_LARGE, INVALID_PARAMETER, IDEMPOTENCY_KEY_INVALID, IDEMPOTENCY_KEY_REUSED, INVALID_CURSOR, RATE_LIMIT_EXCEEDED, INGEST_NOT_AVAILABLE |
message | string · required | What went wrong, for a person. |
status | integer · required | The HTTP status. |
details | string | null | Extra detail, e.g. the offending field or the retry hint. |
path | string | The request path. |
timestamp | string | When the error occurred (UTC). |
IngestAccepted
The upload was accepted and recorded as an ingest job.
| Field | Type | Description |
|---|---|---|
ingest_id | string · required | Opaque id of the recorded upload. — e.g. ing_7f3k9q2m4x8z1c5v |
status | string · required | Always accepted. — one of accepted |
IngestResultsForm
multipart/form-data fields of an upload.
| Field | Type | Description |
|---|---|---|
file | string (binary) · required | The results file. Up to 25 MB; may be empty for a final complete=true call. |
format | string · required | File format. — one of junit-xml, playwright-json, to-results-json |
project | string | Only with an all-projects key: the project's public id. A project key may omit it; if sent it must be that key's own project. — pattern ^prj_[0-9a-hjkmnp-tv-z]{12}$; e.g. prj_8kd2hq0vxc1a |
run_key | string | Your stable id for the logical run (e.g. the CI run id). Uploads with the same key append to the same run. — up to 200 characters; e.g. gha-9876543210 |
run_name | string | Run name. Defaults to CI · <branch> · #<job>. — up to 255 characters |
environment | string | An Environment name or id for the whole upload. — up to 120 characters |
complete | string | true closes the run after this upload. — one of true, false |
tags | string | Comma-separated names of Automation tags. — up to 1000 characters; e.g. e2e,team-core |
ci_branch | string | CI fact: branch. — up to 255 characters; e.g. main |
ci_commit | string | CI fact: commit SHA. — up to 64 characters; e.g. 4f2c9a1 |
ci_actor | string | CI fact: who triggered the job. — up to 255 characters |
ci_job_url | string (uri) | CI fact: link to the job (http or https). — up to 2048 characters |
ci_provider | string | CI fact: provider (github, gitlab, circleci...). — up to 64 characters; e.g. github |
ci_build_number | string | CI fact: build or pipeline number. — up to 64 characters; e.g. 512 |
Project
A project the key can act on.
| Field | Type | Description |
|---|---|---|
public_id | string · required | Opaque public project id; pass it as project= with an all-projects key. — pattern ^prj_[0-9a-hjkmnp-tv-z]{12}$; e.g. prj_8kd2hq0vxc1a |
name | string · required | Project name. — e.g. Checkout Web |
ProjectPage
A page of results with an opaque cursor to the next page.
| Field | Type | Description |
|---|---|---|
data | array of Project · required | The page's items. |
next_cursor | string | null · required | Opaque cursor for the next page; null on the last page. — e.g. djE6cHJqXzhrZDJocTB2eGMxYQ |