REST API · v1 · OpenAPI 3.1

Drive everything from a script.

Every action you can take in the Outworx dashboard — create projects, push spec versions, promote a default, soft-deactivate an old version — is a single curl away. One account-scoped token, JSON in, JSON out.

All plansReplaces: bespoke CI shims · per-project upload tokens
ci → docs.outworx.io
$ curl -X POST -H "Authorization: Bearer otwx_pat_..." \
  -H "Content-Type: application/json" \
  --data-binary '@openapi.json' \
  'https://docs.outworx.io/api/v1/projects/payments-api/versions?label=v2&makeDefault=true'
← 201 Createdis_default · true
{
  "id": "0a3b…",
  "project_id": "f1b7…",
  "version_label": "v2",
  "spec_format": "openapi3",
  "is_default": true,
  "is_active": true,
  "spec_size": 142884,
  "created_at": "2026-05-09T13:04:11Z"
}

Quick start

Sixty seconds to your first call.

Three calls. No SDK install, no codegen. The body of a spec upload is the spec itself — same shape your CI already has on disk.

1

Generate a personal access token

Open Settings, find the API tokens card, click New token, name it (ci-pipeline, local-dev, etc), optionally set an expiry. The plaintext is shown once — copy it now and stash it in a CI secret. We hash and forget.

2

Create a project

Slug auto-generates from name when omitted. Plan-limit checks kick in here so a runaway script can't blow past your project cap.

curl -X POST -H "Authorization: Bearer $OUTWORX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Payments API"}' \
  https://docs.outworx.io/api/v1/projects
3

Push a spec version

Body IS the spec — OpenAPI 3.x JSON/YAML, Swagger 2.0, or GraphQL SDL. 50 MB cap. The first active version becomes the default automatically.

curl -X POST -H "Authorization: Bearer $OUTWORX_TOKEN" \
  -H "Content-Type: application/json" \
  --data-binary '@openapi.json' \
  'https://docs.outworx.io/api/v1/projects/payments-api/versions?label=v1'
4

Promote on release

Single-default invariant is enforced server-side. Setting is_default: true on a non-default version demotes the previous default in the same write — no two-step dance.

curl -X PATCH -H "Authorization: Bearer $OUTWORX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"is_default":true}' \
  https://docs.outworx.io/api/v1/projects/payments-api/versions/v2

Endpoints

Ten routes. One token.

The full request and response shapes — including every error code, every example, every schema — live in the OpenAPI spec. Drop the URL into Postman, openapi-typescript, or your client of choice.

Projects

5 routes
GET/api/v1/projectsList your projects (paginated, ?q= filter)
POST/api/v1/projectsCreate a project — slug auto-generates from name
GET/api/v1/projects/{slug}Get one project
PATCH/api/v1/projects/{slug}Sparse update: name, is_public, base_url, custom domain
DELETE/api/v1/projects/{slug}Delete a project (cascades to versions)

Versions

5 routes
GET/api/v1/projects/{slug}/versionsList versions (?include_previews= to surface PR-scoped rows)
POST/api/v1/projects/{slug}/versionsPush a spec version (?label=, ?makeDefault=, ?preview= for PR previews)
GET/api/v1/projects/{slug}/versions/{label}Get one version
PATCH/api/v1/projects/{slug}/versions/{label}Promote default, soft-deactivate, override base_url
DELETE/api/v1/projects/{slug}/versions/{label}Delete a version (default version is protected)
Single-default invariant: the API rejects direct demotion of the default version with 400 VALIDATION_ERROR — the project would have no default and the docs would 404. DELETE on the default returns 409 CONFLICT for the same reason. Promote a replacement first; we handle the demotion in the same write.

Conventions

Predictable shapes, stable codes.

Three things to know up front. Pattern-match on error.code — that's the stable identifier; messages are display-only and may change between versions.

Auth

Authorization: Bearer otwx_pat_… Tokens are sha-256 hashed at rest, optionally expire, and act as the user who created them. Revoke from the dashboard and the token returns 401 INVALID_TOKEN on the very next request.

List shape

Lists wrap data: { data: […], pagination: { total, limit, offset } }. limit clamps to 1–100 (default 50), offset defaults to 0. Single-resource endpoints return the resource directly — no envelope.

Errors

Stable code + human message + optional details. We don't differentiate “doesn't exist” from “not yours” — both are 404 NOT_FOUND so a token can't probe slug existence.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "`name` is required."
  }
}

Ready to wire it up?

Generate a token, drop the OpenAPI spec into your client of choice, and the dashboard becomes optional. The full guide walks through CI bootstrapping, the single-default invariant, plan limits, and what we kept out of v1.