All documentation
Automation

REST API

The app runs on this API, and a scoped token can call most of it. Account, billing and token management need a signed-in session.

Conventions

  • REST over JSON, versioned at /v1, served from https://provisore.com.
  • Authenticate with the session cookie the web app uses, or with a personal access token sent as Authorization: Bearer pvs_….
  • Every request is scoped to your active team. An id from another team returns 404.
  • Endpoints that change something require an Idempotency-Key header of 8 to 255 characters, and refuse a request without one. A repeated request returns the original result with Idempotent-Replayed: true.
  • Destructive endpoints require you to name the target in a header: X-Confirm-Domain, X-Confirm-Name, or X-Confirm-Target.

Errors

{
  "code": "php_version_in_use",
  "message": "PHP 8.2 still serves api.example.com.",
  "fieldErrors": { "version": "Not removable while a site uses it." },
  "requestId": "01J8Z…"
}

Branch on code, display message, and include requestId when you contact support. The common statuses are 400 for an invalid request, 402 when the team is read-only or its plan does not allow the change, 403 for a missing scope or role, 404 for not found, 409 for conflicting state or a confirmation mismatch, 410 for a one-time secret already revealed, and 429 when rate limited.

Long-running operations

Anything that touches a server returns a job straight away and continues in the background. That covers provisioning, deploys, certificates, backups, restores, databases, daemons, cron, and firewall rules.

POST /v1/sites/{siteId}/deployments
Authorization: Bearer pvs_…
Idempotency-Key: 2026-08-18-build-4171
{ "trigger": "manual" }

202 Accepted
{ "deployment": { "id": "…", "status": "queued" },
  "job":        { "id": "…", "status": "queued" } }

GET  /v1/jobs/{jobId}          # poll
GET  /v1/jobs/{jobId}/events   # or stream it
POST /v1/jobs/{jobId}/cancel   # applied between steps

The event stream is Server-Sent Events. It sends a snapshot first, then log, progress, status, and periodic heartbeat events. Reconnect with Last-Event-ID and you receive the events you missed before the stream resumes.

Lists and pagination

Collections return { "data": [ … ] }. Jobs and audit entries page with a cursor. Pass the previous page's nextCursor as cursor. Entries added while you page neither shift nor duplicate results.

Example: deploy from CI

SITE=$(curl -fsS https://provisore.com/v1/sites \
  -H "Authorization: Bearer $PROVISORE_TOKEN" \
  | jq -r '.data[] | select(.domain=="example.com") | .id')

JOB=$(curl -fsS -X POST "https://provisore.com/v1/sites/$SITE/deployments" \
  -H "Authorization: Bearer $PROVISORE_TOKEN" \
  -H "Idempotency-Key: $GITHUB_RUN_ID" \
  -H "Content-Type: application/json" \
  -d '{"trigger":"manual"}' | jq -r .job.id)

while :; do
  STATUS=$(curl -fsS "https://provisore.com/v1/jobs/$JOB" \
    -H "Authorization: Bearer $PROVISORE_TOKEN" | jq -r .status)
  case "$STATUS" in
    succeeded) break ;;
    failed|cancelled) echo "deploy $STATUS" >&2; exit 1 ;;
  esac
  sleep 2
done

The token needs sites:read to find the site, deployments:write to start the deploy, and observability:read to follow its job.

To deploy when a build goes green and do nothing else, a deploy hook is simpler. It is one URL, with no token to manage.

This page is the reference

Build requests from the examples above. There is no published OpenAPI document to generate a client from, and no client library.