Skip to content

Databases API

17 operations. Every call needs a session cookie or an Authorization: Bearer nct_… token unless marked Public. Conventions, errors and scopes

GET/database-engines

List the database engines and versions that can be created

Response 200 · OK · application/json
CatalogOutputBody
  • EngineView[] | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/environments/{environmentId}/databases

Create a managed database

Creates a staged database service with its data volume and generated credentials; nothing runs until it is deployed. Other services connect with ${{<slug>.DATABASE_URL}} (or REDIS_URL, MONGO_URL).

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
environmentIdrequiredpathstring
Request body · application/json · required
CreateDatabaseInputBody
  • acceptLicenseboolean
    Required for engines with a source-available licence (MongoDB, Redis)
  • databaseNamestring
  • engineenum: postgres | mysql | mariadb | valkey | redis | mongodb | clickhouserequired
    Valkey is the default key-value engine
  • flavorenum: postgis
    Image variant, e.g. postgis for PostgreSQL
  • namestring
    Display name; defaults to the engine name
  • serverIdstring
  • versionstring
    Major version; omitted means the engine's default
Response 201 · Created · application/json
ServiceView
  • appliedGenerationinteger (int64)required
  • Configrequired
  • createdAtstring (date-time)required
  • currentDeploymentIdstringrequired
  • ReleaseRefrequired
  • desiredStateenum: running | stoppedrequired
  • DomainView[] | nullrequired
  • environmentIdstringrequired
  • generationinteger (int64)required
  • GitRefrequired
  • gitTokenSetbooleanrequired
  • hasStagedChangesbooleanrequired
  • idstringrequired
  • kindenum: app | worker | database | route | stackrequired
  • DeploymentRefrequired
  • MaintenanceViewrequired
  • namestringrequired
  • NetworkRef[] | nullrequired
  • ObservedViewrequired
  • observedAtstring (date-time) | nullrequired
  • PendingChangeCountsrequired
  • privateHoststringrequired
  • projectIdstringrequired
  • registryAuthSetbooleanrequired
  • ScalingViewrequired
  • ServerRefrequired
  • serverIdstringrequired
  • slugstringrequired
  • sourceTypeenum: image | git | external | composerequired
  • stagedKindstring | nullrequired
    new | edited | null
  • stalebooleanrequired
  • TailnetViewrequired
  • updatedAtstring (date-time)required
  • VolumeRef[] | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/services/{serviceId}/database

Get a managed database's engine, exports and state

ParameterInTypeDescription
serviceIdrequiredpathstring
Response 200 · OK · application/json
DatabaseView
  • credentialKeysstring[] | nullrequired
    Variables that hold credentials; rotate them with the rotate action
  • deployedbooleanrequired
  • EngineViewrequired
  • ExportView[] | nullrequired
  • imagestringrequired
  • InfoView
  • ReplicationView
  • RotationView
  • serviceIdstringrequired
  • Specrequired
  • UpgradeView
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/promote

Promote a read replica to primary (manual)

Called on the replica. Manual: NebulaCtrl does not detect failures or switch automatically. With dryRun the plan is returned (status 200): switchover while the old primary is reachable (it is frozen, stopped and fenced, the replica replays everything, no data is lost) or forced otherwise (it needs acceptDataLoss: what the replica had not received is lost). The old primary is fenced and never runs as a primary again; rebuild it as a replica or delete it. Variables that reference the old primary are rewritten as staged changes. Production environments need approval. Asynchronous: poll replication.promotion.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serviceIdrequiredpathstring
Request body · application/json · required
PromoteInputBody
  • acceptDataLossboolean
    Required for a forced promote: what the replica had not received is lost
  • confirmstring
    Must equal the replica's slug
  • dryRunboolean
    Only return the plan
Response 202 · Accepted · application/json
PromoteResult
  • dryRunbooleanrequired
  • PromotePlanrequired
  • promotionIdstring
  • statusstring
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/services/{serviceId}/database/public-port

Get a database's public port

