Skip to content

Database

Previewcapability-gated

The database resource exposes the managed database behind an environment — its metrics and schema, read queries, and exports — as a typed, scoped surface. It’s part of the dynamic application layer: the depth a generic PaaS won’t touch, delivered with scoped keys and async jobs.

GET …/{envID}/database  

db:read

Returns size, table inventory, and engine metadata for the environment’s database — no row data, so this read is cheap and safe to poll.

200 response
{
"data": {
"engine": "mysql", "version": "8.0",
"size_bytes": 184320512,
"tables": [
{ "name": "wp_posts", "rows": 12840, "size_bytes": 5242880 },
{ "name": "wp_options", "rows": 412, "size_bytes": 1048576 }
]
},
"request_id": "req_01J9..."
}

POST …/{envID}/database/query  

db:read

Run a read-only query and get typed rows back. db:read rejects anything that writes — INSERT, UPDATE, DELETE, DDL — so a read-scoped key can never mutate data. Returns a job for large result sets.

Parameter Type Required Description
query string yes A read-only SQL statement. Writes are rejected.
params array no Bound parameters, in order, for placeholders in query.
limit integer no Cap rows returned. A platform ceiling applies regardless.
Count published posts
curl -X POST https://api.managed.dev/v1/sites/site_01J7.../environments/env_01J8.../database/query \
-H "Authorization: Bearer mfk_live_9aF2..." \
-H "Forge-Version: 2026-06-23" \
-H "Content-Type: application/json" \
-d '{ "query": "SELECT post_status, COUNT(*) AS n FROM wp_posts WHERE post_type = ? GROUP BY post_status", "params": ["post"] }'
200 response
{
"data": {
"columns": ["post_status", "n"],
"rows": [
{ "post_status": "publish", "n": 240 },
{ "post_status": "draft", "n": 18 }
],
"row_count": 2
},
"request_id": "req_01J9..."
}

POST …/{envID}/database/export  

db:read

Produce a downloadable dump of the environment’s database. Returns 202 Accepted with a job; when it completes, the job’s result carries a short-lived signed download URL.

Parameter Type Required Description
tables array no Restrict the export to named tables. Omit for the whole database.
compress boolean no Gzip the dump. Defaults to true.
  1. Request the export.

    Export the whole database, compressed
    curl -X POST https://api.managed.dev/v1/sites/site_01J7.../environments/env_01J8.../database/export \
    -H "Authorization: Bearer mfk_live_9aF2..." \
    -H "Forge-Version: 2026-06-23" \
    -H "Idempotency-Key: c7e0-18aa-9d31" \
    -H "Content-Type: application/json" \
    -d '{ "compress": true }'
    202 response
    HTTP/1.1 202 Accepted
    Location: /v1/jobs/job_01J9...
    {
    "data": { "id": "job_01J9...", "type": "database.export", "status": "queued",
    "created_at": "2026-06-23T18:22:40.118Z",
    "resource": { "type": "database", "site_id": "site_01J7...", "env_id": "env_01J8..." } },
    "request_id": "req_01J9..."
    }
  2. Wait for the job, then read its result for the signed URL. See async jobs.

    Completed job result
    { "download_url": "https://files.managed.dev/exports/...?sig=...",
    "expires_at": "2026-06-23T19:22:40Z", "size_bytes": 41943040 }

Write access lives behind db:write and is treated with care. A write query or a schema migration is dry-run by default: send "confirm": false (the default) to get back the rows or statements that would change, then resend with "confirm": true to apply. Pair any write with a snapshot so a mistake is one restore away.