Skip to main content

Organization Settings

GET /orgs/{orgId}/api/v1/admin/organization
PUT /orgs/{orgId}/api/v1/admin/organization
PATCH /orgs/{orgId}/api/v1/admin/organization
GET /orgs/{orgId}/api/v1/admin/settings/auth
PUT /orgs/{orgId}/api/v1/admin/settings/auth
PATCH /orgs/{orgId}/api/v1/admin/settings/auth
GET /orgs/{orgId}/api/v1/admin/settings/branding
PUT /orgs/{orgId}/api/v1/admin/settings/branding
PATCH /orgs/{orgId}/api/v1/admin/settings/branding
GET /orgs/{orgId}/api/v1/admin/settings/scim
PUT /orgs/{orgId}/api/v1/admin/settings/scim
PATCH /orgs/{orgId}/api/v1/admin/settings/scim
note

All endpoints on this page need an API key or a Bearer token with admin:settings:read (GET) or admin:settings:write (PUT/PATCH), and a permission: settings.view to read, settings.manage to change the organization and its authentication settings, branding.view/branding.edit for branding and scim.view/scim.edit for SCIM. See Required permissions.

Use this page to read your organization's profile, change its name and the handful of organization-level settings that are safe to change over the API, and manage the authentication, branding and SCIM blocks. The general, security and email blocks are on the Settings page.

Secrets in responses​

No settings response on this page returns credential material. Every non-empty value under a secret-looking key (names ending in secret, password, token, tokens, hash, key, credentials, or containing private_key; public_key, *_preview and *_at stay readable) is replaced with a marker:

{ "bearer_token_hash": { "configured": true, "redacted": true } }

You can PATCH a fetched payload back unchanged: a marker leaves the stored value as it is. To change a secret, send the new value in place of the marker.

Get Organization Info​

Get Organization
curl https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/organization \
-H "Authorization: ApiKey lmk_abc123"

The response is wrapped in a data envelope. The organization id is an integer; settings may be null when no organization-level settings have been saved.

Organization Object
{
"data": {
"id": 4,
"slug": "acme-corp",
"name": "ACME Corp",
"status": "active",
"settings": null,
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-03-01T08:00:00Z"
}
}

Update Organization​

Update Organization Name
curl -X PATCH https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/organization \
-H "Authorization: ApiKey lmk_abc123" \
-H "Content-Type: application/json" \
-d '{ "name": "ACME Corporation" }'

Writable settings keys​

PUT and PATCH behave the same: name replaces the organization name, and settings is merged into the stored settings one top-level key at a time. Only these top-level keys are accepted:

KeyTypeWhat it controls
display_name (alias displayName)stringName shown on hosted pages
timezonestringIANA time zone
localestringDefault locale
securityobjectOAuth hardening switches such as dpop_require_nonce; see Security settings
emailobjectOutbound e-mail settings; see Email settings
audit_log_retention_daysintegerAudit log retention
audit_log_auto_deletebooleanPurge audit logs past retention automatically
agent_governanceobjectAgent governance defaults; see Governance

Everything else is refused. The request fails as a whole, nothing is written, and the response lists every offending path in details.rejected_keys:

  • any top-level key not in the table (for example sandbox, allow_shared_signing_key, include_global_jwks, allow_root_admin_login, slug, status);
  • any key at any depth whose name ends in _hash, _secret, _token, _key or _password (for example security.scim_token).
Rejected update
curl -X PATCH https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/organization \
-H "Authorization: ApiKey lmk_abc123" \
-H "Content-Type: application/json" \
-d '{ "settings": { "timezone": "UTC", "sandbox": { "is_sandbox": false } } }'
400 Bad Request
{
"error": "invalid_request",
"message": "Unsupported settings key(s): sandbox. Writable keys are: display_name, displayName, timezone, locale, security, email, audit_log_retention_days, audit_log_auto_delete, agent_governance.",
"status": 400,
"details": {
"rejected_keys": ["sandbox"]
}
}

