Skip to main content

Organization Admin API

Programmatic access to organization administration: user management, roles and groups, OAuth clients, webhooks, audit logs, social providers, agents, permissions, settings, analytics, and sessions. Authentication uses an API key or an OAuth 2.0 access token obtained with the client credentials grant. That grant is a server-to-server sign-in: the application presents its own client ID and secret, with no user involved.

Administrative access and scopes required

Every endpoint here checks two things. The credential's owner must hold the endpoint's own permission in the organization (for example users.view; see Required permissions). The credential must also carry a scope that covers the endpoint: admin:<resource>:<read|write> on an API key, or the same scope or the blanket admin on an access token. Missing either gives 403. Neither credential creates a browser session. See Credentials and access model.

Table of Contents​

Getting Started​

Prerequisites​

  1. A LumoAuth organization (identified by a slug, e.g., acme-corp)
  2. An admin user holding the permissions for the endpoints that you call (settings.manage alone is not enough)
  3. Either an API key with the scopes that you need (the simplest path, see Creating an API Key) or an access token that carries an admin scope

Quick Start​

# 1. Obtain an access token using client credentials.
# The client must be a first-party client allowed the 'admin' scope (or a
# narrower admin:<resource>:<read|write> scope); request it explicitly.
curl -X POST 'https://app.lumoauth.dev/orgs/acme-corp/api/v1/oauth/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&scope=admin'

# 2. Use the token to list users
curl 'https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/users' \
-H 'Authorization: Bearer YOUR_ACCESS_TOKEN'

Authentication​

Every Admin API endpoint accepts either of two credentials (see the OpenAPI BearerAuth / ApiKeyAuth security schemes):

1. OAuth 2.0 access token — obtained via the client credentials grant (see the Quick Start above). The token must carry admin or an admin:<resource>:<read|write> scope; an openid profile email token is refused with 403 even for administrators. Details: Admin API scopes for Bearer tokens.

Authorization: Bearer YOUR_ACCESS_TOKEN

2. Organization API key — sent in either of these equivalent forms (keys carry the lmk_ prefix):

X-API-Key: lmk_your_api_key_here
Authorization: ApiKey lmk_your_api_key_here

Creating an API Key​

  1. Navigate to your organization portal at /orgs/{orgId}/portal/settings/api-keys (API keys under Applications & developer tools in the sidebar)
  2. Click "Create API key"
  3. Select only the scopes that your use case needs (admin:users:read for a read-only report; add the :write scope only when the job changes data). A read scope cannot change data, and a scope for a single resource cannot reach other resources. Full list: API key scopes
  4. Click Create API key, then copy and securely store the generated API key (it is shown only once)

The Create API key form with the name, description and expiration

Secure Your API Keys

Store your client secrets and access tokens securely. Never commit them to source control or expose them in client-side code.

Required Permissions​

To access the Admin API, the user behind the credential (the API key's creator, or the token's subject) must:

  1. Belong to the organization being accessed
  2. Be active and hold the permission that the endpoint declares. The full list is in Required permissions

This is re-checked on every request. If the key's creator is deactivated or loses a permission, the key stops working for the endpoints that need it. A 403 names the missing permission in details.required_permissions.

Credentials never create a session​

Requests authenticated with an API key or a Bearer token are stateless: no session cookie is set, and the credential must be sent on every call. Both are refused (403) on the portal and account pages, which only accept an interactive browser login.

Common mistakes​

