This is a personal proof-of-concept project. It is not intended for production use. Please refrain from using it.
Skip to content

REST API

Upliftr's backend is a FastAPI JSON API. Everything the dashboard does, you can do over HTTP, author suites, start and observe runs, manage issues and settings, generate suites from a URL, export to Playwright, and read analytics.

  • Base path: /api/v1
  • Auth: every endpoint requires Authorization: Bearer <jwt-or-api-token>, except the open ones: GET /health, GET /health/ready, POST /auth/login, and the first-run bootstrap GET /auth/setup + POST /auth/setup (the latter only works while no users exist). See Authentication.
  • Interactive OpenAPI / Swagger UI: /docs, try every endpoint live, with full request / response schemas.
  • Raw schema: /openapi.json

The live OpenAPI page is the source of truth for exact request and response shapes, the tables below are a map, not a substitute. Generate clients from /openapi.json.

Endpoints

Health

MethodPathDescription
GET/healthLiveness, always 200 if serving.
GET/health/readyReadiness, 200 if the data dir is writable, else 503.

Auth

Full details in Authentication.

MethodPathDescription
GET/auth/setupOpen. { needs_setup }, true while the instance has no admin yet.
POST/auth/setupOpen (only valid pre-first-user). { email, password } creates the first admin → { token, user }.
POST/auth/login{ email, password }{ token, user }. Open (no auth).
GET/auth/meThe current user.
POST/auth/tokensCreate an API token { name? } → returns the raw tw_… once.
GET/auth/tokensList your API tokens (metadata only).
DELETE/auth/tokens/{id}Revoke an API token.
GET/auth/usersList users (admin).
POST/auth/usersCreate a user { email, password, role } (admin).

Suites

MethodPathDescription
GET/suitesList suites (paginated: limit, offset, q).
POST/suitesCreate a new suite, body { yaml }. The server picks a unique filename (never overwrites). Returns { ok, file }.
GET/suites/{name}Get a suite ({ file, yaml, cases }).
PUT/suites/{name}Update a suite, body { yaml }; validates YAML, returns 400 on error.
DELETE/suites/{name}Delete a suite.
GET/suites/{name}/exportExport the suite as a portable Playwright .spec.ts (text/plain).

Runs

Runs are persisted to a durable queue and worked by a pool of up to UPLIFTR_MAX_CONCURRENT_RUNS (default 2) workers, submit any number; they run in parallel up to that limit and the rest wait their turn (no 409). The queue survives a restart; a run interrupted by a crash is reconciled on the next startup. Each job is its own run id. State within a suite (generated fixtures and values a case capture:s) is shared across that suite's cases.

MethodPathDescription
GET/runsRun history (includes queued / running jobs).
POST/runsEnqueue one or more jobs. Single-suite form: { suite, cases?, file_issues?, sharded? }. Queue form: { jobs: [{ suite, cases? }, …], file_issues? }. cases is a subset of case ids (omit for all). Runs are headless. Returns { run_id, run_ids, queued }.
GET/runs/queueCurrently running + pending jobs, { active, active_suite, running: [{ id, suite }], running_suites, pending: [{ id, suite, cases }], busy } (active/active_suite keep the single-run shape for back-compat).
GET/runs/{id}Run status + live events + report. Events include action (each LLM browser action) and shot (a per-step screenshot path).

Run artifacts (per-step screenshots, reports) are served read-only under /api/v1/artifacts/<run_id>/…; each case in the report carries a shots[] list of { label, note, path } you can render from that base.

Plans (ordered regression passes)

A plan bundles suites into an ordered pass you run on demand or on a cron schedule.

MethodPathDescription
GET/plansList plans.
GET/plans/{plan_id}Plan detail (suites, schedule, last run).
POST/plansCreate/update a plan, body { id?, name, description?, items: [{ suite, cases? }], schedule?, auth? } (schedule is a cron expression; set id to update).
DELETE/plans/{plan_id}Delete a plan.
POST/plans/{plan_id}/runEnqueue the whole plan as one ordered pass → { run_ids }.

Issues (built-in tracker)

MethodPathDescription
GET/issues?status=List native issues (paginated; optional status, q).
GET/issues/{id}Issue detail ({ …, body_md, comments }).
PATCH/issues/{id}Partial edit, any of { status, title, body_md, severity }. status is open / closed / acknowledged.
POST/issues/{id}/commentsAdd a comment, body { body }.

Settings (admin)

Writing settings requires an admin.

