Guide
REST API reference
The Layerbase Cloud API lets you create, list, and query databases over HTTPS, and manage the personal API keys that authenticate every request. This page documents each public endpoint: the auth header it expects, the fields it accepts, the shape it returns, and the status codes it can send back. The Docs overview has the quickstart if you are starting from scratch.
Base URL
Every request uses HTTPS and the same base URL. The examples below store it in $LAYERBASE_API_URL.
https://cloud.layerbase.devAuthentication
All /v1/* endpoints except GET /v1/engines require a personal API key as a Bearer token. Keys are prefixed sk_ and the full secret is shown exactly once, at creation. Create and manage keys under Personal API keys in cloud settings, or with the key endpoints below.
Authorization: Bearer sk_<your-key>Keys have one of two scopes. An account key (the default) can reach every endpoint for your account. A database key is pinned to one database: it may only call /v1/databases/<that-id> and its sub-paths, and returns 403 anywhere else.
An sk_ key is the only credential the authenticated /v1/* endpoints accept (the unauthenticated ones noted above take no credential at all). In particular, the session token the CLI stores after the browser login flow, lbase login with no flags, is a browser-issued JWT that works only against the layerbase.com/api/cli/* proxy routes, and sending it here returns 401 Invalid API key. Storing a key with lbase login --api-key sk_... is a different flow and does leave the CLI holding a valid sk_ credential. If you are debugging that error while signed in to the CLI, that mismatch is the usual cause: create a key under Personal API keys and send it instead. See the CLI guide for how the two credentials divide up.
Request and response format
Requests and responses are JSON, and body fields use camelCase. Send Content-Type: application/json on any request with a body. Errors return { "error": "message" } with a relevant HTTP status; some also add a machine-readable code (for example database_limit_reached or pool_block_required).
200Success.
201Created (database, API key).
400Invalid input: bad engine, name, or body field.
401Missing, malformed, or unknown API key.
402Account is suspended for a failed payment. Mutating calls are blocked; GET calls still work.
403Not allowed: a database-scoped key hitting another database, an engine your plan cannot create, or an owner-only action.
404Database or key not found (or not yours).
409Conflict: name already taken, pool capacity exhausted, or a pool block is required.
423Database is locked, or an operation is in progress.
429Your plan's database limit or monthly programmatic-create limit is reached.
503Temporarily unavailable: engine binary not ready, database waking or archived, or account migrating.
Health and engines
/healthUnauthenticated liveness probe. Returns { "status": "ok", "service": "layerbase-cloud" }. Returns 503 with draining or overloaded when the server is shutting down or under memory pressure.
/v1/enginesThe public engine registry: every engine, its display name, versions, and defaults. No auth required. This is the same data the dashboard create flow reads, so you can use it to build a valid engine and version for a create call.
Databases
/v1/databasesLists the databases you own plus any shared with you through a team. Returns { "databases": [ ... ] }. Each entry includes id, name, engine, version, status, host, port, connectionString, an access field of owner or member, the placement fields server / serverPool (the canonical server slug and either shared or dedicated; both null when placement is not reported), and the transient fields expiresAt / transient (see transient databases). App workloads are not databases and never appear here.
curl $LAYERBASE_API_URL/v1/databases \
-H "Authorization: Bearer $LAYERBASE_API_KEY"/v1/databasesProvisions a new database. Only engine is required; the rest have defaults.
engineRequired. e.g. postgresql, mysql, redis, valkey, mariadb, mongodb, clickhouse.
versionOptional. Defaults to the engine default from /v1/engines.
nameOptional. Lowercase letter first, then letters/numbers/hyphens/underscores, up to 63 chars. Auto-generated if omitted.
databaseOptional. Initial database/schema name. Defaults per engine.
backupPolicyOptional. 'none' (default), '7d', or '30d'.
keepAliveOptional boolean. Always-on (skip hibernation). Paid plans only.
storageBlocksOptional integer 0-20. Extra storage blocks.
ttlHoursOptional integer 1-72. Makes the database transient: an expires_at is stamped and the database is destroyed outright at expiry with no final backup. Ideal for CI. See Transient databases below.
teamIdOptional. Owning team. Defaults to your primary team.
Returns 201 with the new database, including its connection details and a status. Fast engines come back running; slow-start engines (MySQL, MariaDB, ClickHouse, QuestDB, libSQL) come back provisioning and finish in the background, so poll GET /v1/databases/:id until status is running. Redis and Valkey also return restUrl / restToken; MySQL and MariaDB also return psUrl / psUsername / psPassword for their HTTP drivers (see serverless and edge access).
The response also carries the placement fields server (the canonical server slug of the box hosting the database) and serverPool (shared or dedicated). Either may be null while a slow-start engine is still provisioning, or when the host does not report placement.
curl -X POST $LAYERBASE_API_URL/v1/databases \
-H "Authorization: Bearer $LAYERBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"engine": "postgresql", "name": "my-app"}'Common failures: 400 for an invalid engine or name, 403 for an engine your plan cannot create, 409 when the name is taken or the pool is exhausted, and 429 when you hit your plan's database limit or your monthly programmatic-create limit (see programmatic-create limits).
Transient databases (TTL)
Pass ttlHours (a whole number from 1 to 72) on create to make the database transient. Layerbase stamps an expires_at deadline and a reaper destroys the database outright at expiry: there is no final backup and no archive-warning window, because you asked for a throwaway. This is the recommended primitive for a fresh, disposable database per CI run: a crashed job cannot strand a database against your quota, because it self-destructs at the deadline. Every database in the response carries two extra fields: expiresAt (an ISO timestamp, or null for a durable database) and transient (a boolean).
A transient database still counts against your plan's database quota while it is alive, and it cannot be branched. An out-of-range ttlHours returns 400 with { "code": "invalid_ttl" } (the value is never silently clamped), and branching a transient database returns 400 with { "code": "branch_on_transient_forbidden" }.
curl -X POST $LAYERBASE_API_URL/v1/databases \
-H "Authorization: Bearer $LAYERBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"engine": "postgresql", "ttlHours": 2}'/v1/databases/:idReturns one database with the same fields as the list entry plus teamName and stopped_at. Returns 404 if the database does not exist or is not yours. Poll this after a create to watch status settle.
/v1/databases/:id/queryRuns a query over HTTP against the database, no driver or open socket required, which makes it the easiest path from serverless and edge runtimes. Send { "query": "SELECT 1" } for SQL engines; the query is capped at 10 KB. A hibernated database wakes automatically (you may get a 503 with retry_after while it does); an archived one returns 503 with a restore path, and a locked one returns 423. The full request shapes for non-SQL engines and edge examples are in serverless and edge access.
curl -X POST $LAYERBASE_API_URL/v1/databases/<id>/query \
-H "Authorization: Bearer $LAYERBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "SELECT 1"}'Identity and usage
/v1/meReturns who the key belongs to and your current programmatic-create usage, with no side effects. Use it for a whoami check or to let an agent report your standing before it provisions anything.
{
"user": { "id": "...", "email": "you@example.com", "plan": "pro" },
"usage": {
"programmaticCreates": {
"used": 12,
"limit": 500,
"resetsAt": "2026-08-01T00:00:00.000Z"
}
}
}limit is null when your plan is unmetered (a Custom plan on your own servers), and resetsAt is the first instant of next month in UTC.
Programmatic-create limits
Every database create authenticated by an API key counts toward a monthly programmatic-create quota, tracked per calendar month in UTC. This is separate from your plan's database-count quota: it caps how many databases automation may spin up over a month (transient or durable), so a CI loop cannot exhaust shared capacity. Creates you make in the dashboard do not count. The per-plan limits are:
5 / month30 / month500 / month1,000 / monthUnmeteredWhen you exceed the limit, the create returns 429 before any provisioning work, with a machine-readable body so a script or agent can back off gracefully:
{
"code": "programmatic_create_limit_reached",
"error": "Programmatic create limit reached (5/5 this month). Upgrade your plan for a higher limit: https://layerbase.com/pricing",
"used": 5,
"limit": 5,
"resetsAt": "2026-08-01T00:00:00.000Z"
}API keys
Manage the personal keys that authenticate the API. The raw secret is returned exactly once, on create and rotate; store it immediately.
/v1/api-keysLists your active keys. Returns { "keys": [ ... ] } with each key's id, name, prefix, scopeType, createdAt, and lastUsedAt. The secret is never included.
/v1/api-keysCreates a key. Body is optional: name (defaults to default, max 80 chars), scopeType (account or database), and scopeId (required when scopeType is database, naming a database you own). Returns 201 with { "key": { ..., "secret": "sk_..." } }. The secret appears only in this response.
curl -X POST $LAYERBASE_API_URL/v1/api-keys \
-H "Authorization: Bearer $LAYERBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "ci"}'/v1/api-keys/:id/rotateMints a replacement key with the same name and scope and revokes the old one after a 24-hour grace window, so long-running callers can pick up the new secret without an outage. Returns 201 with the new key and its one-time secret. Returns 404 if the key is not yours and 410 if it is already revoked.
/v1/api-keys/:idRevokes a key immediately. Returns { "ok": true } and is idempotent (revoking an already-revoked key still returns 200). Any request using that key fails 401 afterward.
The dashboard exposes many more per-database operations (stop, start, backup, restore, branch, firewall, client certificates) over the same /v1/databases/:id/* surface. Those are covered in their own guides, linked below.