Provision a Per-App Database

POST /v1/applications/{uuid}/database
Prefer the Databases API. Databases are an account resource: create one with its own users and connect it to one or more apps (with an optional variable prefix). This endpoint keeps working as a shortcut: it creates an ordinary database of your account and connects the app to it.

Give a backend app (type managed, fullstack or function) its own MariaDB database in one call. In one step Ngris creates a database in your account (listed by GET /v1/databases), named after the app — <name>-2, <name>-3 … when the account already has a database of that name — with a read-write user named app, and connects the app to it as that user with no prefix, so the app gets DB_HOST … DATABASE_URL. One per application.

The variables are built when the app starts: nothing is written into the app's environment variables, and the password is never returned. To get one, reset the app user's password (connected apps restart). From then on it is an ordinary database: rename it, add users, connect other apps, or disconnect it. It stays when you delete the app, with its users and data; only a WordPress site's own database is deleted with the site. While the app is connected to it, the app's backups cover it.

Engine. MariaDB (MySQL-compatible) is the only engine. The request takes no engine parameter.

Environment variables

The connection gives the app these variables. They show in the app's env list as source: "database" rows, and reach the backend once the database and its app user are ready — a running app then restarts to pick them up:

DB_HOST string
The in-cluster database host.
DB_PORT string
3306 for MySQL / MariaDB.
DB_NAME string
The app's database name.
DB_USER string
The app user's login (u_<6 characters>_app).
DB_PASSWORD secret
Stored encrypted with the user, masked in the env list — delivered to the backend, never returned.
DATABASE_URL secret
A ready-to-use DSN (e.g. mysql://user:pass@host:3306/db). Also a masked secret.

Response (202 Accepted)

Provisioning is asynchronous. The database is created with status: "provisioning"; poll GET /database until it is ready. The response body is the database object itself (it is not wrapped), with no password. Calling again while it is provisioning answers 202 with it again; a failed one is retried.

uuid string (uuid)
The database's identifier in the Databases API.
name string
The database's label: the app's name (with -2, -3 … when taken). You can rename it.
status string
provisioning → ready (or failed).
db_name string
The schema name inside MariaDB (app_<slug>_<8 characters>).
db_user string
The login of the app user the app connects as.
db_host string
The in-cluster database host.
account_uuid string (uuid)
The account that owns the database.

Deprecated: until the sunset the database object also carries the legacy integer id and *_id fields. Don't use them; read uuid and the *_uuid fields.

Errors

403
The managed_backends or managed_database entitlement is not on your plan, or the account is at its plan's database limit.
404
Application not found, or it is a static app (no backend) — a managed database needs a managed backend.
409
A managed database already exists for this application. With code: "env_conflict" and names: the app already uses one of the names (its own environment variable, or a database connected without a prefix).
Request
curl -X POST \ "https://api.ngris.com/v1/applications/019be838-d261-7d9b-9499-71995a3a91c6/database" \ -H "X-API-KEY: <your_api_key>"
Response — 202 Accepted
{ "uuid": "019c0f03-217d-7dd5-ae01-5cd84d2f5729", "account_uuid": "019a68b9-1a79-7820-a884-41f554aba6bd", "name": "my-api", "engine": "mariadb", "db_name": "app_my_api_k3x9q2tm", "db_user": "u_p7d2m1_app", "db_host": "mariadb-apps.ngris-appdb.svc.cluster.local", "status": "provisioning", "created_at": "2026-10-18T12:00:00Z" }
Response — 409 Conflict
{ "error": "a managed database already exists for this application: it already uses DB_HOST", "code": "env_conflict", "names": ["DB_HOST"] }

Get the Per-App Database

GET /v1/applications/{uuid}/database

Read the app's own database: the one the call above created (or a WordPress site's), otherwise the database behind the app's DB_HOST … DATABASE_URL — a connection with no prefix that reaches production. Every database connected to the app is listed by GET /v1/applications/{uuid}/database-connections. Returns its status and the connection identifiers (db_name, db_user — the login the app connects as — and db_host). The password is never included: it is stored encrypted and reaches the backend as DB_PASSWORD; reset the user's password to get a new one. Poll this after provisioning until status is ready.

Response (200 OK)

database object | null
null when no database has been provisioned; otherwise the database.
database.status string
provisioning, ready, or failed.
database.db_name / db_user / db_host string
Connection identifiers — no password.
entitled bool
Whether the account has the managed_database entitlement (so a client can show the right affordance).

Errors

403
The managed_backends entitlement is not on your plan.
404
Application not found, or it is a static app (no backend).
Request
curl "https://api.ngris.com/v1/applications/019be838-d261-7d9b-9499-71995a3a91c6/database" \ -H "X-API-KEY: <your_api_key>"
Response — 200 OK (ready)
{ "database": { "uuid": "019c0f03-217d-7dd5-ae01-5cd84d2f5729", "account_uuid": "019a68b9-1a79-7820-a884-41f554aba6bd", "name": "my-api", "engine": "mariadb", "db_name": "app_my_api_k3x9q2tm", "db_user": "u_p7d2m1_app", "db_host": "mariadb-apps.ngris-appdb.svc.cluster.local", "status": "ready", "created_at": "2026-10-18T12:00:00Z" }, "entitled": true }
Response — 200 OK (none yet)
{ "database": null, "entitled": true }