Platform-derived flags (sandbox status, shared signing-key opt-ins, JWKS publication) and every stored secret are never client-writable through this endpoint.

allow_root_admin_login (read-only)​

By default LumoAuth operators cannot sign in through your organization's hosted OAuth login page; the page only knows your organization's own users. The allow_root_admin_login switch re-enables that fallback, for example during a support engagement. It is not writable through this API or the organization portal: a PATCH containing it returns 400 invalid_request with rejected_keys. It is changed only by LumoAuth operators, at your request. Each change is audited in your log as admin.tenant.root_admin_login.enabled / .disabled, and every such login as oauth.root_fallback_login at critical severity.

security.dpop_require_nonce​

security is one of the writable keys, so { "settings": { "security": { "dpop_require_nonce": true } } } is accepted here. Be aware that this endpoint replaces the entire security object with what you send. To change one switch without touching the rest, use PATCH /settings/security, which merges key by key. What the switch does is documented under Security settings fields.

Common mistakes​

  • 400 invalid_request with rejected_keys: you sent a key outside the table above, or a nested key with a secret-like suffix. Remove it; the platform manages those values.
  • A security switch disappeared after a PATCH /organization: the security object was replaced wholesale. Resend the full object, or use PATCH /settings/security next time.
  • metadata is silently ignored: the organization has no free-form metadata field. Use settings with an allow-listed key, or store application data on your side.
  • 403 forbidden: the credential lacks admin:settings:write (or admin:settings:read for GET), or the Bearer token has no admin scope. See Authentication errors.

Sign-in settings​

Control how users authenticate within the organization.

Get Auth Settings
curl https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/settings/auth \
-H "Authorization: ApiKey lmk_abc123"

The response is wrapped in a data envelope. Auth settings are a flat object (there are no nested session/login_flow groups); the one nested object is mfa_policy, present once an MFA policy has been saved. session_timeout is in seconds.

MFA settings

Manage MFA with the dedicated MFA policy API (GET/PUT /admin/policies/mfa), which validates and clamps values, stamps the grace-period start and audits the change. mfa_required, mfa_methods and mfa_sms_enabled are legacy keys kept in sync with the policy. Sending mfa_required, mfa_sms_enabled or mfa_policy to this endpoint is applied as an MFA policy change (mfa_required: true → required, false → risk_based; mfa_sms_enabled toggles sms_otp).

Auth Settings
{
"data": {
"passkey_enabled": false,
"biometric_enabled": false,
"mfa_required": false,
"mfa_methods": [],
"push_auth_required": false,
"social_login_enabled": false,
"social_providers": [],
"password_min_length": 8,
"password_require_special": false,
"password_policy": {
"template": "fair",
"min_length": 8,
"require_special": false,
"require_numbers": false,
"require_uppercase": false,
"require_lowercase": false
},
"password_rotation_policy": {
"enabled": false,
"max_age_days": 90,
"notify_before_days": 7,
"history_count": 0
},
"no_mfa_action": "allow",
"session_timeout": 1209600,
"dynamic_client_registration_enabled": false,
"progressive_profiling": {
"enabled": false,
"rules": []
}
}
}
Update Auth Settings
curl -X PATCH https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/settings/auth \
-H "Authorization: ApiKey lmk_abc123" \
-H "Content-Type: application/json" \
-d '{
"passkey_enabled": true,
"session_timeout": 28800
}'

Branding Settings​

Customize the login page appearance for the organization.

Get Branding Settings
curl https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/settings/branding \
-H "Authorization: ApiKey lmk_abc123"

The response is wrapped in a data envelope. The gradient is a single CSS string (background_gradient), and the welcome copy is split into welcome_title / welcome_subtitle.

