Skip to main content
A database with managed SQL roles can have up to ten additional roles next to its owner, runtime and readonly logins. Each additional role has its own generated username, password, access profile and connection limit. See Database roles for the profiles and how to grant a Custom role access. For a single-login database that opted in to additional roles, use the additional roles API for existing databases instead. API access requires Pro or Business. Every endpoint on this page accepts a full-account key or a key scoped to selected databases that includes this database; see Authentication. Every response, including errors, is sent with Cache-Control: no-store. Only the credentials endpoint returns a password. {id} and {roleId} must be lowercase UUIDs. Endpoints that take no body reject a non-empty body with 400 VALIDATION_ERROR.

The role object

reserved means a create has not finished; see Reconcile an unfinished create. updating means a rotation or revocation is pending. expired means the credential’s validity period has ended; it can no longer be revealed or rotated.

List roles

200 OK
Roles are ordered by ordinal. Revoked roles are left out unless you add ?includeRevoked=true. Removed roles are never listed.

Create a role

The body must contain exactly these three fields: The Idempotency-Key header is required: 1–200 characters, without line breaks or NUL characters, and not starting with dbhost-internal-. A successful create finishes setup in the same call and returns the role as ready. The response contains no password; use Reveal the password.
200 OK
All three profiles get CONNECT on the database and can log in immediately. read_only also gets SELECT and read_write gets DML. A custom role gets no table grants; grant access from your migrations as the owner role. DBHost never grants an additional role CREATE or TEMPORARY. Reuse the same idempotency key after a timeout or an uncertain result. The same key with the same body returns the same role and resumes its setup; the same key with a different body returns 409 MANAGED_ROLE_CONFLICT. Creation is refused with 409 MANAGED_ROLE_CONFLICT when:
  • the database already has ten roles. Revoked roles still count; delete one to free its slot
  • the display name is already in use
  • another role on the database is still reserved, or a credential change on the database is unfinished
  • a restore of the database is in progress
  • the database is not active
  • the database would have four or more additional roles, or the new limit takes the total above the database’s role budget, and the database has no effective server connection cap
If the CONNECT grant was withdrawn during setup, the response is 409 CONNECT_GRANT_REQUIRED with the SQL the database owner can run, then retry the same request:
409 Conflict
A database cloned from a backup that predates additional-role support returns 409 CUSTOM_ROLE_REQUIRES_V3_CLONE. Make a new clone from a newer backup of the source database before adding roles.

Rename a role

The body must contain exactly displayName, with the same rules as on create. Only the label changes; the username, password and grants stay the same. The role must be ready or revoked.
200 OK

Reveal the password

Send no body. The role must be ready, without a pending change, and not expired. Each reveal is recorded in the account’s audit log.
200 OK
Connect with TLS. Store the password in a secret manager and keep it out of logs and source control.

Rotate or revoke

The body must contain exactly kind (rotate or revoke) and confirmDisconnect: true. The Idempotency-Key header follows the same rules as on create.
Rotation and revocation close the role’s open connections. Open transactions on those connections roll back.
rotate sets a new password. revoke disables the login; the role keeps its slot until you delete it. The role must be ready, and a rotation also needs an unexpired credential. Changes are refused while a restore of the database is in progress or another credential change on the database is unfinished.
202 Accepted
The status code is 202 while status is pending and 200 when it is completed. credentialGeneration is the generation the change produces. Retry with the same key and body after an uncertain result; a different kind on the same key is refused.

Read a change

Returns 200 with the same fields as above. It does not advance the change.

Reconcile a change

The body must be exactly {"confirmDisconnect": true}. DBHost replays the recorded change and returns 202 while pending or 200 when completed. A change that has already completed is not applied again.

Delete a role

The body must be exactly {"confirm": true}. A ready role is revoked first, which closes its open connections, then removed from PostgreSQL. A revoked role is removed directly. Repeat the same call to continue a pending delete. DBHost does not cascade through your objects. If the role still owns objects or holds grants, the role stays revoked and the response lists what to clean up:
409 Conflict
kind is grant, owned_object, policy, other or other_database. At most 20 entries are returned; truncated: true means there are more. Revoke the grants or reassign the objects as the owner role, then call delete again.

Remove a revoked role

Send no body. This removes a role that is already revoked and returns 200 with {"roleId": "...", "status": "removed"}, or 202 with {"roleId": "...", "status": "pending"} while removal runs. Remaining dependencies return 409 ROLE_DEPENDENCIES without the list; use the /delete endpoint above to see it.

Reconcile an unfinished create

A create that was interrupted can leave a role in reserved. Retrying the original create with the same idempotency key and body is the simplest way to finish it. The two step endpoints are also available. Both take no body. POST /api/v1/databases/{id}/custom-roles/{roleId}/prepare creates the PostgreSQL role and returns 202:
202 Accepted
POST /api/v1/databases/{id}/custom-roles/{roleId}/admit applies the profile’s grants and opens the login. It returns 200 with the same fields and "status": "ready", or 409 CONNECT_GRANT_REQUIRED with grantSql as shown under Create a role. Neither step is needed after a successful create.

Errors

Dashboard and CLI

The same actions are on the database detail page under Additional roles on every plan. The CLI provides them as dbhost managed custom-* commands; see CLI.