ResponseCauseFix
403 with an OAuth token from an ordinary appToken has no admin scopeRequest admin or admin:<resource>:<read|write> on a first-party client, or use an API key
403 Insufficient scope with an API key; body lists required_scopesKey lacks the resource or :write scopeCreate a key with the listed scope
403 Access denied: missing required permission with details.required_permissionsCredential owner lacks the endpoint's permissionGrant the listed permission, or create the key under an admin who holds it
400 invalid_request with details.rejected_keys on PATCH /organizationsettings contained a key outside the allow-list or a reserved *_secret/*_token/*_key suffixSend only the writable settings keys

Base URL Structure​

All Admin API endpoints follow this pattern:

/orgs/{orgId}/api/v1/admin/{resource}

Where:

  • \{orgId\} is the unique identifier for your organization
  • \{resource\} is the resource type (users, roles, clients, etc.)

Example Environments​

EnvironmentBase URL
Productionhttps://app.lumoauth.dev/orgs/\{orgId\}/api/v1/admin
EU Productionhttps://eu.app.lumoauth.dev/orgs/\{orgId\}/api/v1/admin

Common Patterns​

Pagination​

All list endpoints support pagination:

ParameterTypeDefaultDescription
pageinteger1Page number (1-indexed)
limitinteger25Items per page (max: 100)

Response Format:

{
"data": [...],
"meta": {
"total": 100,
"page": 1,
"limit": 25,
"totalPages": 4,
"hasNextPage": true,
"hasPreviousPage": false
}
}

Filtering​

Many endpoints support filtering via query parameters:

# Filter users by role and active status
GET /admin/users?role=admin&active=true

# Search across fields
GET /admin/users?search=john

Sorting​

List endpoints typically support sorting:

GET /admin/users?sortBy=createdAt&sortDir=DESC

ID Lookup​

User endpoints accept the user's UUID or email address in the path:

  • UUID: /admin/users/01234567-89ab-cdef-0123-456789abcdef
  • Email: /admin/users/john@example.com

Roles, groups and permissions accept their id or slug: /admin/roles/admin.

Error Handling​

All errors follow a consistent format. error is a machine-readable string code (not a boolean), message is a human-readable description, status echoes the HTTP status, and details is an optional object with field-level context:

{
"error": "validation_error",
"message": "Human-readable error description",
"status": 422,
"details": {
"missing_fields": ["email"],
"invalid_values": {
"status": "Must be one of: active, inactive, suspended"
}
}
}

Status Codes and Error Codes​

Each HTTP status maps to a stable error code that your code can branch on. See API Error Reference for the complete list.

CodeMeaningerror code
200Success—
201Created—
400Bad Request - Invalid inputinvalid_request
401Unauthorized - Missing or invalid credentialsunauthorized
403Forbidden - Insufficient permissionsforbidden
404Not Found - Resource doesn't existnot_found
409Conflict - Resource already existsconflict
422Unprocessable Entity - Validation failedvalidation_error
429Too Many Requests - Rate limitedrate_limit_exceeded
500Internal Server Errorserver_error
503Service Unavailabletemporarily_unavailable

Rate Limiting​

The Admin API is rate limited per credential to prevent abuse. When rate limited, you receive a 429 Too Many Requests response with the error code rate_limit_exceeded and a Retry-After header giving the number of seconds to wait before retrying. There are no per-request quota headers on successful responses.

API Reference​

Available Resources​

ResourceEndpointDescription
Users/admin/usersCreate, update, search users. Reset passwords, view MFA enrollment, block/unblock accounts
Roles/admin/rolesDefine and manage roles. Assign permissions, view role members
Groups/admin/groupsOrganize users into groups. Assign roles, manage memberships
Permissions/admin/permissionsCreate custom permissions and scopes for fine-grained access control
OAuth Clients/admin/clientsRegister OAuth 2.0 clients, configure grants and redirects, rotate secrets
Webhooks/admin/webhooksSubscribe to events, test endpoints, manage webhook secrets
Social Providers/admin/social-providersConfigure social login (Google, GitHub, etc.) with client credentials
AI Agents/admin/agentsRegister AI agents, generate tokens, manage agent lifecycle
Audit Logs/admin/audit-logsQuery audit events, export logs, view statistics
Sessions/admin/sessionsView active sessions, revoke tokens, manage user sessions
Settings/admin/settingsRead every area at once, or one area under /admin/settings/{general|authentication|security|email|branding|scim}; the organization profile is /admin/organization
Analytics/admin/analyticsDashboard metrics, login trends, statistics on user activity

Users​

Manage users within your organization.

List Users​

GET /admin/users

Create User​

POST /admin/users
Content-Type: application/json

{
"email": "newuser@example.com",
"username": "newuser",
"name": "New User",
"password": "SecurePassword123!",
"isActive": true,
"emailVerified": false,
"roles": ["user", "editor"],
"groups": ["engineering"]
}

Update User​

Accepts PUT or PATCH; both send only the fields to change (email, name, givenName, familyName, phoneNumber, picture, locale, zoneinfo, isActive, emailVerified, password).

PATCH /admin/users/{userId}
Content-Type: application/json

{
"name": "Updated Name",
"isActive": true,
"emailVerified": true
}

Block/Unblock User​

POST /admin/users/{userId}/block
POST /admin/users/{userId}/unblock

Set User Password​

PUT /admin/users/{userId}/password
Content-Type: application/json

{
"password": "NewSecurePassword123!"
}

The password must satisfy the organization's password policy and the breached-password check. To let the user choose their own instead, POST /admin/users/{userId}/password-reset sends them a reset email.

Roles​

Manage roles and their permissions.

Create Role​

POST /admin/roles
Content-Type: application/json

{
"name": "Content Manager",
"slug": "content-manager",
"description": "Can manage content and publications",
"permissions": ["content.read", "content.write", "content.publish"]
}

Groups​

Manage user groups.

Create Group​

POST /admin/groups
Content-Type: application/json

{
"name": "Engineering Team",
"slug": "engineering",
"description": "All engineering staff",
"roles": ["developer"]
}

OAuth Clients​

Manage OAuth 2.0 clients for your applications.

Create Client​

POST /admin/clients
Content-Type: application/json

{
"name": "Mobile App",
"redirectUris": [
"myapp://callback",
"https://myapp.example.com/callback"
],
"scopes": ["openid", "profile", "email", "offline_access"],
"grantTypes": ["authorization_code", "refresh_token"],
"isConfidential": false,
"requiresPkce": true
}

isConfidential: false marks a public client (one that cannot keep a secret, such as a mobile or single-page app). requiresPkce enforces PKCE, a one-time secret that protects the sign-in code for such clients. Enable or disable a client later with POST /admin/clients/{clientId}/enable and /disable.

Response:

{
"data": {
"id": 42,
"clientId": "app_mobile_abc123",
"secret": "secret_xyz789",
"name": "Mobile App",
"_note": "Store the secret securely. It will not be shown again."
},
"message": "OAuth client created successfully"
}

Rotate Client Secret​

POST /admin/clients/{clientId}/rotate-secret

Generates a new client secret; the old one stops working immediately.

{
"data": {
"clientId": "app_mobile_abc123",
"secret": "new_secret_def456",
"_note": "Store the new secret securely. It will not be shown again."
},
"message": "Client secret rotated successfully"
}

Webhooks​

Configure webhooks to receive notifications of events in real time.

List Available Events​

GET /admin/webhooks/events

Create Webhook​

POST /admin/webhooks
Content-Type: application/json

{
"url": "https://api.example.com/webhooks/lumoauth",
"events": ["user.created", "user.login", "user.login_failed"],
"type": "custom",
"isActive": true
}

The response includes the webhook's HMAC signing secret once (data.secret, with a _note); event names are the ones GET /admin/webhooks/events lists.

Test Webhook​

POST /admin/webhooks/{webhookId}/test

Rotate Webhook Secret​

POST /admin/webhooks/{webhookId}/rotate-secret

Generates a new webhook secret for signature verification.

{
"data": {
"id": 42,
"secret": "new-signing-secret",
"_note": "Store the new secret securely. It will not be shown again."
},
"message": "Webhook secret rotated successfully"
}

Audit Logs​

Access and export audit logs for compliance and monitoring.

List Audit Logs​

GET /admin/audit-logs

Export Audit Logs​

GET /admin/audit-logs/export?format=csv&from=2024-01-01T00:00:00Z&to=2024-01-31T23:59:59Z

Formats: csv (default), json. Export is limited to 10,000 records per request.

Social Providers​

Configure social login providers (Google, GitHub, Microsoft, etc.).

AI Agents​

Manage AI/machine agents for programmatic access.

Permissions & Scopes​

Manage custom permissions and OAuth scopes.

Settings​

Configure organization-wide settings including authentication, branding, and more.

Analytics​

Access analytics and dashboard data.

Sessions & Tokens​

Manage active sessions and access tokens.

Quick Examples​

Create a Complete User with Roles and Groups​

curl -X POST "https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/users" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"email": "developer@acme.com",
"name": "Jane Developer",
"password": "SecureP@ssword123",
"roles": ["developer", "user"],
"groups": ["engineering"],
"emailVerified": true,
"isActive": true
}'

Set Up a New OAuth Client​

# Create the client
CLIENT=$(curl -X POST "https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/clients" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Web App",
"redirectUris": ["https://app.acme.com/callback"],
"scopes": ["openid", "profile", "email", "offline_access"],
"grantTypes": ["authorization_code", "refresh_token"],
"isConfidential": true,
"requiresPkce": true
}')

# Extract and save the credentials
echo $CLIENT | jq -r '.data.clientId' > client_id.txt
echo $CLIENT | jq -r '.data.secret' > client_secret.txt # Store securely!

Configure Webhooks for User Events​

# Create webhook
curl -X POST "https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/webhooks" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.acme.com/webhooks/auth",
"events": ["user.created", "user.updated", "user.deleted", "user.login"],
"isActive": true
}'

# Test the webhook
curl -X POST "https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/webhooks/1/test" \
-H "Authorization: Bearer $ACCESS_TOKEN"

The same calls are available from the CLI: lumo webhooks create --url … --events user.created,user.login and lumo api POST /webhooks/1/test.

Complete API Reference

For the full interactive OpenAPI specification with all endpoints, request/response schemas, and example payloads, see the API Specification page.

Standards used on this page​

Plain nameStandard
OAuth 2.0 (the core sign-in and token protocol)RFC 6749

See the standards reference for what each one covers and how LumoAuth uses it.