Project
Covers 5 API operations in the projects category.
| Method | Path | Description |
|---|---|---|
| GET | /v1/orgs/{orgSlug}/projects | — |
| POST | /v1/orgs/{orgSlug}/projects | Creates a project |
| GET | /v1/orgs/{orgSlug}/projects/{projectName} | — |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName} | Delete a project (runlot project delete) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/overview | Project overview (dashboard home) |
GET /v1/orgs/{orgSlug}/projects
operationId listProjects
| Status code | Description | Response body |
|---|---|---|
| 200 | Org's projects | object |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects
Creating a project also issues a hostname. Assignments are not created yet — they are created at the first deployment. Assigning a node to a project with no code starts a process with nothing to serve.
The project count limit is enforced here (docs/limits.md §2). It locks and counts the org row, so concurrent creation cannot exceed the limit.
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 exceeded (project_limit). The details of project_limit is {limit, count, plan} — parsing the number out of the message with a regex would silently break the day the wording is polished. It is 409 because retrying will not change the outcome (403 means permission, 429 means retrying after a wait will work). | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}
operationId getProject
| Status code | Description | Response body |
|---|---|---|
| 200 | Project | ProjectDetail |
| 403 | — | — |
| 404 | — | — |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}
Requires admin or higher. This cannot be undone and leaves no recovery generation.
With no project
to go back to, the pre-delete generation becomes a blob nobody can use.
Export any data you need first with runlot pg export.
The confirm field must carry the exact project name. The server checks this for the
same reason
as org deletion — three callers hit this surface: the dashboard, the CLI, and scripts.
Teardown proceeds in order: routing, then in-flight requests and commits, then node data
and object storage, then git repositories
and backups, then metadata. 202 means it started;
check completion with GET /v1/orgs/{orgSlug}/operations/{opId}.
operationId deleteProject
Request body: application/json · object
| Status code | Description | Response body |
|---|---|---|
| 202 | Started a teardown operation | OperationStarted |
| 400 | — | — |
| 403 | — | — |
| 404 | — | — |
| 409 | Another operation is in progress (op_in_flight) | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/overview
What the overview screen fetches in one call when you open a project — 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 give you all of that.
Usage is not here. cp-core computes it over a window, so call getUsage
alongside it — bundling it into one response means the whole overview
waits that much longer on a slow day for cp-core. viewer or above.
operationId getProjectOverview
| Status code | Description | Response body |
|---|---|---|
| 200 | Overview | ProjectOverview |
| 403 | — | — |
| 404 | — | — |