Skip to content

Databases API

PandaStack databases are KubeBlocks-backed PostgreSQL and MySQL clusters. (MongoDB is not provisionable and is rejected.) Passwords are never read into responses; connection URLs are returned masked except through the credentials endpoint, which is admin-gated. The database type is stored uppercase internally and surfaced lowercased on the wire.

Concept guides: Databases overview, Create a database, Connecting, Tiers & scaling, Backups & restore, Metrics, Free-tier lifecycle.

All routes require authentication; role floors are noted per endpoint.

DatabaseDetail:

FieldTypeNotes
idnumber
namestring | null
typepostgresql | mysql | string | null
versionstring | null
statusenum | string | nullpending | running | failed | deploying | updating | deleting | queued | stopped.
visibilitypublic | private | string | null
instanceTypestring | nullTier slug.
organizationIdstringBIGINT → string.
regionstring | null
backupstring | nullenabled | disabled.
backupsToKeepnumber | null
architecturestring | nullstandalone | replicaset.
serverDetailsobject{ cpu (vCPU), memory (GB), disk (GB) }.
publicUrlstring | nullMasked.
privateUrlstring | nullMasked.
connectionDetailsobject{ host, port, username, database, passwordAvailable }.
createdAt / updatedAtstring | null

DatabaseListItem is the compact list shape: id, name, type, version, status, visibility, instanceType, serverDetails, createdAt.


GET /v1/databases

Page-paginated list of the org’s databases; connection strings masked.

Auth: any member. Query (DatabaseListQuery): page (default 1), pageSize (default 20, max 100).

Response (DatabaseListPage): { items: DatabaseListItem[], total: number }.

Terminal window
curl "https://api.pandastack.io/v1/databases?page=1&pageSize=20" \
-H "Authorization: Bearer $PANDASTACK_TOKEN"

POST /v1/databases

Provisions a PostgreSQL or MySQL database. The API writes a row and an outbox event in one transaction, then a message flows through RabbitMQ to KubeBlocks. Provisioning is asynchronous — poll the database status. MongoDB is rejected.

Auth: member. Body (CreateDatabaseInput):

FieldTypeRequiredNotes
namestringyesRFC-1123 label; 1–63 chars; ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$.
typeenumyespostgresql | mysql.
versionstringyesMust be allowed for the type — MySQL: 8.4.2 or 5.7.44; PostgreSQL: 16.4.0 or 14.8.0.
instanceTypestringyesTier slug.
visibilitypublic | privatenoDefault public.
usernamestringno1–63 chars. Auto-generated if omitted.
dbNamestringno1–63 chars.
passwordstringnoMin 8. Auto-generated if omitted.
regionstringnoDefault us.
backupenabled | disablednoDefault disabled.
architecturestandalone | replicasetnoDefault standalone.
projectIdnumbernoPositive int; links the DB to a project at creation (injects a connection URL).

Response: DatabaseDetail.

Terminal window
curl -X POST https://api.pandastack.io/v1/databases \
-H "Authorization: Bearer $PANDASTACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "app-db",
"type": "postgresql",
"version": "16.4.0",
"instanceType": "db-free",
"visibility": "private",
"backup": "disabled",
"architecture": "standalone"
}'

See Tiers & scaling for valid instanceType slugs and Free-tier lifecycle for what happens to free databases over time.

GET /v1/databases/:name

Auth: any member. Returns DatabaseDetail (see the database object).

GET /v1/databases/:name/connection-strings

Auth: any member. Response (DatabaseConnectionStrings): { publicUrl (masked), privateUrl (masked) }. Both may be null.

See Connecting.

GET /v1/databases/:name/password

Returns the real password and full connection URLs on demand. This is the only endpoint that surfaces the unmasked secret, and it is admin-gated.

Auth: admin. Response (DatabaseCredentials):

FieldTypeNotes
passwordstring | nullUnmasked, role-gated.
publicUrlstring | nullFull URL with the real password.
privateUrlstring | null
Terminal window
curl https://api.pandastack.io/v1/databases/app-db/password \
-H "Authorization: Bearer $PANDASTACK_TOKEN"

