Projects API
A project is a deployable unit of code. Its slug is either static (served from Firebase/CDN) or container (run on Kubernetes); when you create with auto, PandaStack detects which one your repo is and resolves the slug for you. Secrets are never returned by any project endpoint — the env array carries only plaintext variables.
For the conceptual guides see Projects overview, Static sites, Container apps, Environment variables & secrets, Custom domains, and Redirects, rewrites & headers.
All routes below are org-scoped and require authentication. The role floor is noted per endpoint.
The project object
Section titled “The project object”ProjectDetail (returned by get / create-result-adjacent reads):
| Field | Type | Notes |
|---|---|---|
id | number | |
name | string | null | Subdomain-safe name. |
slug | static | container | string | null | Deployment target. |
branch | string | null | Tracked branch. |
repositoryName | string | null | owner/repo. |
organizationId | string | BIGINT serialized as string. |
projectUrl | string | null | Live URL. |
enabled | boolean | Whether the project is active (see toggle). |
isPublic | boolean | |
language | string | null | e.g. nodejs, python, go, docker. |
runtime | string | null | |
region | string | null | |
baseDir | string | null | Build root directory. |
buildDir | string | null | Static output directory. |
buildCmd | string | null | |
startCmd | string | null | Container start command. |
healthCheckPath | string | null | |
dockerFilePath | string | null | |
tier | object | null | Instance tier. |
disk | number | null | Persistent disk (GB). |
autoScaling | object | null | { enabled, minReplicas, maxReplicas, targetCpuPercent }. |
enableAnalytics | boolean | |
autoDeploy | boolean | Deploy on push. |
env | EnvVar[] | { name, value }; secrets excluded. |
totalDeployments | number | |
successDeployments | number | |
failedDeployments | number | |
latestDeployment | object | null | { status, commitId, createdAt }. |
createdAt / updatedAt | string | null |
ProjectListItem (returned in lists) is a compact subset: id, name, slug, branch, repositoryName, organizationId, projectUrl, enabled, latestDeployment, updatedAt.
List projects
Section titled “List projects”GET /v1/projects
Cursor-paginated list of projects in the active org. Secrets are never returned.
Auth: any member.
Query params (ProjectListQuery):
| Param | Type | Required | Notes |
|---|---|---|---|
cursor | string | no | Opaque cursor from a prior nextCursor. |
limit | int | no | 1–100, default 50. |
slug | string | no | Filter by static or container. |
curl "https://api.pandastack.io/v1/projects?limit=20&slug=container" \ -H "Authorization: Bearer $PANDASTACK_TOKEN"{ "success": true, "data": { "items": [ { "id": 812, "name": "marketing-site", "slug": "static", "branch": "main", "repositoryName": "acme/marketing", "organizationId": "1907", "projectUrl": "https://marketing-site.pandastack.app", "enabled": true, "latestDeployment": { "status": "succeeded", "commitId": "a1b2c3d", "createdAt": "2026-07-14T10:00:00Z" }, "updatedAt": "2026-07-14T10:00:12Z" } ], "nextCursor": null }}Create a project
Section titled “Create a project”POST /v1/projects
Creates a project and triggers its first deploy. Static projects deploy fully; container projects need DNS and deploy asynchronously. A source scan runs at build time. The request body is a discriminated union on slug — pick static, container, or auto.
Auth: member.
slug: "static" — CreateStaticInput
Section titled “slug: "static" — CreateStaticInput”| Field | Type | Required | Notes |
|---|---|---|---|
slug | "static" | yes | Discriminator. |
name | string | yes | RFC-1123 label: lowercase letters, numbers, hyphens; 1–63 chars. |
repositoryName | string | yes | owner/repo. |
branch | string | no | Default main. |
baseDir | string | no | Default ./. |
buildDir | string | no | Default dist. |
buildCmd | string | no | Default npm run build. |
autoDeploy | boolean | no | Default false. |
prPreview | boolean | no | Default false. |
isPublic | boolean | no | Default true. |
enableAnalytics | boolean | no | Default false. |
env | EnvVar[] | no | Default []. |
secrets | EnvVar[] | no | Default []; stored base64, never returned. |
slug: "container" — CreateContainerInput
Section titled “slug: "container" — CreateContainerInput”| Field | Type | Required | Notes |
|---|---|---|---|
slug | "container" | yes | Discriminator. |
name | string | yes | RFC-1123 label. |
repositoryName | string | yes | owner/repo. |
branch | string | no | Default main. |
region | string | no | Default us. |
language | enum | yes | auto | nodejs | python | go | docker. |
isPublic | boolean | no | Default true. |
baseDir | string | no | Default ./. |
buildCmd | string | no | Default "". |
startCmd | string | no | Default "". |
entryPoint | string | no | Default "". |
healthCheckPath | string | no | Default /. |
dockerFilePath | string | no | Default ./Dockerfile. |
dockerBuildContextDir | string | no | Default ./. |
tier | { key: string } | no | Instance tier. |
disk | number | no | 0–100 GB, default 0. |
autoScaling | object | no | { enabled, minReplicas 1–50, maxReplicas 1–100, targetCpuPercent 1–100 }. |
autoDeploy | boolean | no | Default false. |
prPreview | boolean | no | Default false. |
enableAnalytics | boolean | no | Default false. |
env / secrets | EnvVar[] | no | Default []. |
slug: "auto" — CreateAutoInput
Section titled “slug: "auto" — CreateAutoInput”Let PandaStack detect static vs container from the repo. Same base fields as static/container but most build fields are optional overrides:
| Field | Type | Required | Notes |
|---|---|---|---|
slug | "auto" | yes | Discriminator. |
name | string | yes | RFC-1123 label. |
repositoryName | string | yes | owner/repo. |
branch | string | no | Default main. |
baseDir | string | no | Default ./. |
isPublic | boolean | no | Default true. |
autoDeploy / prPreview / enableAnalytics | boolean | no | Default false. |
env / secrets | EnvVar[] | no | Default []. |
buildCmd, buildDir, startCmd | string | no | Optional overrides. |
tier | { key: string } | no | |
disk | number | no | 0–100. |
autoScaling | object | no | See above. |
Response (CreateProjectResult):
| Field | Type | Notes |
|---|---|---|
projectId | number | |
name | string | |
deploymentId | number | First deploy row. |
deploymentUuid | string | Use to poll status / stream logs. |
curl -X POST https://api.pandastack.io/v1/projects \ -H "Authorization: Bearer $PANDASTACK_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "slug": "auto", "name": "my-app", "repositoryName": "acme/my-app", "branch": "main", "autoDeploy": true, "env": [{ "name": "NODE_ENV", "value": "production" }] }'{ "success": true, "data": { "projectId": 900, "name": "my-app", "deploymentId": 5501, "deploymentUuid": "d-8f3c2a1e" }}See Auto-detect deploys and Build & buildpacks.
Upload a static project (ZIP)
Section titled “Upload a static project (ZIP)”POST /v1/projects/static-upload
Create or re-upload a static project directly from a ZIP archive (no Git repo). The upload is content-abuse scanned, then stored in GCS.
Auth: member. Content-Type: multipart/form-data.
| Field | Type | Required | Notes |
|---|---|---|---|
staticFiles | file (ZIP) | yes | Max 30 MB. |
name | string | yes | RFC-1123 label. |
Response: { projectId, name, deploymentId, uploadId, liveUrl, fileCount }.
curl -X POST https://api.pandastack.io/v1/projects/static-upload \ -H "Authorization: Bearer $PANDASTACK_TOKEN" \ -F "name=my-static" \ -F "staticFiles=@site.zip"Check name availability
Section titled “Check name availability”GET /v1/projects/check-name
Auth: any member. Query: ?name=<candidate>. Response (NameAvailability): { name, available }.
curl "https://api.pandastack.io/v1/projects/check-name?name=my-app" \ -H "Authorization: Bearer $PANDASTACK_TOKEN"Get a project
Section titled “Get a project”GET /v1/projects/:name
Auth: any member. Returns the full ProjectDetail (see the project object).
curl https://api.pandastack.io/v1/projects/my-app \ -H "Authorization: Bearer $PANDASTACK_TOKEN"Delete a project
Section titled “Delete a project”DELETE /v1/projects/:name
Deletes the project and tears down its infrastructure. Static teardown is synchronous; container teardown is asynchronous via the worker.
Auth: admin. Response: { deleted: true, slug, async }.
curl -X DELETE https://api.pandastack.io/v1/projects/my-app \ -H "Authorization: Bearer $PANDASTACK_TOKEN"Rename a project
Section titled “Rename a project”PATCH /v1/projects/:name/name
Auth: member. Body (RenameProjectInput):
| Field | Type | Required | Notes |
|---|---|---|---|
name | string | yes | RFC-1123 label, 1–63 chars, ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$. |
Returns the updated ProjectDetail.
Update project config
Section titled “Update project config”PATCH /v1/projects/:name
Auth: member. Body (UpdateProjectInput) — all fields optional:
| Field | Type | Notes |
|---|---|---|
buildCmd | string | Max 2000. |
startCmd | string | Max 2000. |
baseDir | string | Max 500. |
buildDir | string | Max 500. |
healthCheckPath | string | Max 500. |
dockerFilePath | string | Max 500. |
disk | number | 0–1000. |
tier | { key: string } | Instance tier. |
autoScaling | object | { enabled, minReplicas 1–50, maxReplicas 1–100, targetCpuPercent 1–100 }. |
enableAnalytics | boolean | |
autoDeploy | boolean | |
env | EnvVar[] | Plaintext vars. |
secrets | EnvVar[] | Stored base64, never returned. |
Returns the updated ProjectDetail. See Autoscaling & scale-to-zero and Environment variables & secrets.
Enable / disable (pause) a static project
Section titled “Enable / disable (pause) a static project”POST /v1/projects/:name/toggle
Auth: member. Body (ToggleProjectInput): { "enable": boolean }. Returns ProjectDetail.
Roll back a project
Section titled “Roll back a project”POST /v1/projects/:name/rollback
Roll back to a previous deployment.
Auth: member. Body (RollbackInput): { "deploymentUuid": string }. Response: { deploymentUuid }.
curl -X POST https://api.pandastack.io/v1/projects/my-app/rollback \ -H "Authorization: Bearer $PANDASTACK_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "deploymentUuid": "d-previous-uuid" }'Deployments
Section titled “Deployments”Trigger a deploy
Section titled “Trigger a deploy”POST /v1/projects/:name/deploy
Triggers a deploy (create or redeploy), optionally at a specific commit. Writes a deployment row and an outbox event, then returns 202 (async).
Auth: member. Body:
| Field | Type | Required | Notes |
|---|---|---|---|
operation | string | no | Deploy operation hint. |
commitSha | string | no | Deploy a specific commit. |
Response: { deploymentId, deploymentUuid, projectId }.
curl -X POST https://api.pandastack.io/v1/projects/my-app/deploy \ -H "Authorization: Bearer $PANDASTACK_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "commitSha": "a1b2c3d4" }'Redeploy the current source
Section titled “Redeploy the current source”POST /v1/projects/:name/redeploy
Redeploys the current source; 202 async. Auth: member. Body: none. Response: { deploymentId, deploymentUuid, projectId }.
List deployments
Section titled “List deployments”GET /v1/projects/:name/deployments
Cursor-paginated list of a project’s deployments.
Auth: any member. Query (DeploymentListQuery): cursor (optional), limit (1–100, default 20).
Deployment object:
| Field | Type | Notes |
|---|---|---|
id | number | |
deploymentUuid | string | null | |
status | queued | running | succeeded | failed | string | |
commitId | string | null | |
commitSha | string | null | |
branch | string | null | |
enable | boolean | null | |
actor | object | { userId, name, username }. |
createdAt / updatedAt | string | null |
Get deployment status
Section titled “Get deployment status”GET /v1/deployments/:uuid/status
Read-once status of a deployment (the UI polls this).
Auth: any member. Response (DeploymentStatusInfo):
| Field | Type | Notes |
|---|---|---|
deploymentUuid | string | |
status | queued | running | succeeded | failed | string | |
terminal | boolean | true once the deploy has finished (succeeded or failed). |
commitId | string | null | |
branch | string | null | |
createdAt / updatedAt | string | null | |
projectName | string | null | |
repositoryName | string | null | |
projectUrl | string | null |
curl https://api.pandastack.io/v1/deployments/d-8f3c2a1e/status \ -H "Authorization: Bearer $PANDASTACK_TOKEN"Stream build logs
Section titled “Stream build logs”GET /v1/deployments/:uuid/logs/stream
Server-Sent Events stream of build logs. It replays history from Elasticsearch, tails live output, de-duplicates lines, and closes when the deploy reaches a terminal state (or after a 30-minute cap).
Auth: any member. Because this is SSE, pass the token (and org, for JWTs) as query params: ?access_token=<token>&organization_id=<orgId>. See SSE authentication.
Events emitted: log, system, status, done. Each log line matches the LogLine shape: { message, timestamp, stream } where stream is stdout | stderr | system.
curl -N "https://api.pandastack.io/v1/deployments/d-8f3c2a1e/logs/stream?access_token=$PANDASTACK_TOKEN&organization_id=1907"event: logdata: {"message":"Installing dependencies…","timestamp":"2026-07-14T10:00:03Z","stream":"stdout"}
event: statusdata: {"status":"running"}
event: donedata: {"status":"succeeded"}Custom domains
Section titled “Custom domains”Attach your own hostnames to a project. Domains are provisioned through Cloudflare custom hostnames (SSL-for-SaaS). Concept guide: Custom domains.
List custom domains
Section titled “List custom domains”GET /v1/projects/:name/domains
Auth: any member. Response: CustomDomain[].
Add a custom domain
Section titled “Add a custom domain”POST /v1/projects/:name/domains
Auth: member. Body: AddCustomDomainInput. Response: CustomDomain (returns DNS verification details to set at your registrar).
Verify a custom domain
Section titled “Verify a custom domain”POST /v1/domains/:domainId/verify
Re-checks a domain’s verification/SSL status.
Auth: any member. Response: CustomDomain.
Delete a custom domain
Section titled “Delete a custom domain”DELETE /v1/domains/:domainId
Auth: member. Response: { deleted: true }.
Redirects, rewrites & headers
Section titled “Redirects, rewrites & headers”Configure gateway routing rules per project. On containers these are synced to Kong. Concept guide: Redirects, rewrites & headers.
Get / set response headers
Section titled “Get / set response headers”GET /v1/projects/:name/headers (any member) — returns HeaderRule[].
PUT /v1/projects/:name/headers (member) — body SetHeadersInput; persisted to Postgres and Kong-synced for containers. Returns HeaderRule[].
Get / set redirects
Section titled “Get / set redirects”GET /v1/projects/:name/redirects (any member) — returns RedirectRule[].
PUT /v1/projects/:name/redirects (member) — body SetRedirectsInput; persisted to Postgres and Kong-synced. Returns RedirectRule[].
curl -X PUT https://api.pandastack.io/v1/projects/my-app/redirects \ -H "Authorization: Bearer $PANDASTACK_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "redirects": [{ "source": "/old", "destination": "/new", "status": 301 }] }'Related
Section titled “Related”- Metrics & analytics API — per-project performance and audience data.
- Databases API — link a database to a project.
- Integrations API — connect GitHub and marketplace services.