API reference · API 1.0.0

Users

Users, role grants and the permission catalog.

get /api/v1/permissions

The permission catalogue

Operation permissions_list · bearer token

Every fine-grained permission key the portal honours, <feature>-<level>-<scope>. grantable says whether it may be granted to a person; mintable whether an API token may carry it (v1 tokens carry -global keys only, never admin, founder, ssh-console or a key of the api-tokens feature). The roles catalogue also holds role names that are not permission keys (user, admin, …); those can be granted too.

Parameters

NameInTypeDescription
feature query string | null

Only this feature's keys.

limit query integer

Page size.

min 1 · max 200 · default 50
cursor query string | null

next_cursor from the previous page; omit it for the first page. A cursor this list did not issue is a 400 invalid_cursor.

Responses

  • 200

    One page of the permission catalogue.

    application/json → PermissionPage
    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    The caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
get /api/v1/users

List users

Operation users_list · bearer token

The people on this platform, in id order; service accounts only with kind service or all. The filters combine (all must hold): email and username are exact and case-insensitive, is_active, tenant_id (members of that tenant), customer_id (members of any of its tenants), role (holders of that role). Deactivated people are listed unless is_active is true.

Parameters

NameInTypeDescription
email query string | null

Exact address, compared lower-cased.

username query string | null

Exact username, case-insensitive.

kind query string

human (default) leaves service accounts out.

one of human, service, all · default "human"
is_active query boolean | null
tenant_id query string (uuid) | null

Only members of this tenant.

customer_id query string | null

Only members of one of this customer's tenants.

pattern ^[1-9][0-9]{0,8}$
role query string | null

Only holders of this role.

limit query integer

Page size.

min 1 · max 200 · default 50
cursor query string | null

next_cursor from the previous page; omit it for the first page. A cursor this list did not issue is a 400 invalid_cursor.

Responses

  • 200

    One page of users.

    application/json → UserPage
    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    The caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
post /api/v1/users

Create a person

Operation users_create · bearer token

Creates the person with the role user and runs the portal's provisioning: username, SSO account, and — with needs_git_access — a GitLab account and group membership. No password is set and none is ever returned: the person cannot sign in until an operator resets their password in the portal or they use the self-service reset. A provisioning step that fails is a warnings entry (provisioning_<step>_failed) and provisioning_status is ok, partial or error; the person exists either way, so the answer is 201. On a platform with no SSO configured at all the SSO step is skipped, not failed: provisioning_status is partial with a sso_not_configured warning (error stays for a configured SSO that failed). Idempotency-Key is honoured.

Parameters

NameInTypeDescription
Idempotency-Key header string

Makes a retry safe: for 24 hours, the same key with the same request (method, path, query and body) answers with the stored response (Idempotent-Replayed: true) instead of doing the work again. The same key with a different request is a 409 idempotency_key_reused; while the first request is still running it is a 429 idempotency_request_in_progress with Retry-After. 1-255 printable characters without spaces (400 invalid_idempotency_key otherwise); a UUID is a good key. Keys are scoped to the calling account.

min length 1 · max length 255 · pattern ^[!-~]+$

Request bodyrequired

application/json

Schema UserCreate

No password: a person created through the API cannot sign in until an operator resets their password or they reset it themselves.

NameTypeDescription
ad_username string | null

The Windows account name, when firstname.lastname is too long. Lower-case letters, digits, '.', '_' and '-', 1-20 characters, not ending in '.'. Create-only.

pattern ^[a-z0-9._-]{1,20}$
emailrequired string (email)

The person's e-mail address and local sign-in name; unique. Stored and returned entirely LOWER-CASED (local part included), surrounding whitespace dropped, and a Name <address> form reduced to the address. Compare case-insensitively.

first_namerequired string

The person's first name.

min length 1 · max length 100
last_name string | null

The person's last name; may be omitted.

max length 100
locale string

The language the portal and its e-mails use for the person: en or hu. Default hu.

one of en, hu · default "hu"
needs_git_access boolean

Create their GitLab account now (and later whenever it is switched on).

default false
username string | null

Lower-case letters, digits, '.', '_' and '-', 1-20 characters, not ending in '.'. Omit to derive firstname.lastname, folded to ASCII (or ad_username when given). Create-only.

pattern ^[a-z0-9._-]{1,20}$

Responses

  • 201

    The person was created.

    application/json → User
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    The caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 409

    The e-mail address (email_taken) or username (username_taken) is taken, deactivated users included.

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 422

    The Windows name derived from the name, or the one given, is not usable (invalid_directory_name, with field), or the body is invalid.

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
get /api/v1/users/{user_id}

One user

Operation users_get · bearer token

One person (or service account) by id, deactivated ones included. No password and no SSO or GitLab identifier is ever returned; sso_linked and gitlab_linked say whether those accounts exist.

