Skip to main content
Version: Nightly

User Management API

Use these HTTP endpoints to manage accounts after enabling the built-in user provider on a standalone server or frontend. Requests and responses use JSON. Send Content-Type: application/json when creating or updating a user.

Authentication and Catalog Scope​

Every endpoint requires authentication. Most require the Admin privilege; authenticated users can also retrieve their own information.

Use HTTP Basic authentication with a local or LDAP account:

curl -u '<username>:<password>' \
'http://localhost:4000/v1/users/current'

When the jwt_auth plugin is configured, you can use a bearer token instead:

curl -H 'Authorization: Bearer <token>' \
'http://localhost:4000/v1/users/current'

The token must identify an existing user. See External Authentication for the relationship between authentication plugins and stored user permissions.

All /v1/users operations use the request's current catalog, which defaults to greptime. Usernames are unique within a catalog. Select another catalog with the db query parameter or x-greptime-db-name header, using the <catalog>-<database> format:

curl -u '<admin-user>:<admin-password>' \
'http://localhost:4000/v1/users?db=tenant_a-public'

The equivalent header is x-greptime-db-name: tenant_a-public. If both are present, the header takes precedence. Authentication looks up the user in the selected catalog. The catalog field in a create request must match this catalog; it does not select a different target.

In standalone leader-follower deployments, send management requests to the ready leader. Follower reads may use cached credentials and permissions after user changes.

Endpoints​

MethodPathAccessSuccess status
GET/v1/usersAdmin200
GET/v1/users/currentAny authenticated user200
GET/v1/users/{username}Admin or the named user200
POST/v1/usersAdmin201
PUT/v1/users/{username}Admin200
DELETE/v1/users/{username}Admin200
POST/v1/jwks/refreshAdmin200

User Object​

User lookups return the following object. Listing users returns an array of these objects. Passwords, password hashes, and protocol verifiers are not included in responses.

FieldTypeDescription
usernamestringUsername within the catalog.
catalogstringCatalog where the account is stored.
auth_sourcestringPassword authentication source: local or ldap.
privilegesunsigned 32-bit integerPrivilege bitmask.
acl_mapobjectDatabase and table ACLs.
created_atsigned 64-bit integerCreation time, in Unix milliseconds.
updated_atsigned 64-bit integerLast update time, in Unix milliseconds.
{
"username": "alice",
"catalog": "greptime",
"auth_source": "local",
"privileges": 8,
"acl_map": {
"public": [{"type": "match", "table": "cpu_metrics"}]
},
"created_at": 1705312345678,
"updated_at": 1705312345678
}

Privileges​

Combine flags with bitwise OR. For example, SqlSelect | SqlInsert is 8 | 16 = 24. Unknown bits are rejected. The default value 0 grants no global privileges. Admin grants full administrative privileges and bypasses ACL checks.

PrivilegeValue
TableCreate1
TableAlter2
TableDrop4
SqlSelect8
SqlInsert16
SqlDelete32
FlowCreate256
FlowDrop512
DatabaseCreate1024
DatabaseAlter2048
DatabaseDrop4096
Admin8192
TriggerCreate16384
TriggerDrop32768
TriggerAlter65536

See Privileges and ACLs for the operations each flag permits and how privileges interact with ACLs.

ACL Map​

The acl_map object maps database (schema) selectors to arrays of table ACL entries. An ordinary key such as public selects an exact database name. A key beginning with ~regex: selects databases by regular expression.

EntryFieldsAccess
{"type": "all"}No additional fieldsAll tables in matching databases.
{"type": "match", "table": "cpu_metrics"}table: stringThe table with that exact name.
{"type": "regex", "pattern": "^cpu_.*$"}pattern: stringTables whose names match the regular expression.

Database regular expressions match the entire name. Table regular expressions match substrings unless anchored with ^ and $. Entries from overlapping database selectors are combined; an all entry grants access to every table in that database. Invalid regular expressions and empty database regular expressions are rejected.

For example, this map grants access to cpu_metrics in public and every table in databases named tenant_1, tenant_42, and so on:

{
"public": [{"type": "match", "table": "cpu_metrics"}],
"~regex:tenant_[0-9]+": [{"type": "all"}]
}

For non-admin users, {} grants no access to ordinary databases. Empty arrays grant no table access and are omitted when create and update requests are stored. System-schema access and database creation have separate rules; see Privileges and ACLs.

List Users​

GET /v1/users requires Admin and returns a JSON array of user objects in the current catalog. The result is not paginated.

curl -u '<admin-user>:<admin-password>' \
'http://localhost:4000/v1/users'

Success: 200 OK. Each array element has the user object format.

Get the Current User​

GET /v1/users/current returns the authenticated user's information. It does not require Admin.