MethodPathDescription
GET/settingsIntegration settings, secrets are masked on read.
PUT/settingsSave settings, body is the settings object (only non-null fields are written).
POST/settings/test-notificationSend a test Slack/Teams notification with the current config.

Integrations

MethodPathDescription
GET/integrations/trackersWhich issue trackers are configured: { github, gitlab, jira } booleans. Drives the dashboard's tracker picker so it only offers what's set up.

Artifacts

MethodPathDescription
GET/artifacts/{path}A run artifact (per-step screenshot, report). Authenticated, send the Bearer token, or ?token=<jwt> for <img>/<a> tags. Confined to the artifacts directory.

Generate (anything → suite)

Generate a suite from a live app, your docs/spec, or a description. Exhaustive by default, a multi-pass generator (discover areas → expand each into happy-path, validation, edge, error, auth and negative scenarios in parallel).

MethodPathDescription
POST/generateBody { kind, url?, base_url?, text?, auth?, exhaustive?, save_as? }. kind is url | docs | text | openapi. For url, pass url (a deep page works; add auth: { username, password, login_path? } to reach pages behind login). For docs/text/openapi, pass base_url (what the suite targets) plus a url to fetch or pasted text. Returns { yaml } (plus saved_as). See generation.
POST/generate/planExhaustive generation that splits the app into several suites and saves them as a ready-to-run plan. Returns { plan_id, plan_name, suites }.

Analyze (embeddable engine — one call → root-caused bugs)

The single entrypoint for embedding Upliftr: generate + run + root-cause in one call. See Embedding Upliftr and the /analyze contract.

MethodPathDescription
POST/analyzeBody { app_url, kind?, auth?, exhaustive?, file_issues?, mode?, timeout_s?, anthropic_key?, log_backend? }. Generates a suite for app_url, runs it, and returns a typed AnalyzeResult { run_id, status, summary, cases[{status, why, root_cause}], issues }. mode: "sync" (default) waits; "async" returns a run_id to poll via /runs/{id}. anthropic_key / log_backend override the org's saved settings per request.

Tracing (root-cause helper)

MethodPathDescription
GET/tracing/snippet.jsOpen (no auth). The drop-in browser trace-propagation snippet — a dependency-free script that makes an app's same-origin fetch/XHR emit a W3C traceparent, so a UI failure resolves to the backend log line. See Connecting server logs.

Analytics

MethodPathDescription
GET/analyticsFlake / run analytics over the full run history. See Flakiness analytics.

Checks (standalone)

Dry-run a single deterministic check core without authoring a whole suite. These are not suite expect kinds (suites use the four check kinds), they are standalone endpoints for dashboards and visual baselines.

MethodPathDescription
POST/checks/apiBody { url, method?, status?, json_path?, equals?, headers?, body? }. Runs an HTTP request and asserts status and/or a JSON path. Returns { kind: "api", status, observed }.
POST/checks/screenshotBody { name, image_b64, tol? }. Compares a PNG against the stored baseline for name (first run for a name seeds the baseline and passes). Returns { kind: "screenshot_region", status, observed }.

Examples

Start a run:

bash
curl -X POST http://127.0.0.1:8400/api/v1/runs \
  -H 'Content-Type: application/json' \
  -d '{"suite": "signup-login.upliftr.yaml", "file_issues": "upliftr"}'

Poll its status, live events, and report:

bash
curl http://127.0.0.1:8400/api/v1/runs/<run-id>

Save (and validate) a suite, the body is JSON { "yaml": "..." }:

bash
curl -X PUT http://127.0.0.1:8400/api/v1/suites/signup-login.upliftr.yaml \
  -H 'Content-Type: application/json' \
  -d "{\"yaml\": $(jq -Rs . < signup-login.upliftr.yaml)}"

Generate a suite from a URL and save it:

bash
curl -X POST http://127.0.0.1:8400/api/v1/generate \
  -H 'Content-Type: application/json' \
  -d '{"url": "https://app.example.com", "save_as": "app-flows"}'

Export a suite to portable Playwright:

bash
curl http://127.0.0.1:8400/api/v1/suites/signup-login.upliftr.yaml/export -o tests/signup.spec.ts

List open issues from the built-in tracker:

bash
curl 'http://127.0.0.1:8400/api/v1/issues?status=open'

Error shape

Errors are returned as JSON via the app's error handlers, e.g. a missing/invalid token returns 401; an action needing admin returns 403; invalid YAML on PUT /suites/{name} returns 400 with a type of invalid_yaml; generation failures return 502 (generation_error).

See also

Upliftr · AI-native, self-healing E2E testing. Terms · Privacy · Legal Notice