Skip to content
esc

Search pages and sections. Try a tool name, an error code, a route.

↑↓ navigate↵ openesc close

API reference · Management plane

Projects

Create, read, rename, export and delete projects, and read their usage.

Host: https://api.manybases.com · Key: ak_. Two gestures also require a signed-in human (X-Account-Session).

GET/v1/projects
Toollist_projects
EffectThe projects the key's scope allows: { id, name, plan, region, app_url, seats: { used, cap, as_of }, created_at, status, urls: { api } }. seats.used and seats.as_of can be null — see "A dated reading". Paginated: limit defaults to 50, maximum 200, and cursor reads the next page, newest project first.
POST/v1/projects { name, plan? }
Toolcreate_project
Effect201 with the project card. Provisions a real database and a file bucket (about 6 s). Requires a key with the "every project" scope; 402 quota_exceeded when the account's app limit is reached (Free: 2, Builder: 20, Studio: 100). plan is ignored: the plan is the account's
GET/v1/projects/:pid
Toolget_project
EffectThe card plus tables (a count), urls.api — the host of the project's data plane — and urls.site, the site's address. Its figures are the last reading, with its date: reading the card measures nothing — see "A dated reading"
PATCH/v1/projects/:pid { name?, app_url? }
Toolset_app_url
EffectRename, and declare the app's URL. app_url is https:// only, in canonical form with its trailing slash (https://my-app.example/), or null to clear it. Changing app_url requires a signed-in human and confirms in two steps; name alone requires nothing
GET/v1/projects/:pid/usage
Toolget_usage
EffectUsage and quotas — see below
GET/v1/projects/:pid/export
Tool—
EffectA zip. Requires a signed-in human. See Export
DELETE/v1/projects/:pid
Tooldelete_project
EffectDeletes the project and its tables, rows, users, spaces, files, keys, functions and site. Requires a signed-in human and confirms in two steps. Frees the account's app slot

The project card#

plan is the account's plan — free, personal (the Builder plan) or studio — and sets the seat cap (3 on Free, 1 000 on Builder and Studio). region is where the data lives — weur, Cloudflare's Western Europe region — fixed at creation. status has three values on the wire:

  • provisioning — resources are being created. Export and delete answer 409 meanwhile.
  • active — nominal.
  • suspended — the account is above a volume quota (file storage, database size, or requests of the UTC month). Reads keep serving; every write on the data plane answers 402 quota_exceeded. The status is set and lifted by an hourly job, never by a request. Management keeps working: card, rename, keys, export and delete — deleting an app is the way out of an overage, and it is never locked. See Limits.

A project being deleted no longer appears in the list, and its card answers the neutral 404.

The app URL#

app_url is the public address of the app. Invitation links are built from it, and the first deployment of a site fills it in when it is empty. Because changing it redirects every user of the app, a chosen value only enters through a signed-in human and a confirmation: the first PATCH answers 428 with a confirmation_token; the second, same body plus token, applies. Deploying a site never replaces an existing value; taking a site down clears the app URL only if it still pointed at that site. See Sites.

A dated reading#

No route measures anything: list_projects, get_project and get_usage return the platform's last reading of the project, with its as_of. The platform refreshes that reading on its own, every five minutes, a few projects at a time, whether or not anyone asks; creating a project records zeros, which are true. A project never observed returns null for these figures, with a hint — never a 0, which would read "this project is empty". No call refreshes them.

Usage#

GET /v1/projects/:pid/usage returns:

json
{ "data": {
    "storage_bytes": 12345, "db_bytes": 67890, "rows": null,
    "requests_month": 1200,
    "seats": { "used": 2, "cap": 3, "as_of": "2026-09-04T10:00:00Z" },
    "quotas": { "storage_bytes": …, "db_bytes": …, "requests_month": … },
    "as_of": "2026-09-04T10:00:00Z"
} }
  • storage_bytes, db_bytes, rows and seats come from the last observation, with as_of. db_bytes is the size of the database file as the platform reports it, which can lag behind the latest writes. rows is not measured: it is 0 right after creation, then null.
  • requests_month is the account's total for the current UTC month, served on a project route on purpose: the quota is counted account-wide. It counts data-plane requests carrying a valid key; replays and authentication refusals are excluded. The window reopens on the 1st of the month; deleting projects never resets it.
  • quotas are the plan's limits, not a reading.
  • Anything the API cannot derive is null, with a hint saying so.

The app limit#

The Free plan allows 2 apps, Builder 20 and Studio 100. The limit counts existing projects, never the historical total: deleting one frees its slot immediately. POST /v1/projects beyond the limit answers 402 quota_exceeded with the figure and the two exits — delete an app, or upgrade. An account that comes back down to Free keeps its projects; the ones beyond the limit, in creation order, switch to read-only until the account is back under.

Export#

GET /v1/projects/:pid/export returns a zip with dump.sql (schema and data, restorable elsewhere), the project's files and a manifest.json that lists the tables, their presets, and the internal tables the archive deliberately leaves out. It requires a signed-in human, and the refusal comes before the ownership check — an agent alone gets the same 401 whether the project exists or not. Details and the current bound on the number of files: Export.

Deleting a project#

Two gates, in this order: X-Account-Session (without it 401, no token, definitive for an agent), then a confirmation_token from a first 428 call. Nothing is destroyed and the slot is not freed until the second call. A token that no longer counts — expired after 5 minutes, already used, issued for another project or another account — is treated as absent: 428 again with a fresh token, and the response never says which of the four conditions applied. Replaying the DELETE on a project already being deleted answers 200; once it is gone, the neutral 404.