Hosted Databases
Provision and manage project-scoped PostgreSQL databases directly from the Syntropy platform. Each database runs with PgBouncer connection pooling and supports automated backups and credential rotation.
Endpoints
GET /api/organizations/{organizationId}/projects/{projectId}/databases
POST /api/organizations/{organizationId}/projects/{projectId}/databases
GET /api/organizations/{organizationId}/projects/{projectId}/databases/{databaseId}
DELETE /api/organizations/{organizationId}/projects/{projectId}/databases/{databaseId}
GET /api/organizations/{organizationId}/projects/{projectId}/databases/{databaseId}/connection-string
GET /api/organizations/{organizationId}/projects/{projectId}/databases/{databaseId}/credentials
POST /api/organizations/{organizationId}/projects/{projectId}/databases/{databaseId}/credentials
Authentication and Authorization
All database endpoints support:
- authenticated dashboard session, or
- project API key with the appropriate scope
| Scope | Grants |
|---|---|
databases:read | List databases, get status, read connection string, list credentials |
databases:write | Create databases |
databases:admin | Delete databases, rotate credentials |
Database Lifecycle
provisioning → ready → deleting → deleted
Creation and deletion are async. Both operations enqueue a background job and return a jobId you can poll via the Queue Worker API.
List Databases
GET /databases
Returns all databases for the project, ordered by creation date descending.
Response
{
"databases": [
{
"id": "uuid",
"name": "My Database",
"databaseName": "my_db",
"plan": "shared",
"engine": "postgres",
"engineVersion": "16",
"status": "ready",
"requestedStorageGb": 10,
"latestBackupAt": "2026-05-01T03:00:00.000Z",
"provisionedAt": "2026-04-15T12:00:00.000Z",
"createdAt": "2026-04-15T11:58:00.000Z",
"updatedAt": "2026-05-01T03:00:00.000Z"
}
]
}
Create Database
POST /databases
Provisions a new PostgreSQL database. Returns immediately with status: "provisioning" and a jobId to track progress.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Display name (1–255 characters) |
databaseName | string | yes | PostgreSQL database name. Must start with a letter; only lowercase letters, digits, and underscores; max 63 characters. |
requestedStorageGb | integer | no | Requested disk size in GB (1–100, default 10) |
Example
{
"name": "Production DB",
"databaseName": "prod_db",
"requestedStorageGb": 20
}
Response — 201 Created
{
"database": {
"id": "uuid",
"name": "Production DB",
"databaseName": "prod_db",
"plan": "shared",
"status": "provisioning",
"createdAt": "2026-05-08T10:00:00.000Z"
},
"jobId": "job-uuid"
}
status will transition to ready once provisioning completes (poll via /queue/jobs/{jobId}).
Errors
| Status | Reason |
|---|---|
400 | Invalid request body |
409 | A database with that databaseName already exists in this organization |
Get Database
GET /databases/{databaseId}
Returns full database details. When status is ready, the response includes a redacted connection string (password replaced with ***) for display purposes. Use the connection-string endpoint to retrieve the live credential.
Response
{
"database": {
"id": "uuid",
"name": "Production DB",
"databaseName": "prod_db",
"ownerRoleName": "prod_db_owner",
"plan": "shared",
"engine": "postgres",
"engineVersion": "16",
"status": "ready",
"requestedStorageGb": 20,
"backupPolicy": "daily",
"latestBackupAt": "2026-05-07T03:00:00.000Z",
"provisionedAt": "2026-05-08T10:05:00.000Z",
"createdAt": "2026-05-08T10:00:00.000Z",
"updatedAt": "2026-05-08T10:05:00.000Z",
"connectionString": "postgresql://prod_db_owner:***@pool.host:5432/prod_db"
}
}
Delete Database
DELETE /databases/{databaseId} — requires databases:admin
Enqueues a destroy job. Returns immediately with status: "deleting".
Response
{
"jobId": "job-uuid",
"status": "deleting"
}
Errors
| Status | Reason |
|---|---|
404 | Database not found |
409 | Database is already being deleted |
Get Connection String
GET /databases/{databaseId}/connection-string — requires databases:read
Returns the live connection string including the plaintext password. Only available when status is ready. Store this securely — treat it like a secret.
The connection string points to the PgBouncer pooler endpoint, not the Postgres host directly.
Response
{
"connectionString": "postgresql://prod_db_owner:s3cr3tp4ss@pool.host:5432/prod_db"
}
Errors
| Status | Reason |
|---|---|
409 | Database is not ready |
503 | Connection details not yet available (provisioning still in progress) |
List Credentials
GET /databases/{databaseId}/credentials — requires databases:read
Returns all credentials associated with the database, ordered by creation date descending.
Response
{
"credentials": [
{
"id": "uuid",
"name": "owner",
"roleName": "prod_db_owner",
"status": "active",
"scopes": ["read", "write"],
"lastUsedAt": null,
"rotatedAt": null,
"expiresAt": null,
"revokedAt": null,
"createdAt": "2026-05-08T10:05:00.000Z",
"updatedAt": "2026-05-08T10:05:00.000Z"
}
]
}
Rotate Credentials
POST /databases/{databaseId}/credentials — requires databases:admin
Enqueues a credential rotation job for a specific credential. The old password remains valid until the job completes.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
credentialId | string (UUID) | yes | The credential to rotate |
Response
{
"jobId": "job-uuid",
"status": "rotating"
}
Errors
| Status | Reason |
|---|---|
400 | credentialId missing |
404 | Database or credential not found |
409 | Database is not ready, or credential is not active |
Example cURL
# Create a database
curl -X POST \
"https://your-domain.com/api/organizations/{orgId}/projects/{projectId}/databases" \
-H "Authorization: Bearer syn_sk_xxx" \
-H "Content-Type: application/json" \
-d '{"name": "Production DB", "databaseName": "prod_db", "requestedStorageGb": 20}'
# Get the live connection string once ready
curl \
"https://your-domain.com/api/organizations/{orgId}/projects/{projectId}/databases/{databaseId}/connection-string" \
-H "Authorization: Bearer syn_sk_xxx"
Related
- Project API Keys —
databases:read,databases:write,databases:adminscopes - Queue Worker — track provisioning and rotation jobs via
jobId