curl -u '<username>:<password>' \
'http://localhost:4000/v1/users/current'

Success: 200 OK with a user object from the authentication context.

Get a User​

GET /v1/users/{username} returns the named user in the current catalog. Admins can retrieve any user; other users can retrieve only their own information.

curl -u '<admin-user>:<admin-password>' \
'http://localhost:4000/v1/users/alice'

Success: 200 OK with a user object. A missing user returns 404.

Create a User​

POST /v1/users requires Admin.

FieldTypeRequiredDefaultDescription
usernamestringYes—Must match ^[a-zA-Z][a-zA-Z0-9_]*$.
passwordstringFor local users—Local password, 6 to 64 characters. Omit for LDAP users.
auth_sourcestringNo"local""local" or "ldap".
catalogstringNoCurrent catalogMust match the request's current catalog if supplied.
privilegesunsigned 32-bit integerNo0Privilege bitmask.
acl_mapobjectNo{}Database and table ACLs.

Create a local user that can read public.cpu_metrics:

curl -X POST -u '<admin-user>:<admin-password>' \
'http://localhost:4000/v1/users' \
-H 'Content-Type: application/json' \
-d '{
"username": "alice",
"password": "alice_password",
"privileges": 8,
"acl_map": {
"public": [{"type": "match", "table": "cpu_metrics"}]
}
}'

To register an LDAP user, configure the ldap_auth plugin and send a body such as the following to the same endpoint. LDAP users must not have a local password.

{
"username": "directory_reader",
"auth_source": "ldap",
"privileges": 8,
"acl_map": {
"public": [{"type": "all"}]
}
}

Success: 201 Created.

{"message": "User created successfully"}

An existing username in the current catalog returns 409 Conflict.

Update a User​

PUT /v1/users/{username} requires Admin. Supply at least one field with a non-null value. Omitted fields retain their current values.

FieldTypeDescription
passwordstringNew local password, 6 to 64 characters. LDAP password updates are rejected.
privilegesunsigned 32-bit integerReplaces the entire privilege bitmask.
acl_mapobjectReplaces the entire ACL map; entries are not merged with the stored map.

This example grants read and insert privileges and replaces the ACL with access to all tables in public:

curl -X PUT -u '<admin-user>:<admin-password>' \
'http://localhost:4000/v1/users/alice' \
-H 'Content-Type: application/json' \
-d '{
"privileges": 24,
"acl_map": {"public": [{"type": "all"}]}
}'

Success: 200 OK.

{"message": "User updated successfully"}

The username, catalog, and authentication source cannot be changed through this endpoint. Removing Admin from the protected admin account returns 403 and rejects the entire update, including password or ACL changes in the same request. A missing user returns 404. Concurrent updates can return 409; read the latest user information before deciding whether to retry.

Delete a User​

DELETE /v1/users/{username} requires Admin. You cannot delete your own account or the protected admin account; these requests return 403.

curl -X DELETE -u '<admin-user>:<admin-password>' \
'http://localhost:4000/v1/users/alice'

Success: 200 OK.

{"message": "User 'alice' deleted successfully"}

A missing user returns 404.

Refresh JWKS Keys​

POST /v1/jwks/refresh requires Admin and requests an immediate refresh of the JWT verification keys from the configured JWKS URL. It refreshes only the server receiving the request.

curl -X POST -u '<admin-user>:<admin-password>' \
'http://localhost:4000/v1/jwks/refresh'

Success: 200 OK, with the number of usable keys in the current key set:

{"keys": 2}

If JWT authentication is disabled or uses a static key instead of a JWKS URL, the endpoint returns 400. A failed refresh returns 502 and keeps the previous cached key set.

Errors​

Validation and user-management errors include an error message:

{"error": "User 'alice' already exists"}

Authentication and server errors can also include code and execution_time_ms fields. Use the HTTP status to distinguish error categories.

StatusMeaning
400 Bad RequestMalformed JSON, invalid username, password, privilege bits, or ACLs; mismatched catalog; empty update; or an unsupported mutation. Also returned when JWKS refresh is not configured.
401 UnauthorizedMissing or invalid credentials, invalid token, or authentication denied for the selected catalog/database.
403 ForbiddenInsufficient privileges or a protected-account operation.
404 Not FoundThe requested user does not exist.
409 ConflictDuplicate username or a concurrent update conflict.
413 Payload Too LargeRequest body exceeds the server's limit.
415 Unsupported Media TypeMissing or unsupported JSON content type on a create or update request.
422 Unprocessable EntityJSON does not match the request schema, such as a missing required field, wrong field type, or unsupported auth_source.
500 Internal Server ErrorServer or metadata operation failed.
502 Bad GatewayJWKS refresh failed; the previous key set is retained.