Databases API
Database services are Aeroplane services with repoFullName: "database:<engine>".
All examples assume:
export AEROPLANE_URL="https://pilot.example.com"export AEROPLANE_API_KEY="ap_..."Supported Engines
Section titled “Supported Engines”Use these engine IDs in repoFullName:
database:postgresdatabase:timescaledatabase:mysqldatabase:redisdatabase:mongodbdatabase:clickhouse
Create PostgreSQL
Section titled “Create PostgreSQL”POST /api/projects/:projectId/servicesRequired access: write
Project scope: project must be visible to the key.
Payload:
{ "name": "postgres-db", "repoFullName": "database:postgres", "repoUrl": "database", "branch": "main", "internalPort": 5432, "databasePublicEnabled": true, "postgresLogicalReplicationEnabled": true, "env": [ { "key": "POSTGRES_DB", "value": "aeroplane" }, { "key": "POSTGRES_USER", "value": "postgres" }, { "key": "POSTGRES_PASSWORD", "value": "change-this-password" } ]}Example:
curl -X POST "$AEROPLANE_URL/api/projects/project_123/services" \ -H "Authorization: Bearer $AEROPLANE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "postgres-db", "repoFullName": "database:postgres", "repoUrl": "database", "branch": "main", "internalPort": 5432, "databasePublicEnabled": true, "postgresLogicalReplicationEnabled": true, "env": [ { "key": "POSTGRES_DB", "value": "aeroplane" }, { "key": "POSTGRES_USER", "value": "postgres" }, { "key": "POSTGRES_PASSWORD", "value": "change-this-password" } ] }'Response:
{ "service": { "id": "svc_postgres", "projectId": "project_123", "name": "postgres-db", "slug": "postgres-db", "repoFullName": "database:postgres", "repoUrl": "database", "dockerImage": null, "branch": "main", "runtimeMode": "web", "internalPort": 5432, "hostPort": 41003, "databasePublicEnabled": true, "databasePublicHostname": "postgres-db.example.com", "postgresLogicalReplicationEnabled": true, "status": "idle", "createdAt": "2026-06-10T08:50:00.000Z", "updatedAt": "2026-06-10T08:50:00.000Z" }}databasePublicHostname is optional. When omitted and a root domain is configured, Aeroplane generates the public database hostname from the service name.
Create Other Engines
Section titled “Create Other Engines”Use the same endpoint and change repoFullName, internalPort, and initial environment variables.
Redis:
{ "name": "redis-db", "repoFullName": "database:redis", "repoUrl": "database", "branch": "main", "internalPort": 6379, "databasePublicEnabled": true, "env": [ { "key": "REDIS_PASSWORD", "value": "change-this-password" } ]}MongoDB:
{ "name": "mongo-db", "repoFullName": "database:mongodb", "repoUrl": "database", "branch": "main", "internalPort": 27017, "databasePublicEnabled": true, "env": [ { "key": "MONGO_INITDB_ROOT_USERNAME", "value": "mongo" }, { "key": "MONGO_INITDB_ROOT_PASSWORD", "value": "change-this-password" } ]}MySQL:
{ "name": "mysql-db", "repoFullName": "database:mysql", "repoUrl": "database", "branch": "main", "internalPort": 3306, "databasePublicEnabled": true, "env": [ { "key": "MYSQL_DATABASE", "value": "aeroplane" }, { "key": "MYSQL_USER", "value": "mysql" }, { "key": "MYSQL_PASSWORD", "value": "change-this-password" }, { "key": "MYSQL_ROOT_PASSWORD", "value": "change-this-root-password" } ]}ClickHouse:
{ "name": "clickhouse-db", "repoFullName": "database:clickhouse", "repoUrl": "database", "branch": "main", "internalPort": 8123, "databasePublicEnabled": true, "env": [ { "key": "CLICKHOUSE_DB", "value": "aeroplane" }, { "key": "CLICKHOUSE_USER", "value": "clickhouse" }, { "key": "CLICKHOUSE_PASSWORD", "value": "change-this-password" }, { "key": "CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT", "value": "1" } ]}TimescaleDB:
{ "name": "timescale-db", "repoFullName": "database:timescale", "repoUrl": "database", "branch": "main", "internalPort": 5432, "databasePublicEnabled": true, "postgresLogicalReplicationEnabled": true, "env": [ { "key": "POSTGRES_DB", "value": "aeroplane" }, { "key": "POSTGRES_USER", "value": "postgres" }, { "key": "POSTGRES_PASSWORD", "value": "change-this-password" }, { "key": "TIMESCALEDB_TELEMETRY", "value": "off" } ]}List Tables
Section titled “List Tables”GET /api/services/:serviceId/database/tablesRequired access: read
Project scope: service project must be visible to the key.
For Redis, add ?database=0 to choose a logical database.
Example:
curl "$AEROPLANE_URL/api/services/svc_postgres/database/tables" \ -H "Authorization: Bearer $AEROPLANE_API_KEY"Response:
{ "engine": "postgres", "tables": [ { "id": "public.users", "name": "users", "schema": "public", "rowCount": 42 } ]}Read Rows
Section titled “Read Rows”GET /api/services/:serviceId/database/rows?table=:table&limit=:limit&offset=:offsetRequired access: read
Example:
curl "$AEROPLANE_URL/api/services/svc_postgres/database/rows?table=public.users&limit=50&offset=0" \ -H "Authorization: Bearer $AEROPLANE_API_KEY"Response:
{ "engine": "postgres", "table": "public.users", "columns": [ { "name": "id", "type": "uuid", "primary": true }, { "name": "email", "type": "text", "primary": false } ], "rows": [ { "id": "user_123", "email": "owner@example.com" } ], "limit": 50, "offset": 0, "total": 1}Run SQL Query
Section titled “Run SQL Query”POST /api/services/:serviceId/database/queryRequired access: write
Payload:
{ "sql": "select now() as current_time"}Response:
{ "columns": [ { "name": "current_time", "type": "timestamp" } ], "rows": [ { "current_time": "2026-06-10T08:55:00.000Z" } ], "rowCount": 1}Insert Row
Section titled “Insert Row”POST /api/services/:serviceId/database/rowsRequired access: write
Payload:
{ "table": "public.users", "values": { "email": "new@example.com" }}Response:
{ "ok": true, "table": "public.users", "id": "user_456"}Update Row
Section titled “Update Row”PATCH /api/services/:serviceId/database/rowsRequired access: write
Payload:
{ "table": "public.users", "primaryKey": { "id": "user_456" }, "values": { "email": "updated@example.com" }}Response:
{ "ok": true}Delete Row
Section titled “Delete Row”DELETE /api/services/:serviceId/database/rowsRequired access: write
Payload:
{ "table": "public.users", "primaryKey": { "id": "user_456" }}Response:
{ "ok": true}List Backups
Section titled “List Backups”GET /api/services/:serviceId/database/backupsRequired access: read
Response:
{ "backups": [ { "id": "backup_123", "serviceId": "svc_postgres", "engine": "postgres", "status": "succeeded", "trigger": "manual", "storage": "disk", "format": "custom", "localPath": "/data/backups/svc_postgres/backup_123.dump", "r2Key": null, "sizeBytes": 2048, "checksum": "sha256:...", "error": null, "createdAt": "2026-06-10T09:00:00.000Z", "startedAt": "2026-06-10T09:00:00.000Z", "finishedAt": "2026-06-10T09:00:05.000Z" } ], "settings": { "serviceId": "svc_postgres", "storage": "disk", "automaticEnabled": false, "dailyEnabled": false, "weeklyEnabled": false, "monthlyEnabled": false, "createdAt": "2026-06-10T08:50:00.000Z", "updatedAt": "2026-06-10T08:50:00.000Z" }, "r2": { "connected": false }}Create Backup
Section titled “Create Backup”POST /api/services/:serviceId/database/backupsRequired access: write
Payload:
{ "storage": "disk"}Allowed storage values: disk, r2, disk+r2.
Response:
{ "backup": { "id": "backup_123", "serviceId": "svc_postgres", "engine": "postgres", "status": "running", "trigger": "manual", "storage": "disk", "format": "custom", "createdAt": "2026-06-10T09:00:00.000Z", "startedAt": "2026-06-10T09:00:00.000Z", "finishedAt": null }}Restore Backup
Section titled “Restore Backup”POST /api/services/:serviceId/database/backups/:backupId/restoreRequired access: write
Response:
{ "ok": true, "restoredAt": "2026-06-10T09:10:00.000Z", "backup": { "id": "backup_123", "status": "succeeded" }}Download Backup
Section titled “Download Backup”GET /api/services/:serviceId/database/backups/:backupId/downloadRequired access: read
Example:
curl -L "$AEROPLANE_URL/api/services/svc_postgres/database/backups/backup_123/download" \ -H "Authorization: Bearer $AEROPLANE_API_KEY" \ -o backup.dumpResponse body: backup file bytes.
Delete Backup
Section titled “Delete Backup”DELETE /api/services/:serviceId/database/backups/:backupIdRequired access: write
Response:
{ "ok": true}Postgres TLS Info
Section titled “Postgres TLS Info”GET /api/services/:serviceId/database/tlsRequired access: read
Postgres-compatible services only.
Response:
{ "tls": { "active": true, "caCertAvailable": true, "publicHostname": "postgres-db.example.com", "publicPort": 41003 }}Download Postgres CA
Section titled “Download Postgres CA”GET /api/services/:serviceId/database/tls/caRequired access: read
Response body: PEM file bytes.
Data Imports
Section titled “Data Imports”List imports:
GET /api/services/:serviceId/database/importsResponse:
{ "imports": [ { "id": "import_123", "serviceId": "svc_postgres", "engine": "postgres", "source": "postgres-url", "sourceLabel": "Postgres URL", "status": "succeeded", "createdAt": "2026-06-10T09:20:00.000Z", "startedAt": "2026-06-10T09:20:00.000Z", "finishedAt": "2026-06-10T09:21:00.000Z" } ]}Import Postgres from URL:
POST /api/services/:serviceId/database/import/postgres-urlPayload:
{ "sourceUrl": "postgresql://user:password@host:5432/database"}Import Redis from URL:
POST /api/services/:serviceId/database/import/redis-urlPayload:
{ "sourceUrl": "redis://:password@host:6379/0"}Import response:
{ "result": { "id": "import_123", "status": "running", "source": "postgres-url", "createdAt": "2026-06-10T09:20:00.000Z" }}