Parameters

NameInTypeDescription
user_idrequired path string

Responses

  • 200

    The user.

    application/json → User
    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    The caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 404

    No such user (user_not_found).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
patch /api/v1/users/{user_id}

Change a user

Operation users_update · bearer token

Only the members in the body change. username and ad_username are create-only: sending the current value is accepted, any other value is a 422 immutable_field naming the field, whether or not the person has an SSO account (sso_linked). Changing email answers with an email_keyed_grants_affected warning. is_active: false is a deactivation, with the same destroy gate, refusals and steps as DELETE; is_active: true re-activates (the SSO account is enabled and the GitLab account unblocked; desktop access is not restored). Switching needs_git_access on runs the GitLab provisioning step now; switching it off removes no account. Changes that reach the SSO account are converged before the answer; a failure there is a sso_sync_failed warning.

The body is a JSON Merge Patch (RFC 7396), sent as application/merge-patch+json or application/json: a member that is omitted is left unchanged, and a member set to null clears that field where clearing is allowed (the schema marks those fields nullable; null for any other field is a 422).

Parameters

NameInTypeDescription
user_idrequired path string

Request bodyrequired

application/jsonapplication/merge-patch+json

Schema UserPatch

JSON Merge Patch (RFC 7396): a member that is omitted keeps its current value; a member sent as null clears the field when the field is nullable (the schema marks it so), and null for any other field is a 422. A "" is a value (an empty string), not a clear. Only last_name is nullable.

NameTypeDescription
ad_username string | null

Create-only: a PATCH may send the current value (nothing changes); any other value is 422 immutable_field, whether or not the person has an SSO account yet.

email string (email) | null

The person's e-mail address and local sign-in name; unique. Stored and returned entirely LOWER-CASED (local part included), surrounding whitespace dropped, and a Name <address> form reduced to the address. Compare case-insensitively. A change answers with a email_keyed_grants_affected warning.

first_name string | null

The person's first name.

min length 1 · max length 100
is_active boolean | null

false deactivates exactly like DELETE (same refusals, same destroy gate); true re-activates.

last_name string | null

null clears it.

min length 1 · max length 100
locale string | null

The language the portal and its e-mails use for the person: en or hu.

one of en, hu
needs_git_access boolean | null

Switching it on creates the GitLab account now. Switching it off does not remove one.

username string | null

Create-only: a PATCH may send the current value (nothing changes); any other value is 422 immutable_field, whether or not the person has an SSO account yet.

Responses

  • 200

    The user after the change.

    application/json → User
    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    is_active: false with a token created without allow_destroy (destroy_not_allowed). Also: the caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 404

    No such user (user_not_found).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 409

    The e-mail address is taken (email_taken), the user is a service account (service_account_managed_elsewhere), or a deactivation is refused (cannot_deactivate_self, last_active_admin).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 422

    A create-only field was changed (immutable_field, with field: username or ad_username), or the body is invalid.

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
delete /api/v1/users/{user_id}

Deactivate a user

Operation users_delete · bearer token

Answers 204 with no body, like every v1 DELETE. A downstream step that fails does not undo the deactivation and is not in this answer: it is logged and kept on the audit row (warnings). To get the step outcomes in the answer, deactivate with PATCH {"is_active": false} instead: the same gate, refusals and steps, answered 200 with the user and its warnings. Deactivation never deletes. It sets is_active to false and then, at once: clears the cached active state so signed-in sessions and API tokens stop on the next request; converges the SSO account, which disables it, and ends its open SSO sessions; removes the person from the remote desktop group; and blocks their GitLab account when they have one. Each of those steps that fails is a warning (sso_disable_failed, sso_logout_failed, sso_not_configured, vdi_revoke_failed, gitlab_block_failed, gitlab_not_configured, session_cache_not_cleared); the deactivation stands. Repeating it repeats the steps. Refused (409) for your own account (cannot_deactivate_self), the last active admin (last_active_admin) and a service account (service_account_managed_elsewhere). Tenant memberships, role grants and service grants are kept, so re-activating restores them. NOT done: the person's account on the partner portal is not disabled; disable it there.

Parameters

NameInTypeDescription
user_idrequired path string

Responses

  • 204

    The person is deactivated.

    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    A token created without allow_destroy (destroy_not_allowed). Also: the caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 404

    No such user (user_not_found).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 409

    Your own account (cannot_deactivate_self), the last active admin (last_active_admin), or a service account (service_account_managed_elsewhere).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
get /api/v1/users/{user_id}/roles

A user's role grants

Operation user_roles_list · bearer token

Every role the person holds, in role order.

Parameters

NameInTypeDescription
user_idrequired path string
limit query integer

Page size.

min 1 · max 200 · default 50
cursor query string | null

