Projects API
List, create, configure and delete projects, check whether a name is free, and read the regions a project can be set to.
A project is one app with its own address, PostgreSQL database, files, secrets, domains and schedules. These routes manage the project itself; what it runs is on Deploys. Every route needs a token except List regions.
/ projectsEvery project you can access/ projectsCreate a project/ projects/ availableCheck whether a name is free/ projects/ suggestGet a generated name nobody is using/ projects/ {name}Change its region, start command or Dockerfile setting/ projects/ {name}Delete it and everything in it/ regionsThe regions a project can be set toThe project object
Every route that returns a project returns this shape.
namestringmy-app-ada.labelstringmy-app.hoststringurlstringstatestringrunning while the project has a process of its own running, stopped otherwise. A static site, or a release served by the Fortly runtime, has no process of its own and reads stopped while it serves normally.cache_enabledbooleancache_ttlinteger60.regionstringus-central.cmdstringignore_dockerfilebooleanruntimestring | nullcmd: Node, Static, Python, Ruby, Go, PHP, Java or Rust. null when not recognised.db_bytesintegerfiles_countintegerfiles_bytesintegerliveobject | nullid, created_at, files, bytes. null before the first release.ownerobject | nullid and email.List projects
/ projectsEvery project you can accessReturns your own projects and those of every team you belong to, sorted by name.
curl https://api.fortly.com/projects \
-H "Authorization: Bearer $FORTLY_TOKEN"const res = await fetch("https://api.fortly.com/projects", {
headers: { Authorization: `Bearer ${process.env.FORTLY_TOKEN}` },
});
const { projects } = await res.json();{
"projects": [
{
"name": "my-app-ada",
"label": "my-app",
"host": "my-app-ada.fortly.com",
"url": "https://my-app-ada.fortly.com",
"state": "running",
"cache_enabled": true,
"cache_ttl": 60,
"region": "us-central",
"cmd": "next start",
"ignore_dockerfile": false,
"runtime": null,
"db_bytes": 8028160,
"files_count": 12,
"files_bytes": 3481920,
"live": {
"id": "dpl_3f9c2a71d04e4b8c9a6e5d1f2b7c8a90",
"created_at": 1791820800,
"files": 214,
"bytes": 1893422
},
"owner": { "id": "8b1e4f0c2d6a4e7f9c3b5a1d0e2f4c6b", "email": "ada@example.com" }
}
]
}Create a project
/ projectsCreate a projectCreates an empty project with a database and an address. Nothing is served until its first release.
namestringRequiredcurl -X POST https://api.fortly.com/projects \
-H "Authorization: Bearer $FORTLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"my-app"}'const res = await fetch("https://api.fortly.com/projects", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FORTLY_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ name: "my-app" }),
});
const project = await res.json(); // project.name is what every other route takesAnswers 201 with the new project:
{
"name": "my-app-ada",
"label": "my-app",
"host": "my-app-ada.fortly.com",
"url": "https://my-app-ada.fortly.com",
"state": "stopped",
"cache_enabled": true,
"cache_ttl": 60,
"region": "us-central",
"cmd": "",
"ignore_dockerfile": false,
"runtime": null,
"db_bytes": 0,
"files_count": 0,
"files_bytes": 0,
"live": null,
"owner": { "id": "8b1e4f0c2d6a4e7f9c3b5a1d0e2f4c6b", "email": "ada@example.com" }
}| Status | When |
|---|---|
400 | The name breaks a rule above, or is reserved by the platform (api is one). |
403 | Your plan's project limit is reached. Fortly Starter and Pro do not limit projects. |
409 | You already have a project with this name. The body includes a free suggestion. |
429 | Projects are being created too quickly on this account. See Retry-After. |
{
"error": "you already have a project called my-app",
"suggestion": "my-app-2"
}Check a name
/ projects/ availableCheck whether a name is freeSays whether you could create a project with this name, and if not, a near one you could. It checks only your own projects; another account's my-app does not stand in your way.
namestringRequiredcurl "https://api.fortly.com/projects/available?name=my-app" \
-H "Authorization: Bearer $FORTLY_TOKEN"const res = await fetch(
`https://api.fortly.com/projects/available?name=${encodeURIComponent("my-app")}`,
{ headers: { Authorization: `Bearer ${process.env.FORTLY_TOKEN}` } },
);
const { available, suggestion, host } = await res.json();{
"available": false,
"suggestion": "my-app-2",
"host": "my-app-2-ada.fortly.com"
}host is the address the suggested name would be published at. A name that breaks the naming rules answers 200 with the reason instead:
{
"available": false,
"problem": "a project name can use lower-case letters, digits and hyphens"
}Suggest a name
/ projects/ suggestGet a generated name nobody is usingReturns a generated name of two words and a number that none of your projects uses.
curl https://api.fortly.com/projects/suggest \
-H "Authorization: Bearer $FORTLY_TOKEN"const res = await fetch("https://api.fortly.com/projects/suggest", {
headers: { Authorization: `Bearer ${process.env.FORTLY_TOKEN}` },
});
const { name } = await res.json();{ "name": "winter-harbor-24" }Update a project
/ projects/ {name}Change its region, start command or Dockerfile settingChanges only the fields you send. Nothing is restarted.
namestringRequiredname.regionstringcmdstringx-fortly-cmd. Static sites and releases on the Fortly runtime do not run it. An empty string clears it, and the command is then detected from each release.ignore_dockerfilebooleantrue to stop reading the project's Dockerfile when it is built.Fortly runs the start command directly, not through a shell. A command containing |, &, ;, <, >, a backtick, parentheses, quotes or * is refused with 400, and so is one that starts with a VAR=value assignment. Put the shell part in a script your project ships and name the script here.
curl -X PATCH https://api.fortly.com/projects/my-app-ada \
-H "Authorization: Bearer $FORTLY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"cmd":"next start","region":"eu-west"}'const res = await fetch("https://api.fortly.com/projects/my-app-ada", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.FORTLY_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ cmd: "next start", region: "eu-west" }),
});
const project = await res.json();Answers 200 with the updated project. In this response files_count and files_bytes are always 0; read them from List projects.
Delete a project
/ projects/ {name}Delete it and everything in itStops the project and removes its releases, database, files, secrets, domains and schedules, including the copies in object storage. The name becomes free for anyone.
There is no undo. Export the database first if you might want it.
namestringRequiredname.Only the account owner or a team admin can delete a project; a member gets 403.
curl -X DELETE https://api.fortly.com/projects/my-app-ada \
-H "Authorization: Bearer $FORTLY_TOKEN"await fetch("https://api.fortly.com/projects/my-app-ada", {
method: "DELETE",
headers: { Authorization: `Bearer ${process.env.FORTLY_TOKEN}` },
});Answers 204 No Content. A 502 means object storage did not confirm the removal; send the request again.
List regions
/ regionsThe regions a project can be set toThe fixed list of region ids Update a project accepts, and the default. Needs no token.
curl https://api.fortly.com/regionsconst { regions, default: fallback } = await (await fetch("https://api.fortly.com/regions")).json();{
"regions": [
{ "id": "us-central", "name": "US Central", "city": "Dallas", "country": "United States", "area": "North America" },
{ "id": "us-east", "name": "US East", "city": "Ashburn", "country": "United States", "area": "North America" }
],
"default": "us-central"
}The ids are us-central, us-east, us-west, ca-central, sa-east, eu-west, eu-central, eu-north, uk-south, ap-south, ap-southeast, ap-northeast and au-southeast.
A region is recorded on the project and every release inherits it. Changing it does not move or restart a running project.