On this page

API & Automation

Proba.run exposes a machine-facing layer for CI pipelines and scripts: a public REST API for reading and writing your test data, dedicated endpoints for submitting automated test results, and one-way synchronization of test cases with a git repository. All of it is authenticated with an API key instead of a user session.

API keys

An API key is a project-scoped secret used for machine access — no login, no 2FA. Create one from your project settings, on the API keys tab.

  1. Click New key and give it a name.
  2. The raw key is shown exactly once, right after creation. Copy it immediately — Proba.run only stores a hash, so it cannot be shown again.
  3. Send the key on every request in the X-Api-Key header.

Each key has a scope:

ScopeCan do
full (default)Read and write everything the key's owner can access in the project
read_onlyRead endpoints only — any write request returns an error

Use a read_only key wherever a script or integration only needs to read data (for example, the case sync skill described below). Revoke a key from the same tab at any time; revoked keys stop working immediately.

Public REST API

The public API lives under /api/v1/** and is scoped to the project the key belongs to — there is no project identifier in the URL, so a key can never reach another project's data.

MethodPathPurpose
GET/api/v1/projectProject metadata
GET/api/v1/casesList cases (filter by folder, priority, status, search, archived)
GET/api/v1/cases/{caseNumber}Case detail with fully expanded steps
POST/api/v1/casesCreate a case
PATCH/api/v1/cases/{caseNumber}Update a case (partial)
DELETE/api/v1/cases/{caseNumber}Move a case to the project trash
POST/api/v1/cases/importBulk-import cases (folders and tags resolved by name)
GET/api/v1/tagsProject tags (source of tagIds for case writes)
GET/api/v1/foldersProject folders
GET/api/v1/runsList runs
GET/api/v1/runs/{runNumber}Run detail with progress
GET/api/v1/runs/{runNumber}/casesRun cases, paginated
POST/api/v1/runsCreate a run
PATCH/api/v1/runs/{runNumber}Update a run (name, description, close/reopen)
POST/api/v1/runs/{runNumber}/cases/{caseNumber}/resultsSubmit a result
GET/api/v1/tasksTasks with their requirements
GET/api/v1/sync/manifestFull case manifest for git sync (see below)

List endpoints are paginated with ?page and ?perPage (default 25, maximum 100) and return { items, total, page, perPage, totalPages }. Any error responds with { "error": "...", "code": "..." } — branch your client logic on code (unauthorized, not_found, validation_failed, archived, rate_limited), not on the error text.

Example requests

List a project's active cases:

curl -H "X-Api-Key: qalab_xxx" \
  "https://your-instance.example.com/api/v1/cases?status=active&page=1"

Submit a result for a case in an existing run:

curl -X POST \
  -H "X-Api-Key: qalab_xxx" \
  -H "Content-Type: application/json" \
  -d '{"status":"passed","elapsedSeconds":1.4}' \
  "https://your-instance.example.com/api/v1/runs/42/cases/DMO-17/results"

Creating and editing cases via the API

POST /api/v1/cases creates a single case and responds with the same shape as the case detail endpoint. title is required; optional fields are folderId (must belong to the project), priority (low|medium|high|critical), status (active|draft|deprecated), description, preconditions, tagIds (uuids from GET /api/v1/tags), and steps in one of two forms — a steps array of { "step", "expected" } objects, or a plain-text stepsText (optionally with expectedText). Passing both forms at once is rejected.

PATCH /api/v1/cases/{caseNumber} updates only the fields you send (an empty patch is rejected): same fields as create, plus folderId: null moves the case to the project root and tagIds replaces the whole tag set. DELETE /api/v1/cases/{caseNumber} soft-deletes the case into the project trash — restoring or purging stays in the UI.

curl -X POST \
  -H "X-Api-Key: qalab_xxx" \
  -H "Content-Type: application/json" \
  -d '{"title":"Login works","priority":"high","steps":[{"step":"Open /login","expected":"Form is shown"}]}' \
  "https://your-instance.example.com/api/v1/cases"

POST /api/v1/cases/import accepts { "cases": [...] } with up to 2000 items and follows the CSV import semantics: folders and tags are resolved by name (created when missing), steps are plain text only (stepsText), and an unknown priority/status silently falls back to the default (medium/active). Invalid items do not fail the batch — the response is { "imported": N, "errors": [{ "row": 3, "reason": "..." }] } with 1-based row numbers. Item fields: title (required), folder, priority, status, description, preconditions, tags (array of names), stepsText.

curl -X POST \
  -H "X-Api-Key: qalab_xxx" \
  -H "Content-Type: application/json" \
  -d '{"cases":[{"title":"Login works","folder":"Auth","tags":["smoke"],"stepsText":"1. Open /login"}]}' \
  "https://your-instance.example.com/api/v1/cases/import"

Both endpoints require a full-scope key. Bulk import is additionally covered by the import rate limit and is only available on plans that include imports.

Submitting automated test results

For CI pipelines that just need to report results without managing runs case by case, use the automation endpoints. Both create a closed run in one call and auto-create any missing test case by title.

  • POST /api/automation/runs — JSON body with a run name and a results array (title, status, optional elapsedSeconds/comment).
  • POST /api/automation/runs/junit — multipart upload of a JUnit XML file plus a name field.

Both require X-Api-Key and return the created run, including its progress summary, so CI can link back to it.

Rate limits

Every machine endpoint is rate-limited per API key, with a 429 response and a Retry-After header when exceeded:

EndpointsLimit
Public API (/api/v1/**)120 requests / minute
Automation result submission30 requests / minute

Syncing test cases with a git repository

Instance owners can link a project to a GitHub repository so test cases stored as markdown files stay in sync with Proba.run. This is aimed at teams that want Claude Code (or another tool working inside the repo) to read, review, and test against the same case files the team edits in Proba.run.

  • Repository to Proba.run: from the project's Repository sync settings, configure the repo (owner, name, branch, path prefix) and a token, then click Synchronize. A preview shows what will be created, updated, moved, or unlinked before anything is written.
  • Proba.run to repository: the /api/v1/sync/manifest endpoint returns the current state of every synced case as file content. A companion skill, installed into the repository, pulls this manifest and updates local files to match — creating, overwriting, moving, or removing files as needed. It never commits or pushes; that stays a manual, reviewed step.

A read_only API key is the recommended choice for the sync skill, since it only ever needs to read the manifest.