next_cursor from the previous page; omit it for the first page. A cursor this list did not issue is a 400 invalid_cursor.

Responses

  • 200

    One page of the user's role grants.

    application/json → RoleGrantPage
    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    The caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 404

    No such user (user_not_found).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
get /api/v1/users/{user_id}/roles/{role}

One role grant

Operation user_roles_get · bearer token

Whether the person holds one role: the grant, or 404 role_grant_not_found.

Parameters

NameInTypeDescription
user_idrequired path string
rolerequired path string

Responses

  • 200

    The role grant.

    application/json → RoleGrant
    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    The caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 404

    No such user (user_not_found) or grant (role_grant_not_found).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
put /api/v1/users/{user_id}/roles/{role}

Grant a role

Operation user_roles_put · bearer token

201 when the role was granted, 200 when the user already held it (nothing changes). No body. The portal's role rules apply: the role must exist in the roles catalogue (unknown_role, 422); a key that is not grantable is refused (role_not_grantable, 400); founder and ssh-console are granted only by a holder and never to yourself; the last active admin keeps admin, and nobody removes their own; a user keeps at least one role (last_role, 409). An API token can never grant or revoke admin, founder, ssh-console or a key of the api-tokens feature (role_not_manageable_by_token: managing tokens takes a browser session), can never change the roles of its own account (token_cannot_change_own_roles), and grants or revokes only a role within its own effective scopes (role_not_held_by_token), all 403; a browser session is held to none of these three and keeps the portal's rules. The change is converged into SSO before the answer; a failure there is a sso_sync_failed warning.

Parameters

NameInTypeDescription
user_idrequired path string
rolerequired path string

Responses

  • 200

    The user already held the role; nothing changed.

    application/json → RoleGrant
    Headers: X-Request-ID
  • 201

    The role was granted.

    application/json → RoleGrant
    Headers: X-Request-ID
  • 400

    The key is not grantable (role_not_grantable).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    A role rule refused it (role_not_manageable_by_token, token_cannot_change_own_roles, role_not_held_by_token, privileged_role_requires_holding_it, cannot_grant_to_self). Also: the caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 404

    No such user (user_not_found).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 409

    The user is a service account (service_account_managed_elsewhere).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 422

    No such role in the catalogue (unknown_role).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
delete /api/v1/users/{user_id}/roles/{role}

Revoke a role

Operation user_roles_delete · bearer token

Removes one role. Not destroy-gated: it needs the write permission only. The portal's role rules apply: the role must exist in the roles catalogue (unknown_role, 422); a key that is not grantable is refused (role_not_grantable, 400); founder and ssh-console are granted only by a holder and never to yourself; the last active admin keeps admin, and nobody removes their own; a user keeps at least one role (last_role, 409). An API token can never grant or revoke admin, founder, ssh-console or a key of the api-tokens feature (role_not_manageable_by_token: managing tokens takes a browser session), can never change the roles of its own account (token_cannot_change_own_roles), and grants or revokes only a role within its own effective scopes (role_not_held_by_token), all 403; a browser session is held to none of these three and keeps the portal's rules. The change is converged into SSO before the answer; a failure there is a sso_sync_failed warning.

Parameters

NameInTypeDescription
user_idrequired path string
rolerequired path string

Responses

  • 204

    The role was revoked.

    Headers: X-Request-ID
  • 401

    Not authenticated: no Authorization: Bearer header (not_authenticated), or the credential is refused (token_invalid, token_expired, token_revoked, principal_disabled, token_ip_not_allowed).

    application/jsonapplication/problem+json → Problem
  • 403

    A role rule refused it (role_not_manageable_by_token, token_cannot_change_own_roles, role_not_held_by_token, cannot_remove_own_admin). Also: the caller lacks a permission the operation needs (forbidden; required lists the keys, any one of which would do), or the licence refuses a change (licence_locked, licence_restricted, licence_required, with state and remedy; never retry a licence_* code).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 404

    No such user (user_not_found) or grant (role_grant_not_found).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 409

    The last active admin's admin (last_active_admin), the user's last role (last_role), or a service account (service_account_managed_elsewhere).

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID
  • 429

    More than 600 requests in a minute with this token (rate_limited), or the first request with this Idempotency-Key is still running (idempotency_request_in_progress). Retry after Retry-After.

    application/jsonapplication/problem+json → Problem
  • 503

    The platform cannot answer right now (unavailable; retry after Retry-After), or API tokens are not configured on it (api_tokens_unconfigured; an operator must act).

    application/jsonapplication/problem+json → Problem
  • default

    Problem details (RFC 9457)

    application/jsonapplication/problem+json → Problem
    Headers: X-Request-ID

Rendered from openapi-v1.json, platform release 1.0.187. Your installation serves the contract of its own version at /api/v1/openapi.json.