Sites API
List, create, and inspect sites with curl-able examples.
The sites surface lets you enumerate, inspect, and create the sites in a workspace. The REST API has no version prefix: all paths below are rooted at https://api.showly.ai.
List sites
GET /sites
Authorization: Bearer <token>
Returns every site the token can see (a plain array — no pagination yet), plus a sibling entitlements object with the workspace's site caps.
{
"ok": true,
"data": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"projectId": "9b2f1c44-0d31-4c19-8a77-0f4bd4a1c001",
"slug": "marketing-site",
"name": "Marketing site",
"framework": "next-export",
"status": "active",
"repositoryUrl": "https://github.com/acme/marketing",
"productionUrl": "https://marketing-site.showly.site",
"createdAt": "2026-03-01T10:14:22Z",
"updatedAt": "2026-07-01T08:03:10Z"
}
],
"entitlements": {
"maxSites": "unlimited",
"currentSites": 3,
"maxLiveSites": "unlimited",
"currentLiveSites": 1
}
}
Site ids are UUIDs. The framework value is a free-form string auto-detected by the builder (for example next-export, astro, static-html).
Site allowances
maxLiveSites is the commercial Live-site allowance. It is "unlimited" on both Free and Pro. A finite value can still appear on a custom contract or entitlement override, and production publish checks that value when present.
maxSites covers all active site records, including Preview-only sites. It is also "unlimited" on every baseline plan. A finite value appears only when an operator has applied an explicit workspace override; moving from Free to Pro does not add site slots. Workspace Previews do not expire.
Get a single site
GET /sites/{siteId}
Returns the site plus the current manifest and most-recent deployment summary.
Create a site
POST /sites
Content-Type: application/json
{
"projectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Docs",
"slug": "docs",
"repositoryUrl": "https://github.com/acme/docs"
}
Returns 201 + the created site. projectId is the UUID of the project the site belongs to. slug must match ^[a-z0-9-]+$ and be unique in the workspace; if it collides you get 409 with error.code: "slug_taken". framework and repositoryUrl are optional.
Build configuration lives in a showly.json manifest committed to the repository, not in the create body. The builder auto-detects the framework and reads rootDirectory, runtime, buildCommand, output, and related fields from that file. See Site manifest for the full schema.
Deploy targets
Deploy targets are configured at the organization level, not per site. They are mounted at /deployment-targets:
| Method | Path | Purpose |
|---|---|---|
GET | /deployment-targets | List configured targets. |
GET | /deployment-targets/capabilities | List supported provider options. |
POST | /deployment-targets | Create a target. |
PATCH | /deployment-targets/:id | Update a target. |
DELETE | /deployment-targets/:id | Remove a target. |
A target carries a provider, mode, and runtime. The capability endpoint is the source of truth for combinations enabled in the current environment; enum values in an API schema do not promise that a provider is provisioned. Unsupported combinations return 400 deployment_target_not_implemented.
Registering a deployment target in your own cloud account requires the byoCloudTargets entitlement and a user actor. A token-only bot cannot create, update, or delete an own-cloud target.
Curl example: end-to-end create + first deploy
# 1. Create the site
SITE=$(curl -sS -X POST https://api.showly.ai/sites \
-H "authorization: bearer $SHOWLY_TOKEN" \
-H "content-type: application/json" \
-d '{ "projectId": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "Demo", "slug": "demo", "repositoryUrl": "https://github.com/acme/demo" }' \
| jq -r '.data.id')
# 2. Inspect the site (and the auto-detected manifest)
curl -sS "https://api.showly.ai/sites/$SITE" \
-H "authorization: bearer $SHOWLY_TOKEN"
# 3. Request a preview deployment (siteId in the path; Idempotency-Key required)
curl -sS -X POST "https://api.showly.ai/sites/$SITE/deploy" \
-H "authorization: bearer $SHOWLY_TOKEN" \
-H "content-type: application/json" \
-H "idempotency-key: $(uuidgen)" \
-d '{ "environment": "preview" }'
The create-deployment call returns 202. The Idempotency-Key header is required on POST /sites/:siteId/deploy; without it the request returns 428, and a conflicting retry returns 409. See Deployments for the rest of the deploy lifecycle.
Archive and restore
Deleting a site archives it: it disappears from GET /sites but is still listed by GET /sites/archived. Sites are not archived just because they remain in Preview. Explicit deletion makes the site's slug available for reuse. If the workspace has a finite explicit maxSites override, deletion also frees one overridden slot.
Bring one back with:
POST /sites/:siteId/restore
The site returns empty and ready to redeploy — its old deployments are not resurrected, because their build artifacts have already been garbage-collected. Restoring consumes a site slot, so it returns 402 if you are at your maxSites allowance, and 404 if the id is unknown, belongs to another workspace, or is already active.
Errors
| Code | Status | Meaning |
|---|---|---|
site_not_found | 404 | siteId doesn't exist or token can't see it. |
slug_taken | 409 | A different site already uses that slug. |
project_not_found | 404 | projectId doesn't exist in this workspace. |
github_installation_not_found | 404 | The referenced GitHub App install is missing. |