Public API

Deployments API

Trigger publishes, query rollbacks, and stream pipeline events.

The deployments surface covers preview builds, production publishes, and pipeline event streams. Paths are unprefixed and rooted at https://api.showly.ai (there is no version prefix).

Create a deployment

POST /sites/{siteId}/deploy
Authorization: Bearer <token>
Idempotency-Key: <uuid>
Content-Type: application/json

{
  "environment": "preview",
  "commitSha": "abc123...",
  "branch": "main"
}

This is the only route that creates a deployment (siteId is in the path; there is no POST /deployments). It requires an Idempotency-Key header — a missing key returns 428, and a replayed key that conflicts returns 409. It returns 202 + a deployment record in queued state. The build runs asynchronously; subscribe to events or poll the deployment record.

{
  "ok": true,
  "data": {
    "id": "dep_01HZX...",
    "siteId": "site_01HZX...",
    "environment": "preview",
    "status": "queued",
    "createdAt": "2026-05-14T15:00:00Z"
  }
}

Publish to production

Production publishes use the same endpoint with environment: "production" and a sourceDeploymentId naming the already-built ready preview being promoted:

POST /sites/{siteId}/deploy
Authorization: Bearer <token>
Idempotency-Key: <uuid>
Content-Type: application/json

{
  "environment": "production",
  "sourceDeploymentId": "dep_01HZX..."
}

Production publish is gated by step-up MFA and an approval. This means it cannot be driven from a token-only REST or CI client: the publish must be requested and approved from a human web session. Agents reach this path through the MCP request_publish tool, which returns a webApprovalUrl deep link to the web approval screen. Use the decision endpoint below to record an approve/reject once a request exists.

Get a deployment

GET /deployments/{deploymentId}

A deployment status is exactly one of five values:

queued → building → ready
                  ↘ failed
                  ↘ canceled

ready is the terminal success state for both preview and production deployments; failed and canceled are the terminal failure states. There is no built or live status. A ready preview deployment carries a previewUrl; a ready production deployment serves the site's production route.

Stream pipeline events

GET /deployments/{deploymentId}/events
Accept: text/event-stream

Server-sent events, one event per pipeline state transition + log batch:

event: status
data: { "status": "building", "at": "..." }

event: log
data: { "stream": "build", "lines": [...] }

event: status
data: { "status": "ready", "previewUrl": "https://preview-xxx.showly.app" }

The stream closes when the deployment reaches a terminal state.

Approve / reject a production publish request

POST /approvals/{requestId}/decision
Content-Type: application/json

{
  "decision": "approve" | "reject",
  "notes": "looks good"
}

Requires an active user membership with an allowed approval role. The originating actor is forbidden from approving their own request (separation of duties).

Rollback

There is no rollback REST endpoint. Reverting to a prior deployment is a web-UI operation only. To revert programmatically, re-publish the previously-ready deployment by calling POST /sites/{siteId}/deploy with environment: "production" and that deployment's id as sourceDeploymentId (still subject to step-up MFA and approval).

List deployments

GET /deployments?siteId=...&environment=production&limit=50

Supports cursor pagination. Filter by status, siteId, environment, since, until. Scoped per-site listing is also available at GET /sites/{siteId}/deployments.

Errors specific to deployments

CodeStatusMeaning
idempotency_key_required428POST /sites/{siteId}/deploy was called without an Idempotency-Key header.
idempotency_conflict409The supplied Idempotency-Key was already used with a different request.
deployment_not_found404Token can't see this deployment.
approval_required428Production publish needs an approval before it can promote.
source_deployment_required428Production publish must name the ready preview via sourceDeploymentId.
self_approval_forbidden403Approver is the originating actor (separation of duties).
build_quota_exceeded429Workspace hit its concurrent-build limit. Branch on error.code — this 429 does NOT carry a Retry-After header and will not clear on a timer.

Patterns

Wait for a deployment to finish (CI):

DEP=$(curl ... | jq -r .data.id)
while :; do
  S=$(curl -sS .../deployments/$DEP | jq -r .data.status)
  [ "$S" = "ready" ] && break
  { [ "$S" = "failed" ] || [ "$S" = "canceled" ]; } && exit 1
  sleep 10
done

Stream logs to a file:

curl -N .../deployments/$DEP/events \
  | grep -A1 'event: log' \
  | tee build.log

For most automation, the [MCP create_preview tool](/docs/mcp/tool-reference) is simpler — the REST API exists for the cases MCP doesn't fit.