Skip to content
Coritan Docs

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.

View as Markdown

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.

  • Send your access token as Authorization: Bearer $CORITAN_TOKEN (Authentication). Each request takes the app's uuid, which GET /api/v1/client/apps lists.
  • 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).

A 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, in git_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, in git_ref. A bare tag name, such as v1.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 API

POST /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.
Shell
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:

JSON
{
  "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.

A 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}:

Shell
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.

A 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:

Shell
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).

You 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:

Shell
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.

GET /api/v1/client/apps/{app_uuid}/deployments lists the app's releases, newest first:

Shell
curl "https://api.coritan.com/api/v1/client/apps/3c9e2f4a-8b1d-4f6e-a2c7-5d8b9e0f1a21/deployments?limit=20&offset=0" \
  -H "Authorization: Bearer $CORITAN_TOKEN"
JSON
{
  "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.

The 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.

The 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 in git_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.

API operations on this page

MethodPathWhat it does
GET/api/v1/client/apps/{app_uuid}/deploymentsList an app's releases, newest first, a page at a time
POST/api/v1/client/apps/{app_uuid}/deploymentsDeploy a branch or an image, which starts a release
POST/api/v1/client/apps/{app_uuid}/deployments/{deployment_uuid}/cancelCancel a release that is still queued, building or deploying
POST/api/v1/client/apps/{app_uuid}/redeployStart a release from the live release or from the branch again
GET/api/v1/orgs/{org_slug}/apps/{app_uuid}/deploymentsList an app's releases, newest first, a page at a time
POST/api/v1/orgs/{org_slug}/apps/{app_uuid}/deploymentsDeploy a branch or an image, which starts a release
POST/api/v1/orgs/{org_slug}/apps/{app_uuid}/deployments/{deployment_uuid}/cancelCancel a release that is still queued, building or deploying
POST/api/v1/orgs/{org_slug}/apps/{app_uuid}/redeployStart a release from the live release or from the branch again