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": "8c9d3e2a-4f1b-4c6d-9a2e-1f0b3c4d5e6f",
    "siteId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "target": "preview",
    "status": "queued",
    "createdAt": "2026-05-14T15:00:00Z"
  }
}

The environment field on a deployment record is named target and is one of preview, staging, or production.

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 does not require OTP or MFA enrollment. It still requires an explicit publish action and, on plans with approval workflows (Team/Enterprise), a second-person approval. Agents use request_publish on approval-workflow plans or the two-step publish_site confirmation on self-serve plans.

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 its address in the url field; a ready production deployment serves the site's production route.

Stream build progress

Live build progress streams over SSE from the previews surface:

GET /previews/{deploymentId}/stream
Accept: text/event-stream

The stream emits status transitions and closes when the deployment reaches a terminal state. For post-hoc reads, two plain endpoints cover most needs:

  • GET /deployments/{deploymentId}/log?lineCount=200 — the captured build log tail.
  • GET /deployments/{deploymentId}/diagnostics — a structured failure bundle (stage, error code, log tail, ranked hypotheses) designed for agent self-debugging.

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 re-publish a previously ready Preview, call POST /sites/{siteId}/deploy with environment: "production" and that deployment's id as sourceDeploymentId; normal approval, quota, and security gates still apply, but OTP enrollment is not required.

List deployments

GET /deployments

Returns the full deployment list for your workspace as a plain array — there are no filter or pagination parameters yet. For a single site's history, use GET /sites/{siteId}/deployments.

Errors specific to deployments

CodeStatusMeaning
idempotency_key_required428POST /sites/{siteId}/deploy was called without an Idempotency-Key header.
idempotency_key_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).
source_deployment_not_found404The sourceDeploymentId doesn't exist or isn't visible to your token.
source_deployment_not_ready409The named source deployment isn't in a publishable (ready) state.

Exhausting the monthly deploy quota returns 402 with a quota error — upgrade the plan or wait for the monthly reset.

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

Read the build log:

curl -sS ".../deployments/$DEP/log?lineCount=500" \
  | jq -r '.data.lines[]' | 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.