Docs

Deploys API

Upload a release as a gzipped tar, control whether it is built, watch it go live, and roll back to an earlier one.

Updated October 12, 2026
On this page
  1. The release object
  2. List releases
  3. Upload a release
  4. Activate a release
  5. List releases across projects

A release is a gzipped tar of your project. Upload a static site and it goes live at once. Upload source without its node_modules and Fortly's build service installs and builds it first. Earlier releases are kept, so you can put one back without rebuilding. For how builds are detected and run, see Builds; for rollbacks, Releases.

GET/projects/{name}/deploysIts releases, newest first
POST/projects/{name}/deploysUpload a release
POST/projects/{name}/deploys/{id}/activateMake an earlier release live again
GET/deploysRecent releases across all your projects

The release object

idstring
The release id, dpl_ followed by 32 hex characters.
projectstring
The project's name.
account_idstring
The account that made the release.
created_atinteger
When it was uploaded, Unix seconds.
filesinteger
Files in the unpacked archive.
bytesinteger
Unpacked size, in bytes.
cmdstring
The start command recorded on the release. fortly static for a site served as files.
statestring
building, ready, live, superseded (was live, replaced by a newer one), failed, or gone (cleaned up).
sourcestring | null
upload or github.
shastring | null
For a repository deploy, the commit. repo and branch likewise.
buildstring | null
What ran before it went live, such as npm ci && npm run build. null when nothing was built.
project_idstring | null
The project's permanent id, prj_….
runtime_typestring | null
How it is served: static or fortly.
frameworkstring | null
The framework detected at build time, such as Next.js.
started_atinteger | null
When the build began.
finished_atinteger | null
When the build finished, either way.
activated_atinteger | null
When it became live.
failurestring | null
Why a failed release failed, in one line. The full output is in the project's log.
spa_fallbackboolean
For a static site, whether unmatched paths are answered with index.html.

The object also carries build provenance fields — execution_engine, artifact_root, manifest_path, source_digest, builder_image, builder_image_digest, build_digest and build_artifact_kind — which are null when not recorded.

List releases

GET/projects/{name}/deploysIts releases, newest first

Returns the project's 50 most recent releases, newest first.

namestringRequired
Path parameter. The project's name.
Terminal
curl https://api.fortly.com/projects/my-app-ada/deploys \
  -H "Authorization: Bearer $FORTLY_TOKEN"
JSON
{
  "deploys": [
    {
      "id": "dpl_3f9c2a71d04e4b8c9a6e5d1f2b7c8a90",
      "project": "my-app-ada",
      "account_id": "8b1e4f0c2d6a4e7f9c3b5a1d0e2f4c6b",
      "created_at": 1791820800,
      "files": 214,
      "bytes": 1893422,
      "cmd": "next start",
      "state": "live",
      "source": "upload",
      "sha": null,
      "repo": null,
      "branch": null,
      "build": "npm ci && npm run build",
      "project_id": "prj_0d4e7a9b1c2f4e6a8b0c3d5e7f9a1b2c",
      "runtime_type": "fortly",
      "execution_engine": null,
      "framework": "Next.js",
      "artifact_root": "accounts/8b1e4f0c2d6a4e7f9c3b5a1d0e2f4c6b/projects/prj_0d4e7a9b1c2f4e6a8b0c3d5e7f9a1b2c/",
      "manifest_path": "accounts/8b1e4f0c2d6a4e7f9c3b5a1d0e2f4c6b/projects/prj_0d4e7a9b1c2f4e6a8b0c3d5e7f9a1b2c/deployments/dpl_3f9c2a71d04e4b8c9a6e5d1f2b7c8a90/manifest.json",
      "started_at": 1791820801,
      "finished_at": 1791820839,
      "activated_at": 1791820840,
      "failure": null,
      "spa_fallback": false,
      "source_digest": null,
      "builder_image": null,
      "builder_image_digest": null,
      "build_digest": null,
      "build_artifact_kind": null
    }
  ]
}

Upload a release

POST/projects/{name}/deploysUpload a release

The body is the archive itself — a gzipped tar of the project, sent raw rather than as a multipart form.

What can go live:

  • A static site. A folder with an index.html at its root and no package.json, or a build whose output has an index.html in out, .output/public, dist, build or _site.
  • A Next.js or Nuxt server app, built by Fortly. Upload the source without node_modules (or send x-fortly-build: force). The build service builds it and the result runs on the Fortly runtime.

Server output that Fortly's build service did not build, such as a server packed with its own node_modules or one you built yourself, is refused. So is any server framework or runtime Fortly cannot build. In both cases the live release stays as it is. See Builds.

namestringRequired
Path parameter. The project's name.
x-fortly-cmdheader
A start command to record on this release, as its cmd. Static sites and releases on the Fortly runtime do not run it; it only matters for releases from the older process runtime. A release must still have a start command from somewhere. When this header is absent, the project's cmd setting is used, and when that is empty too, the command is read from the files: a package.json start script, or fortly static for a site. If none of these gives one, the upload is refused with 400, so you rarely need to send this header.
x-fortly-buildheader
skip never builds: what arrived is what runs. force builds even when node_modules is already there. Absent, or any other value, builds only when dependencies are missing. off, none and false also mean skip; always also means force.
Terminal
# Source without node_modules: Fortly builds it
tar --exclude=node_modules --exclude=.git -czf release.tgz .