ParameterInTypeDescription
serviceIdrequiredpathstring
Response 200 · OK · application/json
PublicPortView
  • allowCidrsstring[] | nullrequired
  • denyCidrsstring[] | nullrequired
  • deployedbooleanrequired
    The proxy publishes the port
  • enabledbooleanrequired
  • hoststring
    The address clients connect to (the server's public IP); empty when the server has none
  • listenPortinteger (int64)
  • newEntrypointbooleanrequired
    The proxy does not listen on this port yet: applying it recreates the proxy container (about a second of dropped connections)
  • openToAllbooleanrequired
    The allow-list admits every address (confirmed with the database slug)
  • routeIdstring
    The route service that holds the port
  • serverIdstring
  • serverNamestring
  • stagedbooleanrequired
    The route has changes that are not deployed yet
  • suggestedPortinteger (int64)required
    A free port to start from when enabling
  • tlsenum: passthroughrequired
    The proxy never terminates TLS on this port
  • warningsstring[] | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

PUT/services/{serviceId}/database/public-port

Publish (or change) a database's public port

Stages a TCP route on listenPort of the database's server with a mandatory IP allow-list and an optional deny list (deny first). 0.0.0.0/0 or ::/0 is accepted only with confirmOpen set to the database slug. The proxy forwards raw TCP and never terminates TLS. Nothing changes until the route is deployed; a new port recreates the proxy container (about a second of dropped connections). Needs projects:write and proxy:write. 422 codes: allowlist_required, open_confirmation_required, invalid_config, invalid_listen_port, no_server, agent_too_old. 409 port_in_use.

ParameterInTypeDescription
serviceIdrequiredpathstring
Request body · application/json · required
SetPublicPortInputBody
  • allowCidrsstring[] | nullrequired
    Client networks (CIDRs or addresses) allowed to connect. Mandatory.
  • confirmOpenstring
    Required when allowCidrs admits every address (0.0.0.0/0 or ::/0): the database slug
  • denyCidrsstring[] | null
    Client networks refused first, even when allowCidrs admits them
  • listenPortinteger (int64)required
    Port on the server (not 80, 443 or a proxy port)
Response 200 · OK · application/json
PublicPortView
  • allowCidrsstring[] | nullrequired
  • denyCidrsstring[] | nullrequired
  • deployedbooleanrequired
    The proxy publishes the port
  • enabledbooleanrequired
  • hoststring
    The address clients connect to (the server's public IP); empty when the server has none
  • listenPortinteger (int64)
  • newEntrypointbooleanrequired
    The proxy does not listen on this port yet: applying it recreates the proxy container (about a second of dropped connections)
  • openToAllbooleanrequired
    The allow-list admits every address (confirmed with the database slug)
  • routeIdstring
    The route service that holds the port
  • serverIdstring
  • serverNamestring
  • stagedbooleanrequired
    The route has changes that are not deployed yet
  • suggestedPortinteger (int64)required
    A free port to start from when enabling
  • tlsenum: passthroughrequired
    The proxy never terminates TLS on this port
  • warningsstring[] | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictport_in_use
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

DELETE/services/{serviceId}/database/public-port

Close a database's public port

Deletes the route service. A deployed route disappears from the server's table at once.

ParameterInTypeDescription
serviceIdrequiredpathstring
Response 200 · OK · application/json
PublicPortView
  • allowCidrsstring[] | nullrequired
  • denyCidrsstring[] | nullrequired
  • deployedbooleanrequired
    The proxy publishes the port
  • enabledbooleanrequired
  • hoststring
    The address clients connect to (the server's public IP); empty when the server has none
  • listenPortinteger (int64)
  • newEntrypointbooleanrequired
    The proxy does not listen on this port yet: applying it recreates the proxy container (about a second of dropped connections)
  • openToAllbooleanrequired
    The allow-list admits every address (confirmed with the database slug)
  • routeIdstring
    The route service that holds the port
  • serverIdstring
  • serverNamestring
  • stagedbooleanrequired
    The route has changes that are not deployed yet
  • suggestedPortinteger (int64)required
    A free port to start from when enabling
  • tlsenum: passthroughrequired
    The proxy never terminates TLS on this port
  • warningsstring[] | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/public-port/connection

Reveal the external connection string (audited)

Like revealDatabaseExport, but with the server's public IP and the public port instead of the private host. Needs deployments:write, is uncached and recorded as secret.reveal. 409 public_port_disabled; 422 no_public_address when the server has no public IP.

ParameterInTypeDescription
serviceIdrequiredpathstring
Request body · application/json · required
PublicConnectionInputBody
  • keystring
    One of the database's exports; defaults to the engine's connection URL (DATABASE_URL, REDIS_URL, MONGO_URL)
Response 200 · OK · application/json
PublicConnection
  • expiresAtstring (date-time)required
    The value is meant to be shown for this long only; clients must not persist it
  • hoststringrequired
  • keystringrequired
  • portinteger (int64)required
  • revealedAtstring (date-time)required
  • valuestringrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflictpublic_port_disabled
  • 422Unprocessable Entityno_public_address
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/rebuild

Rebuild a replica, or a fenced old primary as a replica

Clones the primary again into a new data volume (the old volume is kept until it is deleted). On a fenced old primary the body may name the new primary to follow. Asynchronous.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serviceIdrequiredpathstring
Request body · application/json · required
RebuildInputBody
  • followServiceIdstring
    For a fenced old primary: the new primary to follow (default: the replica that was promoted)
Response 202 · Accepted · application/json
RebuildResult
  • serviceIdstringrequired
  • statusstringrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/refresh

Ask the agent for the database's version, size and connections

Asynchronous: poll GET /services/{id}/database (or watch the event feed) for the new info.

ParameterInTypeDescription
serviceIdrequiredpathstring
Response 202 · Accepted · application/json
RefreshResult
  • commandIdstringrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

DELETE/services/{serviceId}/database/replica

Remove a read replica

Called on the replica. Deletes its container and data volume, drops its slot, role and pg_hba.conf line on the primary and releases its mesh link. Asynchronous.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serviceIdrequiredpathstring
Response 202 · Accepted · application/json
RemoveResult
  • serviceIdstringrequired
  • statusstringrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/replicas

Add a read replica of a PostgreSQL primary

Creates a read replica service in the primary's environment and clones the primary into it. The replica runs on the primary's server or, with the server mesh enabled on both, on another server. Asynchronous: the replica is pending, then preparing, cloning, deploying and streaming; follow it with GET /services/{id}/database/replication. With dryRun only the plan is returned (status 200). Replication is asynchronous and manual: nothing is detected or switched automatically.

ParameterInTypeDescription
Idempotency-KeyheaderstringClient-chosen key (<=255 chars). A retry with the same key replays the original response for 24 hours.
serviceIdrequiredpathstring
Request body · application/json · required
AddReplicaInputBody
  • acceptMeshChangesboolean
    Confirms that the replica adds tailnet devices (a replication link)
  • dryRunboolean
    Only return the plan
  • namestring
    Display name; defaults to <primary>-replica-<n>
  • serverIdstringrequired
    The server the replica runs on (the primary's server, or another server with the mesh enabled)
Response 202 · Accepted · application/json
AddReplicaResult
  • dryRunbooleanrequired
  • ReplicaPlanrequired
  • serviceIdstring
  • statusstring
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

GET/services/{serviceId}/database/replication

Get the read replica group of a PostgreSQL database

ParameterInTypeDescription
serviceIdrequiredpathstring
Response 200 · OK · application/json
ReplicationView
  • canPromotebooleanrequired
  • ServiceRef
  • PromotionView
  • rebuildablebooleanrequired
    A replica that can be rebuilt, or a fenced old primary that can be rebuilt as a replica
  • ReplicaMemberView[] | nullrequired
  • roleenum: standalone | primary | replica | fencedrequired
  • ReplicaStateView
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/reveal

Reveal a connection string (audited)

Returns one derived export such as DATABASE_URL in plain text, uncached. Requires the deployments:write scope (or admin) and is recorded in the audit log as secret.reveal. Every other read stays masked.

ParameterInTypeDescription
serviceIdrequiredpathstring
Request body · application/json · required
RevealInputBody
  • keystringrequired
    One of the database's exports, e.g. DATABASE_URL
Response 200 · OK · application/json
Revealed
  • expiresAtstring (date-time)required
    The value is meant to be shown for this long only; clients must not persist it
  • keystringrequired
  • revealedAtstring (date-time)required
  • valuestringrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/rotate-credentials

Rotate the database password

Changes the application password inside the running database through the agent (or, for Valkey and Redis, stages a new password), updates the variable and stages every service that references the database. Nothing is deployed. With dryRun only the plan is returned.

ParameterInTypeDescription
serviceIdrequiredpathstring
Request body · application/json · required
RotateInputBody
  • dryRunboolean
    Only return the plan
Response 200 · OK · application/json
RotationResult
  • commandIdstring
  • dryRunbooleanrequired
  • RotationPlanrequired
  • rotationIdstring
  • statusenum: planned | pending | appliedrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/upgrade

Upgrade the database version

In-place engines stage the new image. PostgreSQL majors are converted with pg_upgrade into a new volume (the old volume is kept) and the new version is staged when the conversion finishes. Take a backup first.

ParameterInTypeDescription
serviceIdrequiredpathstring
Request body · application/json · required
UpgradeInputBody
  • confirmstringrequired
    Must equal the service slug
  • targetVersionstringrequired
Response 200 · OK · application/json
UpgradeResult
  • commandIdstring
  • UpgradePlanrequired
  • statusenum: staged | pendingrequired
  • upgradeIdstring
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.

POST/services/{serviceId}/database/upgrade/plan

Plan a version upgrade

ParameterInTypeDescription
serviceIdrequiredpathstring
Request body · application/json · required
UpgradePlanInputBody
  • targetVersionstringrequired
Response 200 · OK · application/json
UpgradePlan
  • blockersstring[] | nullrequired
  • downtimestringrequired
  • enginestringrequired
  • executablebooleanrequired
  • fromstringrequired
  • helperImagestring
  • imagestring
  • kindstringrequired
  • methodstringrequired
  • stepsstring[] | nullrequired
  • tostringrequired
  • warningsstring[] | nullrequired
Errors
  • 401Unauthorized
  • 403Forbidden
  • 404Not Found
  • 409Conflict
  • 422Unprocessable Entity
  • 500Internal Server Error

Errors are RFC 9457 application/problem+json with a stable code field.