GET /v1/databases/:name/metrics

A live Kubernetes pod snapshot proxied via worker-v3. Available on all tiers.

Auth: any member. Response (DatabaseMetrics):

FieldTypeNotes
availableboolean
phasestring | nullRunning | Pending | …
readyboolean
restartsnumber
startedAtstring | null
cpuMillinumber | nullCurrent total CPU millicores.
memoryMiBnumber | nullCurrent total memory MiB.
containersDatabaseContainerMetric[]Each { name, cpuMilli, memoryMiB }.

GET /v1/databases/:name/metrics/summary

Engine-level metrics from Google Managed Prometheus (postgres/mysqld exporters). Paid tiers only.

Auth: any member. Query: ?range (MetricRange: 1h | 24h | 7d | 30d). Response (DatabaseEngineMetricsSummary):

FieldTypeNotes
rangeMetricRange
enabledboolean
enginestringpostgresql | mysql.
upboolean | null
connectionsnumber | null
maxConnectionsnumber | null
connectionsPctnumber | null0–100.
qpsnumber | null
cacheHitPctnumber | null0–100.

GET /v1/databases/:name/metrics/timeseries

Auth: any member. Query: ?range. Response (DatabaseEngineMetricsTimeseries): { range, enabled, engine, points: [{ t, connections, qps, cacheHitPct }] }. A null point value means no sample (chart gap).

See Metrics.


GET /v1/databases/:name/backups

Lists a database’s backups (live KubeBlocks state).

Auth: any member. Response (DatabaseBackups):

{
"success": true,
"data": {
"config": {
"enabled": true,
"method": "volume-snapshot",
"cronExpression": "0 3 * * *",
"retentionPeriod": "7d"
},
"items": [
{
"name": "app-db-backup-20260714",
"status": "Completed",
"method": "volume-snapshot",
"totalSize": "512Mi",
"startedAt": "2026-07-14T03:00:00Z",
"completedAt": "2026-07-14T03:01:12Z",
"expiresAt": "2026-07-21T03:00:00Z"
}
]
}
}

config may be null when no backup policy exists. See Backups & restore.


POST /v1/databases/:name/change-tier

Change the database tier in either direction (scale up, scale down, or free ↔ paid). Asynchronous.

Auth: admin. Body (ChangeTierInput):

FieldTypeRequiredNotes
instanceTypestringyesMust exist in the tier catalog.
expectedCurrentTierstringnoOptimistic-concurrency guard.
confirmDowngradeToFreebooleannoDefault false; required to confirm a downgrade to free.

Response: DatabaseDetail.

Terminal window
curl -X POST https://api.pandastack.io/v1/databases/app-db/change-tier \
-H "Authorization: Bearer $PANDASTACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "instanceType": "db-standard", "expectedCurrentTier": "db-free" }'

POST /v1/databases/:name/upgrade

Deprecated alias of change-tier, kept one release for CLI/old-dashboard compatibility. Body UpgradeDatabaseInput is identical to ChangeTierInput. Prefer change-tier.

POST /v1/databases/:name/restore

Restores a database in place from a backup. This overwrites current data. Paid-only, asynchronous.

Auth: admin. Body (RestoreDatabaseInput):

FieldTypeRequiredNotes
backupNamestringyesThe backup to restore.
confirmbooleannoDefault false; must be true to proceed (destructive).

Response: { ok: true }.

Terminal window
curl -X POST https://api.pandastack.io/v1/databases/app-db/restore \
-H "Authorization: Bearer $PANDASTACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "backupName": "app-db-backup-20260714", "confirm": true }'

DELETE /v1/databases/:name

Deletes the database; the KubeBlocks Cluster CR is torn down asynchronously via worker-v3.

Auth: member. Response: { success: true, data: { async: true } }.

Terminal window
curl -X DELETE https://api.pandastack.io/v1/databases/app-db \
-H "Authorization: Bearer $PANDASTACK_TOKEN"

There is no dedicated link route on this page — a database is linked to a project at creation by passing projectId in POST /v1/databases, which injects a connection URL into the project’s environment. See the Projects API and Connecting.