curl -X POST https://api.fortly.com/projects/my-app-ada/deploys \
  -H "Authorization: Bearer $FORTLY_TOKEN" \
  --data-binary @release.tgz

# x-fortly-build: force   build even if node_modules is in the archive
# x-fortly-build: skip    never build; serve what arrived

What the status means:

  • 201 Created — nothing needed building, and the release is already live. This is the answer for a static site uploaded ready to serve.
  • 202 Accepted — the release is building. The response comes back straight away with "building": true; the build continues and narrates itself in the project's log. Poll List releases until this release's state is no longer building.
JSON
{
  "deploy": {
    "id": "dpl_7a1b3c5d7e9f4a2b8c6d0e1f3a5b7c9d",
    "project": "my-app-ada",
    "account_id": "8b1e4f0c2d6a4e7f9c3b5a1d0e2f4c6b",
    "created_at": 1791824400,
    "files": 38,
    "bytes": 51230,
    "cmd": "next start",
    "state": "building",
    "source": "upload",
    "sha": null,
    "repo": null,
    "branch": null,
    "build": "npm ci && npm run build",
    "project_id": "prj_0d4e7a9b1c2f4e6a8b0c3d5e7f9a1b2c",
    "runtime_type": null,
    "execution_engine": null,
    "framework": null,
    "artifact_root": null,
    "manifest_path": null,
    "started_at": null,
    "finished_at": null,
    "activated_at": null,
    "failure": null,
    "spa_fallback": false,
    "source_digest": null,
    "builder_image": null,
    "builder_image_digest": null,
    "build_digest": null,
    "build_artifact_kind": null
  },
  "url": "https://my-app-ada.fortly.com",
  "building": true
}

A 201 has the same shape without building, and the release's state is live.

A build that fails, or one whose output cannot be served, leaves the live release exactly where it was. The new release's state becomes failed, and failure says why.

When an upload that needed no build turns out to need a server Fortly cannot run, the refusal comes back on the request itself as 400. The body includes unsupported_runtime: true, which tells it apart from a broken archive. Fix it by deploying something else, not by retrying:

JSON
{
  "error": "This upload looks like it needs a server, but it wasn't built through Fortly's own build pipeline, so there's nothing safe to run it with. Deploy your project's source (upload it or link a repository) instead of a pre-built output folder, and Fortly will build and run it for you. Static sites deploy as usual; existing deployments are unaffected.",
  "unsupported_runtime": true
}
StatusWhen
400The archive could not be unpacked (it is not a gzipped tar, a path escapes the archive root, or it is over the limits below), or no start command could be found, or what arrived needs a server Fortly cannot run (unsupported_runtime: true). error says which.
409Another release of this project is still building. Wait for it to finish.
413The archive is over 256 MB.

Limits: the upload may be 256 MB, and it may unpack to 2 GB across at most 50,000 files.

Activate a release

POST/projects/{name}/deploys/{id}/activateMake an earlier release live again

Makes an earlier release the live one. Nothing is rebuilt: the release is served as it was built when it was made. The edge cache for the project is cleared.

namestringRequired
Path parameter. The project's name.
idstringRequired
Path parameter. The release id, from List releases.
Terminal
curl -X POST https://api.fortly.com/projects/my-app-ada/deploys/dpl_3f9c2a71d04e4b8c9a6e5d1f2b7c8a90/activate \
  -H "Authorization: Bearer $FORTLY_TOKEN"

Answers 200 with the release, now live:

JSON
{
  "deploy": {
    "id": "dpl_3f9c2a71d04e4b8c9a6e5d1f2b7c8a90",
    "project": "my-app-ada",
    "state": "live",
    "activated_at": 1791828000,
    "cmd": "next start",
    "created_at": 1791820800
  }
}

The deploy object is complete; it is shortened here.

StatusWhen
404No release with this id among the project's 200 most recent.
410The release is building, failed or gone, or its files have been cleaned up, so it cannot be made live.

List releases across projects

GET/deploysRecent releases across all your projects

The 20 most recent releases of each project you can access, merged and sorted newest first, up to 100 in all. Each item is a release object; its project field says which project it belongs to.

Terminal
curl https://api.fortly.com/deploys \
  -H "Authorization: Bearer $FORTLY_TOKEN"
JSON
{
  "deploys": [
    { "id": "dpl_7a1b3c5d7e9f4a2b8c6d0e1f3a5b7c9d", "project": "my-app-ada", "state": "live", "created_at": 1791824400 },
    { "id": "dpl_3f9c2a71d04e4b8c9a6e5d1f2b7c8a90", "project": "my-app-ada", "state": "superseded", "created_at": 1791820800 }
  ]
}

Items are shortened here; each is a complete release object.

Something missing or unclear? Tell us and we will fix the page.© 2026 Fortly