---
title: "Deploy App"
method: POST
path: "/apps/{id}/deploy"
tags: ["Apps"]
---

# Deploy App

`POST /apps/{id}/deploy`

Builds the app's current source and ships it. Returns the run it started, so the caller can render progress from this response and then follow it on the app's `deployment` field. Only one deployment runs per app at a time — calling this while one is in flight reports that run rather than starting a second, and calling it with nothing to publish reports that instead of starting one.

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `draft` boolean — Upload the build without making it live. Defaults to `false`, which deploys and promotes in one step.

## Response `200`

deployment started

- AppDeployment
  - `app_id` string, required — The app being deployed, prefixed `app_`.
  - `build_id` string, nullable, required — The build the deployment produced, prefixed `abld_`, or `null` until it succeeds.
  - `draft` boolean, required — Whether the running or last deployment uploaded a build without making it live.
  - `error` string, nullable, required — Why the deployment failed, or `null` when it did not.
  - `estimated_duration_ms` integer, nullable, required — How long this deployment is expected to take in total, estimated from previous runs.
  - `estimated_remaining_ms` integer, nullable, required — How much longer the deployment is expected to take. Held above zero until it actually finishes.
  - `finished_at` integer, nullable, required — When the deployment ended, in milliseconds since the epoch, or `null` while it is still running.
  - `phase` 'install' | 'build' | 'typecheck' | 'upload_build' | 'upload_source' | 'process_archive' | 'create_build' | 'promote' | 'null', nullable, required — The stage a running deployment has reached, or `null` when none is running. Later phases dominate the wall clock: `process_archive` waits on the upload pipeline and `promote` waits for the build to go live.
  - `progress` number, nullable, required — Fraction of the deployment estimated to be complete, from 0 to 1. Stops just short of 1 until the run ends.
  - `started_at` integer, nullable, required — When the deployment began, in milliseconds since the epoch, or `null` when none has run.
  - `status` 'published' | 'unpublished' | 'publishing' | 'failed' | 'no_source', required — Whether the app has anything to publish, and what a publish in flight is doing. `unpublished` means publishing would ship something new; `no_source` means the sandbox holds no copy of this app, so there is nothing to publish from.
  - `url` string, nullable, required — Where the deployed site is served, or `null` unless the deployment went live.

## Other responses

- `404` — Resource not found
- `409` — Conflict

---

[API](https://skmtc.net/whop/apis/whop-api.md) · [All operations](https://skmtc.net/whop/apis/whop-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/whop/whop-api/revisions/23dfbe1a0d1f/schema)
