Docs

API overview

How to authenticate to the Fortly HTTP API, what requests and responses look like, and how errors and limits are reported.

Updated October 12, 2026
On this page
  1. Base URL
  2. Authentication
  3. Project names in paths
  4. Requests
  5. Responses
  6. Errors
  7. Rate limits
  8. Pagination
  9. Retrying
  10. Resources

The Fortly API is plain HTTPS and JSON. It is the same API the console uses — every screen in the console is a view over these routes, so anything you can do there you can script here. This page covers what every route has in common; the pages under it list each route, its parameters and what it returns.

Base URL

https://api.fortly.com

All paths in this reference are relative to it. There is no version prefix.

Authentication

Send an API token as a bearer token on every request:

HTTP
GET /projects HTTP/1.1
Host: api.fortly.com
Authorization: Bearer fly_...

Make a token in the console under Settings › API tokens. It is shown once, when it is made; Fortly stores only a digest of it. See API tokens for expiry, renewal and rotation.

Terminal
export FORTLY_TOKEN=fly_...

curl https://api.fortly.com/projects \
  -H "Authorization: Bearer $FORTLY_TOKEN"

A token acts as the account that made it, with that account's access: its own projects and those of any team it belongs to. A missing token, or one that is expired or revoked, gets 401.

SituationStatuserror
No Authorization: Bearer header401sign in first
Token unknown, expired or revoked401that token is not valid, or has expired
Fortly could not check the token503could not check your session

A fly_ token can do anything its account can, including deleting projects. Keep it in server-side code and CI secrets, never in a browser. For a frontend, use the project's publishable cvp_ key with the frontend data API.

Project names in paths

Most routes are under /projects/{name}. {name} is the project's name field, which is the name you chose joined to your account's slug: a project you create as my-app gets the name my-app-ada if your slug is ada. The name you chose is returned as label. Read name from List projects or from the response to Create a project.

A project you cannot access answers 404 with no project called {name} — the same answer as a project that does not exist, so a name is never confirmed to someone outside it.

Requests

  • JSON bodies must be sent with Content-Type: application/json. Without it the request is refused with 415; a body that is not valid JSON is 400, and one that is missing a required field or has the wrong type is 422.
  • Binary bodies — a release archive, an uploaded file, a SQL import — are sent raw as the request body, not as a multipart form. Use --data-binary @file with curl.
  • Body size. JSON bodies are limited to 2 MB. The routes that take files have their own ceilings: 256 MB for a release, 64 MB for an uploaded file and 256 MB for a SQL import. A body over the limit is refused with 413.
  • Timestamps in requests and responses are Unix seconds (integers), UTC.

Responses

Successful responses are JSON with 200, 201 or 202, except:

  • Deletions answer 204 No Content with an empty body.
  • Export the database answers with the file itself and a Content-Disposition header naming it.

Lists are wrapped in an object named for what they hold — { "projects": [...] }, { "deploys": [...] } — so a field can be added beside the list later without breaking you.

Errors

An error from Fortly is a JSON object with an error string written to be shown to a person:

JSON
{ "error": "you already have a project called my-app" }

Some errors carry one more field that helps you recover; each route documents its own. For example, a name clash on Create a project also returns a free suggestion.

StatusMeaning
400The request was understood and refused. error says why, in the database's own words where the database refused it.
401No valid token.
403Your plan does not allow it, or your role in the team does not.
404The project, release, domain, file or schedule does not exist, or is not yours.
409It conflicts with something that exists: a project name you already use, a domain already on a project, a release already building.
410A release that can no longer be made live.
413The body is over the route's size limit.
415, 422A JSON body without Content-Type: application/json, or with the wrong shape. These come from the HTTP layer as plain text, not JSON.
429Too many requests of one kind. See Rate limits.
500Something on Fortly's side failed.
501The platform is not configured for this feature, such as storing secrets.
502, 503An upstream Fortly depends on — DNS, object storage, the node itself — did not answer. Safe to retry.

Rate limits

There is no general request quota. Creating a project is throttled per account, because every project claims a database on a shared server: it allows a burst of 8 and then one more every 5 seconds. A throttled request answers 429 with a Retry-After header in seconds:

HTTP
HTTP/1.1 429 Too Many Requests
Retry-After: 5
Content-Type: application/json

{"error":"Projects are being created too quickly on this account. Wait a moment and try again."}

Pagination

Lists return everything there is, except where a route says otherwise:

Retrying

There is no idempotency-key header. What a retry does depends on the route:

  • Creating something with a name — a project, a secret, a domain — is safe to retry. A second project with the same name answers 409; a secret with the same name is replaced; a domain already added answers 409.
  • Uploading a release twice makes two releases. The second becomes live, which is harmless when the archive is the same.
  • Updates and deletions by name or id are safe to repeat; a second deletion answers 404.

Resources

The routes above are for managing a project from outside it. From inside a running project, your server reads and writes its own database through the server data API, and a browser through the frontend data API.

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