Project
Covers 8 API operations in the projects category.
| Method | Path | Description |
|---|---|---|
| GET | /v1/orgs/{orgSlug}/projects | — |
| POST | /v1/orgs/{orgSlug}/projects | Create a project |
| GET | /v1/orgs/{orgSlug}/projects/{projectName} | — |
| PATCH | /v1/orgs/{orgSlug}/projects/{projectName} | Rename a project (runlot project rename) |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName} | Delete a project (runlot project delete) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/overview | Project overview (dashboard home) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/disable | Disable a project (keeps its data) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/enable | Enable a disabled project |
GET /v1/orgs/{orgSlug}/projects
operationId listProjects
| Status code | Description | Response body |
|---|---|---|
| 200 | The organization's projects | object |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects
Creating a project also issues its default hostname. Nothing is running yet — the project starts serving at its first deployment.
The plan's project limit is enforced here, and concurrent creates cannot exceed it.
operationId createProject
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 201 | The created project | Project |
| 403 | — | — |
| 409 | The name is already taken (project_name_taken, hostname_taken), or the plan's project limit has been reached (project_limit). The details of project_limit is {limit, count, plan} — read the numbers from there rather than parsing the message. It is 409 because retrying will not change the outcome. | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}
operationId getProject
| Status code | Description | Response body |
|---|---|---|
| 200 | The project | ProjectDetail |
| 403 | — | — |
| 404 | — | — |
PATCH /v1/orgs/{orgSlug}/projects/{projectName}
Requires admin or higher. Audited as project.rename, with the old name in
detail.from.
Unlike the org slug, a project name can change. It is the label inside the
*.<slug>.runlot.app wildcard, so the existing certificate already covers the new
name and only the project's default hostname moves. Custom domains are untouched.
No stored data moves. Your database, object storage, generation chains, usage, secrets, and git repository all stay exactly where they are.
What breaks are the copies outside: the name in everyone's runlot.json,
registered git remotes, and Postgres connection strings already pasted into configs.
The old address is not kept as an alias. The response carries the new addresses.
The project's email address does not follow. It is fixed when the grant is made, because the outside world already sends mail there. Revoke and re-grant to move it.
operationId updateProject
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 200 | The renamed project, with its new addresses | Project |
| 400 | — | — |
| 403 | — | — |
| 404 | — | — |
| 409 | Another project in this org already has that name (project_name_taken), or the hostname it would take is already in use (hostname_taken). A project that is being deleted answers project_deleting. | Error |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}
Requires admin or higher. This cannot be undone, and there is no recovery
generation to restore from afterwards. Export anything you need first with
runlot pg export.
The confirm field must carry the exact project name.
The project is gone when this call returns. It disappears from the project list,
from GET, from git, and from mail, and its name is free to use again immediately.
There is nothing to poll and nothing to wait for.
Behind that, deletion runs in two steps. The first cuts routing and drains in-flight
requests, so the address stops answering within seconds. The second destroys the data —
database files, object storage, repositories, bundles, and records — and does not run
until purgeAfter, one month later by default. Nothing in that window is reachable by
anyone, and there is no way to bring it back.
The 202 carries an operation id you can read with
GET /v1/orgs/{orgSlug}/operations/{opId}, which reports the first step. Clients
should not block on it.
operationId deleteProject
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 202 | Deletion started | OperationStarted |
| 400 | — | — |
| 403 | — | — |
| 404 | — | — |
| 409 | Another operation is in progress (op_in_flight) | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/overview
Everything the project's home screen needs in one call — the deployment currently serving and who uploaded it, a handful of recent deployments, the database's last backup, whether declared resources have been provisioned, and recent notifications for this project. This answers "how is it right now", not history — the tabs cover that.
Usage is not included; call getUsage alongside it. Requires viewer or higher.
operationId getProjectOverview
| Status code | Description | Response body |
|---|---|---|
| 200 | The project overview | ProjectOverview |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/disable
Requires admin or higher. The project stops serving and stops taking new backups.
Nothing is deleted: the database, files, repositories and the backups already
taken all stay, and enableProject brings it back. A disabled project does not count
toward the plan's project limit, so this is how an organization that holds more
projects than its plan allows gets its deploys back.
A project left disabled for one year is deleted permanently at deleteAfter.
Calling this on a disabled project changes nothing. Audited as project.disable.
operationId disableProject
| Status code | Description | Response body |
|---|---|---|
| 200 | The project's disabled state | ProjectDisabled |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/enable
Requires admin or higher. The project serves again and backups resume. Audited as
project.enable.
operationId enableProject
| Status code | Description | Response body |
|---|---|---|
| 200 | The project's disabled state | ProjectDisabled |
| 403 | — | — |
| 404 | — | — |
| 409 | project_limit — the organization already has as many active projects as its plan allows. Disable or delete another one first, or upgrade. | Error |