Branding Settings
{
"data": {
"enabled": false,
"logo_url": "https://example.com/logo.png",
"background_color": "#ffffff",
"primary_color": "#667eea",
"button_text": "Sign in",
"show_tenant_name": true,
"custom_css": null,
"custom_html": null,
"theme": "auto",
"self_registration_enabled": true,
"layout": "centered",
"background_type": "solid",
"background_image_url": null,
"background_gradient": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
"background_overlay_opacity": 50,
"show_background_pattern": true,
"welcome_title": null,
"welcome_subtitle": null,
"terms_url": null,
"privacy_url": null,
"footer_text": null,
"show_powered_by": true,
"input_style": "rounded",
"button_style": "filled",
"form_card_style": "card",
"magic_link_enabled": true,
"magic_link_only": false,
"magic_link_expiry": 900,
"email_first_mode": true
}
}

SCIM Settings​

Configure inbound SCIM 2.0 provisioning from your identity provider.

Get SCIM Settings
curl https://app.lumoauth.dev/orgs/acme-corp/api/v1/admin/settings/scim \
-H "Authorization: ApiKey lmk_abc123"

The response is wrapped in a data envelope and splits configuration into inbound (your IdP provisions into LumoAuth) and outbound (LumoAuth pushes changes to a downstream SCIM endpoint). Inbound provisioning is controlled by the allow_user_creation / allow_user_updates / allow_user_deletion / allow_group_operations flags, and auto_activate_users: false creates provisioned users inactive.

  • Inbound bearer_token is write-only. Send a new token in inbound.bearer_token to set it; only its SHA-256 hash (bearer_token_hash, returned redacted), a non-reversible bearer_token_preview and token_created_at are stored and returned.
  • Outbound secrets (bearer_token, basic_password, oauth2_client_secret) are encrypted at rest and returned redacted. Changing endpoint_url or oauth2_token_url requires re-entering the secret in the same request.
  • Outbound authentication. auth_type is bearer, basic or oauth2 (client credentials: oauth2_client_id, oauth2_client_secret, oauth2_token_url, optional oauth2_scope).
  • Outbound sync options. push_group_changes, sync_on_login and batch_sync_enabled are booleans; batch_sync_interval is hourly, daily or weekly. Any other value is rejected with 400. See Groups, login sync and batch sync.
  • Server-owned keys. last_sync_* (last connection test) and last_batch_sync_at / last_batch_sync_status / last_batch_sync_error / last_batch_sync_counts (last batch run) are returned but ignored on write.
SCIM Settings
{
"data": {
"inbound": {
"enabled": false,
"bearer_token_hash": { "configured": true, "redacted": true },
"bearer_token_preview": "lmk_...3f9a1c2e",
"token_created_at": "2026-09-28 10:15:00",
"allow_user_creation": true,
"allow_user_updates": true,
"allow_user_deletion": true,
"allow_group_operations": true,
"protected_attributes": {
"email": false,
"name": false,
"active": false,
"roles": true,
"permissions": true
},
"attribute_mapping": {
"userName": "email",
"name.givenName": "givenName",
"name.familyName": "familyName",
"displayName": "name",
"active": "isActive"
},
"auto_activate_users": true,
"deprovisioning_action": "soft_delete"
},
"outbound": {
"enabled": false,
"endpoint_url": null,
"bearer_token": null,
"auth_type": "bearer",
"oauth2_client_id": null,
"oauth2_client_secret": null,
"oauth2_token_url": null,
"oauth2_scope": null,
"verify_tls": true,
"push_user_creates": true,
"push_user_updates": true,
"push_user_deletes": true,
"push_group_changes": false,
"sync_on_login": false,
"batch_sync_enabled": false,
"batch_sync_interval": "daily",
"attribute_mapping": {
"email": "userName",
"givenName": "name.givenName",
"familyName": "name.familyName",
"name": "displayName",
"isActive": "active"
},
"last_sync_at": null,
"last_sync_status": null,
"last_sync_error": null,
"last_batch_sync_at": null,
"last_batch_sync_status": null,
"last_batch_sync_error": null,
"last_batch_sync_counts": null
}
}
}