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/results answers 503 INGEST_NOT_AVAILABLE with Retry-After, after the key and its scope have been checked. When it is open, an accepted upload is recorded (202 with an ingest_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

RouteScopeSummary
POST /api/v1/ingest/resultsingest:resultsUpload automated test results
GET /api/v1/openapi.jsonnoneThis document
GET /api/v1/projectsreadList 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

NameInDescription
Idempotency-Keyheader · string1-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.

FieldTypeDescription
filestring (binary) · requiredThe results file. Up to 25 MB; may be empty for a final complete=true call.
formatstring · requiredFile format. — one of junit-xml, playwright-json, to-results-json
projectstringOnly 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_keystringYour 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_namestringRun name. Defaults to CI · <branch> · #<job>. — up to 255 characters
environmentstringAn Environment name or id for the whole upload. — up to 120 characters
completestringtrue closes the run after this upload. — one of true, false
tagsstringComma-separated names of Automation tags. — up to 1000 characters; e.g. e2e,team-core
ci_branchstringCI fact: branch. — up to 255 characters; e.g. main
ci_commitstringCI fact: commit SHA. — up to 64 characters; e.g. 4f2c9a1
ci_actorstringCI fact: who triggered the job. — up to 255 characters
ci_job_urlstring (uri)CI fact: link to the job (http or https). — up to 2048 characters
ci_providerstringCI fact: provider (github, gitlab, circleci...). — up to 64 characters; e.g. github
ci_build_numberstringCI fact: build or pipeline number. — up to 64 characters; e.g. 512

Responses

StatusMeaningBody
202Accepted and recorded. A replay of an earlier Idempotency-Key carries the header Idempotent-Replay: true.IngestAccepted
400
  • TENANT_HEADER_NOT_ALLOWED: Do not send X-Tenant-Workspace or X-Tenant-Subdomain: the key decides the workspace.
  • PROJECT_REQUIRED: This key is for all projects: pass project=prj_... to say which one.
  • INVALID_PROJECT_ID: project must be a project id like prj_8kd2hq0vxc1a, from the project's settings page.
  • INVALID_FORMAT: format must be one of junit-xml, playwright-json, to-results-json.
  • FILE_REQUIRED: Send the results as multipart/form-data with a file part.
  • INVALID_PARAMETER: A request parameter is invalid.
  • IDEMPOTENCY_KEY_INVALID: The Idempotency-Key header is malformed.
Error
401API_KEY_UNAUTHORIZED: A valid workspace service key is required.Error
403
  • SCOPE_REQUIRED: This key does not have the scope this endpoint requires.
  • KEY_PROJECT_MISMATCH: This key cannot report to that project, or the project was not found or access is denied.
Error
413FILE_TOO_LARGE: The results file is over 25 MB. Split it by shard or drop stdout from the report.Error
422IDEMPOTENCY_KEY_REUSED: This Idempotency-Key was already used for a different upload.Error
429RATE_LIMIT_EXCEEDED: Too many uploads with this key. Wait for Retry-After, then upload once per CI job. Header: Retry-After.Error
503INGEST_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

StatusMeaningBody
200OKobject

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

NameInDescription
cursorquery · stringOpaque cursor from a previous page's next_cursor.
limitquery · integer (int32)Page size, 1-100 (default 50).

Responses

StatusMeaningBody
200OKProjectPage
400
  • TENANT_HEADER_NOT_ALLOWED: Do not send X-Tenant-Workspace or X-Tenant-Subdomain: the key decides the workspace.
  • INVALID_PARAMETER: A request parameter is invalid.
  • INVALID_CURSOR: The cursor is invalid. Start again without one.
Error
401API_KEY_UNAUTHORIZED: A valid workspace service key is required.Error
403SCOPE_REQUIRED: This key does not have the scope this endpoint requires.Error

Schemas

Error

The error body of every refusal on the public API.

FieldTypeDescription
errorCodestring · requiredMachine-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
messagestring · requiredWhat went wrong, for a person.
statusinteger · requiredThe HTTP status.
detailsstring | nullExtra detail, e.g. the offending field or the retry hint.
pathstringThe request path.
timestampstringWhen the error occurred (UTC).

IngestAccepted

The upload was accepted and recorded as an ingest job.

FieldTypeDescription
ingest_idstring · requiredOpaque id of the recorded upload. — e.g. ing_7f3k9q2m4x8z1c5v
statusstring · requiredAlways accepted. — one of accepted

IngestResultsForm

multipart/form-data fields of an upload.

FieldTypeDescription
filestring (binary) · requiredThe results file. Up to 25 MB; may be empty for a final complete=true call.
formatstring · requiredFile format. — one of junit-xml, playwright-json, to-results-json
projectstringOnly 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_keystringYour 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_namestringRun name. Defaults to CI · <branch> · #<job>. — up to 255 characters
environmentstringAn Environment name or id for the whole upload. — up to 120 characters
completestringtrue closes the run after this upload. — one of true, false
tagsstringComma-separated names of Automation tags. — up to 1000 characters; e.g. e2e,team-core
ci_branchstringCI fact: branch. — up to 255 characters; e.g. main
ci_commitstringCI fact: commit SHA. — up to 64 characters; e.g. 4f2c9a1
ci_actorstringCI fact: who triggered the job. — up to 255 characters
ci_job_urlstring (uri)CI fact: link to the job (http or https). — up to 2048 characters
ci_providerstringCI fact: provider (github, gitlab, circleci...). — up to 64 characters; e.g. github
ci_build_numberstringCI fact: build or pipeline number. — up to 64 characters; e.g. 512

Project

A project the key can act on.

FieldTypeDescription
public_idstring · requiredOpaque public project id; pass it as project= with an all-projects key. — pattern ^prj_[0-9a-hjkmnp-tv-z]{12}$; e.g. prj_8kd2hq0vxc1a
namestring · requiredProject name. — e.g. Checkout Web

ProjectPage

A page of results with an opaque cursor to the next page.

FieldTypeDescription
dataarray of Project · requiredThe page's items.
next_cursorstring | null · requiredOpaque cursor for the next page; null on the last page. — e.g. djE6cHJqXzhrZDJocTB2eGMxYQ

Was this page helpful?Tell us what’s missingOpens an email to support with the page already named.