Deploy an app with the Apps API
Deploy a branch, tag or commit of a git app or a new image with the Apps API, rebuild or redeploy to apply changes, and cancel a release.
In the Apps API, each version of an app is a release, which the API names deployment in its paths and objects. Deploy a branch to ship a new version: a branch, a tag or a commit of a git app, or an image reference for an image app. Rebuild to build the branch again, and redeploy to run the live release again with the settings the app has now. Each release goes live only once its replicas are healthy, and the live release serves until then (Releases).
In the dashboard, the same releases are on the Releases tab of the app's page under App Deployment, with Deploy a branch…, Rebuild…, Redeploy… and Cancel release… (Deploy, promote and roll back releases). An app that runs an image reads Deploy an image… and Pull again…. This page covers the Apps API, which scripts written for Apps keep using.
Before you begin
Section titled Before you begin- Send your access token as
Authorization: Bearer $CORITAN_TOKEN(Authentication). Each request takes the app'suuid, whichGET /api/v1/client/appslists. - The app must be
active. The API refuses to deploy a suspended app. - For an organization's app, you need the owner or admin role in the organization, and you send the same requests under
/api/v1/orgs/{org_slug}/apps(organization apps reference). - A push webhook can deploy each push to the app's branch for you (Deploy on every push).
Choose what to deploy
Section titled Choose what to deployA git app builds the version you name:
- The app's branch
- The default. The build takes the newest commit on the branch when it starts.
- Another branch
- Its name, such as
release, ingit_ref. The app keeps its own branch for pushes and rebuilds. - A tag
- The full name of the tag, such as
refs/tags/v1.4.0, ingit_ref. A bare tag name, such asv1.4.0, is looked for as a branch and the build fails. - A commit
- Its full ID in
git_sha: 40 characters (64 in a repository that uses SHA-256), with or without a branch. A shorter ID is ignored, and the build takes the newest commit on the branch instead. We fetch the commit by its ID. If the host does not serve commits that way, we fetch the branch, and the build fails when the branch has moved past that commit.
An image app runs its saved image unless you name another reference in image_ref, such as ghcr.io/example/web:1.5.0. The reference you name runs for this release only, and the app keeps its saved image. To change the image the app keeps, change its image_ref (Change settings through the API).
Deploy a branch through the API
Section titled Deploy a branch through the APIPOST /api/v1/client/apps/{app_uuid}/deployments deploys a branch, a tag, a commit or an image, and starts a release. An empty body deploys the app's branch or its saved image.
git_ref- For a git app. A branch name, or a full ref such as
refs/tags/v1.4.0. The app's branch when left out. git_sha- For a git app. A commit's full ID.
image_ref- For an image app. The image to run this time. The app's saved image when left out.
curl -X POST https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/deployments \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"git_ref": "refs/tags/v1.4.0"}'
It answers 201 with the new release in deployment:
{
"deployment": {
"uuid": "0b6f3d2e-7a41-4c59-8e1d-2f9a6b3c4d5e",
"status": "queued",
"source": "git",
"trigger": "manual",
"git_ref": "refs/tags/v1.4.0",
"git_sha": null,
"image_ref": null,
"regions": null,
"error": null,
"is_current": false,
"in_flight": true,
"can_rollback": false,
"replicas": {"healthy": 0, "unhealthy": 0, "starting": 0, "total": 0},
"build": {"uuid": "e2a9c4d1-3b5f-4e7a-9c8d-1f2e3a4b5c6d", "status": "queued", "strategy": null, "attempts": 0},
"created_at": "2026-09-26T10:05:00Z"
}
}
The example leaves some fields out. App and release fields describes each one. regions stays null until the release starts placing replicas. Read a release and its build log shows how to follow it.
| Status | detail |
Cause |
|---|---|---|
409 |
{"error": "source_mismatch", "message": "This app runs an image. Deploy an image reference instead"} |
A branch or commit was sent for an image app, or an image for a git app. |
409 |
{"error": "app_not_active", "message": "The deployment is suspended; it cannot deploy"} |
The app is suspended. |
422 |
Give a branch or commit, or an image reference, not both |
The body held both. |
422 |
{"error": "repository_invalid", "message": "'release..x' is not a branch name git accepts."} |
git_ref, or the app's repository settings, cannot be fetched. |
422 |
{"error": "dockerfile_unsupported", "message": "Dockerfiles are not built on the platform. Build the image in your CI and deploy it as a container image."} |
The app still names a Dockerfile path. Clear dockerfile_path, or run the image as an image app (Dockerfile? Deploy a container image). |
429 |
{"error": "rate_limited", "message": "Too many releases of this app. Wait a few minutes.", "retry_after_seconds": 600} |
The app started 30 releases in the last 10 minutes. |
Rebuild
Section titled RebuildA rebuild builds the app's branch again, then replaces the live release once the new release is healthy. Use it after a change that only a new build applies: the repository, the branch, the directory, the access token, the build settings, or a variable the build reads, such as one whose name starts with NEXT_PUBLIC_. For an image app, a rebuild pulls the image the app keeps again, so after you change an image app's image, rebuild: a plain redeploy runs the image that is running now. The dashboard calls it Rebuild…, and Pull again… for an image app.
POST /api/v1/client/apps/{app_uuid}/redeploy starts it with {"rebuild": true}:
curl -X POST https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/redeploy \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"rebuild": true}'
It answers 201 with the new release, as above. The release has trigger rebuild and source git, or image for an image app, so a list says which releases a rebuild started.
Redeploy
Section titled RedeployA redeploy runs the live release again, with the app's settings as they are now. Nothing is built or pulled. Use it after a change that only the running replicas read: a variable the running app reads, or the size. The dashboard calls it Redeploy….
The same request, POST /api/v1/client/apps/{app_uuid}/redeploy, starts it with {"rebuild": false}. The body can be left out, which means the same:
curl -X POST https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/redeploy \
-H "Authorization: Bearer $CORITAN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"rebuild": false}'
It answers 201 with the new release. A redeploy has source redeploy and trigger manual, and starts as deploying. An app with nothing live yet has nothing to redeploy, so either request builds or pulls it afresh, and that release has the trigger manual.
Both requests refuse a suspended app, and both count towards the same limit of 30 releases in 10 minutes. After you change a setting, the answer to the change says whether a redeploy or a rebuild applies it (Change settings through the API).
Cancel a release
Section titled Cancel a releaseYou can cancel a release that is still queued, building or deploying. Its build stops, its replicas are removed, and its status becomes canceled. The live release goes on serving. A release that has finished cannot be cancelled.
POST /api/v1/client/apps/{app_uuid}/deployments/{deployment_uuid}/cancel cancels a release on its way, and answers with it, now canceled, and its replicas:
curl -X POST https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/deployments/0b6f3d2e-7a41-4c59-8e1d-2f9a6b3c4d5e/cancel \
-H "Authorization: Bearer $CORITAN_TOKEN"
A release that has finished answers 409 with The release is ready; only a release on its way can be canceled, naming its status. One that belongs to another app answers 404 with Release not found.
List releases
Section titled List releasesGET /api/v1/client/apps/{app_uuid}/deployments lists the app's releases, newest first:
curl "https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/deployments?limit=20&offset=0" \
-H "Authorization: Bearer $CORITAN_TOKEN"
{
"deployments": [
{"uuid": "0b6f3d2e-7a41-4c59-8e1d-2f9a6b3c4d5e", "status": "ready", "source": "git", "trigger": "manual", "is_current": true},
{"uuid": "8c4e1a7d-2f9b-4d6e-b3a8-6e1f9c2d5a10", "status": "superseded", "source": "git", "trigger": "push", "is_current": false}
],
"total": 14,
"limit": 20,
"offset": 0
}
limit takes 1–100 (20 when left out), offset skips that many releases, and total counts them all. Each release carries every field, shortened here, and is_current marks the live release. trigger says what started it: push, manual (a deploy of a branch, a tag, a commit or an image, a redeploy, an upload or a promotion), rebuild, rollback or deploy_hook. Status words explains each status. The list holds the app's previews too, and the Apps API does not mark them: the Releases tab says which releases are previews.
Result
Section titled ResultThe new release is first in the list, and first on the app's Releases tab in the dashboard. It moves to ready and serves the app once its replicas are healthy in every region, which the dashboard shows as Live. Or it ends as failed or canceled and the live release keeps serving.
Troubleshooting
Section titled TroubleshootingThe deployment is suspended; it cannot deploy- We suspended the app. Contact support to find out why.
This app builds from git. Deploy a branch or a commit instead- An image reference was sent for a git app. For an image app, the message says it runs an image.
git could not fetch v1.4.0 from https://github.com/example/web-shop.- The branch does not exist. For a tag, give its full name, such as
refs/tags/v1.4.0. For a commit, send its full ID ingit_sha. For a private repository, check that the access token can still read it. release has moved past commit 9f2c1e7b4a6d, and github.com does not serve an older commit by its id. Deploy the branch again.- The host would not send the commit by its ID, and the branch no longer ends at it. Deploy the branch, or push a branch that ends at that commit.
The release is ready; only a release on its way can be canceled- The release has finished. To stop serving it, deploy another version or roll back (Roll back to an earlier release).
Too many releases of this app. Wait a few minutes.- The app started 30 releases in the last 10 minutes. Wait, then deploy again.
Related
Section titled Related- Read a release and its build log
- Roll back to an earlier release
- Deploy on every push
- Deploy, promote and roll back releases, for the same in the dashboard
API operations on this page
| Method | Path | What it does |
|---|---|---|
GET | /api/v1/client/apps/{app_uuid}/deployments | List an app's releases, newest first, a page at a time |
POST | /api/v1/client/apps/{app_uuid}/deployments | Deploy a branch or an image, which starts a release |
POST | /api/v1/client/apps/{app_uuid}/deployments/{deployment_uuid}/cancel | Cancel a release that is still queued, building or deploying |
POST | /api/v1/client/apps/{app_uuid}/redeploy | Start a release from the live release or from the branch again |
GET | /api/v1/orgs/{org_slug}/apps/{app_uuid}/deployments | List an app's releases, newest first, a page at a time |
POST | /api/v1/orgs/{org_slug}/apps/{app_uuid}/deployments | Deploy a branch or an image, which starts a release |
POST | /api/v1/orgs/{org_slug}/apps/{app_uuid}/deployments/{deployment_uuid}/cancel | Cancel a release that is still queued, building or deploying |
POST | /api/v1/orgs/{org_slug}/apps/{app_uuid}/redeploy | Start a release from the live release or from the branch again |