Users
Endpoints for managing user accounts including listing, creating, updating, and deleting users.
Endpoints for managing user accounts including listing, creating, updating, and deleting users.
List Users
GET
/users
List all user accounts.
Parameters
| Name | Type | Description |
|---|---|---|
| page optional | integer | Page number for pagination (default: 1) |
| per_page optional | integer | Number of results per page (default: 20, max: 100) |
Response Codes
200
Success
401
Unauthorized
403
Forbidden
Get User
GET
/users/{username}
Get user details.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to retrieve |
Response Codes
200
Success
401
Unauthorized
404
User not found
Create User
POST
/users
Create a new user account.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | Unique username |
| password required | string | User password |
| email required | string | User email address |
| fullname optional | string | Full display name |
| state optional | string | Account state (e.g. enabled, disabled) |
| access optional | object | Permission access object |
JSON
{"username": "editor", "password": "SecurePass123!", "email": "[email protected]", "fullname": "Jane Editor"}
Response Codes
201
User created
401
Unauthorized
409
Username already exists
422
Validation error
Update User
PATCH
/users/{username}
Update a user account.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to update (path parameter) |
| email optional | string | Updated email address |
| fullname optional | string | Updated full display name |
| state optional | string | Updated account state |
| access optional | object | Updated permission access object |
| password optional | string | New password |
Response Codes
200
User updated
401
Unauthorized
404
User not found
422
Validation error
Delete User
DELETE
/users/{username}
Delete a user account.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to delete |
Response Codes
204
User deleted
401
Unauthorized
403
Forbidden
404
User not found
Upload Avatar
POST
/users/{username}/avatar
Upload a custom avatar image for a user. Send as multipart/form-data.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to upload the avatar for |
| avatar required | file | Image file (JPEG, PNG, GIF, or WebP) |
JSON
{"data": {"username": "admin", "email": "[email protected]", "avatar": {"name": "admin-a1b2c3d4.jpg", "type": "image/jpeg"}}}
Response Codes
201
Avatar uploaded
401
Unauthorized
403
Forbidden
404
User not found
422
Validation error (no file or invalid image type)
Delete Avatar
DELETE
/users/{username}/avatar
Remove the custom avatar for a user.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to remove the avatar for |
Response Codes
200
Avatar removed
401
Unauthorized
403
Forbidden
404
User not found
Generate 2FA Secret
POST
/users/{username}/2fa
Generate or regenerate a TOTP two-factor authentication secret and return a QR code data URI.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to generate 2FA for |
JSON
{"data": {"secret": "JBSW Y3DP EHPK 3PXP", "qr_code": "data:image/png;base64,..."}}
Response Codes
200
Secret generated
401
Unauthorized
403
Forbidden
404
User not found
500
Login plugin with 2FA support not installed
List API Keys
GET
/users/{username}/api-keys
List all API keys for a user. Key secrets are not returned.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to list API keys for |
JSON
{"data": [{"id": "abc123", "name": "CI Deploy Key", "scopes": [], "created": 1710000000}]}
Response Codes
200
Success
401
Unauthorized
403
Forbidden
404
User not found
Create API Key
POST
/users/{username}/api-keys
Generate a new API key for a user. The raw key is returned only once in the response.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username to create the API key for |
| name optional | string | A descriptive name for the API key |
| scopes optional | array | List of permission scopes for the key |
| expiry_days optional | integer | Number of days until the key expires. Omit or set to null for no expiry. |
JSON
{"name": "CI Deploy Key", "scopes": [], "expiry_days": 90}
JSON
{"data": {"id": "abc123", "name": "CI Deploy Key", "api_key": "grav_...", "scopes": [], "created": 1710000000}}
Response Codes
201
API key created
401
Unauthorized
403
Forbidden
404
User not found
Revoke API Key
DELETE
/users/{username}/api-keys/{keyId}
Revoke and delete an API key.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | The username who owns the API key |
| keyId required | string | The ID of the API key to revoke |
Response Codes
204
API key revoked
401
Unauthorized
403
Forbidden
404
API key not found
Enable 2FA
POST
/users/{username}/2fa/enable
Verify a TOTP code against the previously generated secret and mark 2FA as enabled on the account. Only the account owner can enable 2FA on their own account (not admins). Fires `onApiUser2faEnabled`.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | Username (path param). |
| code required | string | Current 6-digit TOTP code from the authenticator app. |
JSON
{"code": "123456"}
JSON
{"data": {"twofa_enabled": true}}
Response Codes
200
2FA enabled.
400
Missing code, invalid code, or no 2FA secret generated yet (call `POST /users/{username}/2fa` first).
401
Unauthorized.
403
Only the account owner can enable 2FA.
404
User not found.
500
Login plugin with 2FA support not installed.
Disable 2FA
POST
/users/{username}/2fa/disable
Disable 2FA on an account. Self-disable requires a valid current TOTP code — this stops a stolen session from unilaterally removing 2FA. Admins with `api.users.write` (or superadmin) can force-disable without a code, for lost-device recovery. Both paths clear the `twofa_secret`. Fires `onApiUser2faDisabled` with `forced_by_admin` flag.
Parameters
| Name | Type | Description |
|---|---|---|
| username required | string | Username (path param). |
| code optional | string | Current TOTP code. Required for self-disable; ignored for admin-forced disable. |
JSON
{"code": "123456"}
JSON
{"data": {"twofa_enabled": false}}
Response Codes
200
2FA disabled.
400
Missing/invalid code (self-disable path only).
401
Unauthorized.
403
Caller is neither the account owner nor holds `api.users.write`.
404
User not found.
500
Login plugin with 2FA support not installed.