User
Included from Basic tier
JSON:API type: user.
The v2 OpenAPI document declares this resource's schema; the resource-field coverage gate holds this page to it.
A user is one identity row — local, provider-managed shadow, or service
account. This page covers the JSON:API read surface; the admin identity
lifecycle surface (/api/admin/users/...) answers plain JSON, documented
below because it is where break-glass and disablement live.
Endpoints
| Verb | Path | Behaviour |
|---|---|---|
GET | /api/me | The authenticated principal's own row, plus the session-identity attributes break_glass and directory_shadowed (this endpoint only). Meta: superuser and admin (whether the principal passes the admin gate — superuser, or update on the /admin rule path). |
GET | /api/users | Username ascending. Visibility: synthetic accounts are always hidden; a non-superuser sees only their own row. Ghost rows are hidden unless include_ghosts=true (opschain docs identity); the same parameter applies to the /api/ui_support/users picker roster and, as the include_ghosts request field, to the v2 UserService.ListUsers read (whose rows also carry email_address, opschain docs api-v2). The v2 read additionally excludes dormant identities by default — users whose provider can no longer sign them in — unless its include_dormant field restores them with dormant: true set (opschain docs identity, "Dormant identities"). |
GET | /api/users/{id} | Show, same visibility rule. Meta: superuser — whether that user's compiled principal is a superuser. |
POST | /api/users/me/password | Self-serve password change: current_password + new_password. 204 on success; named 422s for a wrong current password, policy/reuse failures, and for directory-managed identities (OpsChain never writes to an identity provider). |
The synthetic (hidden) usernames are opschain_internal,
mintpress_internal, opschain_unknown, mintpress_unknown.
Attributes
| Attribute | Type | Meaning |
|---|---|---|
username | string | Unique login name (lowercased). |
groupnames | array of strings | Always [] on this read — the effective groups an identity resolves to are visible on the admin show (below); the ui_support/users roster carries each provider identity's snapshot group names. |
auth_provider | string | The identity's provider: local, a provider method string (ldap:<key>, oidc:<key>, github:<key>), ldap (a legacy, not-yet-re-keyed directory row — dormant until the re-key links it), or service_account (automation principals: minted by the agent platform, or user-managed / — opschain docs cli/admin-service-accounts). |
break_glass | boolean | /api/me only — the account's break-glass flag; absent on every other user read. |
directory_shadowed | boolean | /api/me only — true when the session is a local login whose username a directory shadow row also holds (the warn:auth:provider_collision fact, per session); always false when no enabled ldap-kind connection exists, and absent on every other user read. |
email_address | string, nullable | Stored email; null when never set. |
default_notification_methods | array of strings (JSON) | The user's default notification channels. |
direct_message_ids | object (JSON) | Per-channel direct-message ids, served verbatim as stored. |
created_at / updated_at | string (ISO8601, 6 fractional digits) | Row timestamps. |
Meta: superuser on show/me (boolean); /api/me adds admin. The index
emits no meta.
Links: self = /api/users/<id>.
Admin identity surface (plain JSON, not JSON:API)
/api/admin/users (POST/GET), /api/admin/users/{username} (GET/PATCH),
…/disable, …/enable (PATCH), …/reset_password (POST) — admin-gated, and
available only on compositions with the PostgreSQL store. The user view there
is {id, username, auth_provider, break_glass, disabled_at (omitted when null), created_at, email_address (omitted when unset), local_groups, groups (omitted when empty — the show's effective directory-plus-local union), ghost (omitted when false — a hidden ghost row restored by include_ghosts)}.
id is the user id — the identity key assignments and memberships
are recorded against, so a same-named pair is two rows with two ids. Listing
rows additionally carry dormant: true when the row's provider can no
longer sign it in (the marker is
computed per read, never stored). The
password hash is never serialized. PATCH /api/admin/users/{username} edits
break_glass and/or email_address (empty email clears it; local users
only — a directory row's email is mirror-stamped).
The same admin rows are readable over API v2: UserService.GetUser
(by id, or username + the open provider selector; an ambiguous
username refuses invalid_argument naming the matching providers) and the
UserService.ListUsers rows' superset fields break_glass, disabled_at
and local_groups, populated only for callers holding the /admin
updatable determination (opschain docs api-v2, "Admin identity reads").
The opschain admin users list/show transports ride these verbs.
The listings take an optional filter vocabulary (so older callers are unaffected):
GET /api/admin/users?q=<substring>&limit=<n>&include_ghosts=true|false&provider=<instance>
— q case-insensitively substring-matches username, email address and local
group names; limit caps the username-ordered rows (a non-positive or
non-integer value is a named 422); include_ghosts=true restores the hidden
ghost rows (see opschain docs identity); provider keeps only
one provider instance's rows, matched case-insensitively as an open
string over the auth_provider vocabulary (local, ldap, oidc:<key>,
github:<key>, and any future kind) — an instance with no
rows is an empty listing, never a validation error. The same open match is
the v2 UserService.ListUsers request's provider field (opschain docs api-v2). GET /api/admin/groups?q=<substring>&limit=<n>
— q matches the group name and member usernames; limit caps the
name-ordered groups, each row naming its source instance (always
local on this surface).
Semantics worth knowing when reading the JSON:API user:
- Disabled (
disabled_atset): the account cannot authenticate, and disabling immediately revokes every live access, refresh and api_key token — the leaver process never waits out a token TTL. The JSON:APIuserresource does not exposedisabled_at; it is admin-surface-only. - Break-glass (
break_glass): a local fire-door account. Under a containment posture its access tokens are capped at one hour, no refresh token is issued, and it cannot mint api_key tokens. Postures can refuse non-break-glass local users entirely, cap the break-glass account count, and refuse local usernames that shadow directory identities. On the JSON:API resource it is exposed only as/api/me'sbreak_glasssession-identity attribute. - The local-only lifecycle writes (create/update/reset-password) manage
local users only — a directory identity is managed in the directory
(its OpsChain row is a shadow record), and the v1 lifecycle verbs refuse
service accounts with named 422s — a service account is created through
the v2
CreateServiceAccountverb and carries no credential to manage. Disable/enable manage ANY identity (superseded 's local-only rule for these two verbs — the disabled marker is OpsChain-local shadow state): disabling any row revokes their live tokens, sessions and api keys, and the deliberate re-enable is how a re-admitted leaver gets back in (the ratified leaver rule). They ride the v2UserServiceverbs —DisableUser/EnableUserplus the per-member-idempotentBulkSetUserLifecycle— and a disable response carries theowned_automationswarning (opschain docs api-v2, "User lifecycle writes"; theOwnedAutomationsSummarybelow). On the v1 twin a same-named pair resolves to the local row on the bare name;?provider=<auth_provider>(an open match) selects a provider's row (--provideron the CLI). - Disabled rows and the v2 listing:
UserService.ListUsershides disabled rows by default behindinclude_disabled(the GUI users screen's hide-disabled default with its "show disabled users" toggle). By contrast,opschain admin users listpassesinclude_disabled=true, keeping disabled rows listed with their DISABLED marker — different surfaces, different defaults, and shown rows keep distinct dormant/disabled markers.
The CLI family is opschain admin users (create, list, show, update,
disable/enable, reset-password). See opschain docs identity for the full
identity design (providers, bootstrap admin, postures).
OwnedAutomationsSummary
The disable response's owned_automations: what the disabled identity
executes or owns, so the operator knows what now refuses until
reassigned (opschain admin users reassign-automations; in the GUI the
disable dialog's offboarding summary and the disabled row's Reassign
automations…). Counts are exact; each name list caps at 20 entries.
The disable proceeds regardless.
| Field | Type | Meaning |
|---|---|---|
trigger_count | int | Triggers the identity executes — rows naming it run_as, plus rows it created with no explicit run_as. |
trigger_names | string array | Those triggers' names (first 20). |
scheduled_activity_count | int | Scheduled activities the identity executes, on the same rule. |
scheduled_activity_names | string array | Those activities, named <action> (<node path>) (first 20). |
agent_count | int | Agents the identity owns (owned_by); ownership routes escalations, so a disable leaves them unroutable until reassigned. |
agent_names | string array | Those agents, named <project path>/<code> (first 20). |
Related pages
opschain docs identity— providers, break-glass, postures, bootstrap.opschain docs resources/group— local groups and directory groups.opschain docs identity— the session lane and api keys a user owns.