---
title: "Update Deployment User"
method: PATCH
path: "/v1/admin/users/{user_id}"
tags: ["admin"]
---

# Update Deployment User

`PATCH /v1/admin/users/{user_id}`

Deactivate or reactivate an account, or change whether it may administer this deployment.

Both fields are optional and omitting one leaves it alone; a body naming
neither is refused rather than treated as a no-op. Deactivating also ends
that account's dashboard sessions immediately, so a lost laptop stops
working now rather than when its cookie is next presented.

Two changes are refused to keep a deployment reachable: an operator may not
deactivate their own account or drop their own operator access, and neither
may be taken from the deployment's bootstrap operator, which is the identity
master-key sign-in resolves to. Granting either is unguarded.

## Path parameters

- `user_id` string, uuid, required

## Request body

- DeploymentUserUpdateRequest — The two flags the operator surface may flip, each optional. Omitting a field leaves it alone, so deactivating an account and changing what it may administer stay separate decisions even though one endpoint carries both. A body that sets neither is refused rather than treated as a no-op: it is a request that meant something and lost it.
  - `is_active` boolean, nullable
  - `is_superuser` boolean, nullable

## Response `200`

Successful Response

- DeploymentUserPublic — An identity on this deployment, whatever organization it belongs to. Not ``ActiveOrganizationMemberPublic``: that shape is a *membership* joined to an identity, scoped to one organization and hiding the suspended rows. This one is the identity itself, and its ``organizations`` list carries every membership at whatever status, because an account whose only membership is suspended is precisely what an operator comes here to find. ``is_bootstrap_operator`` and ``is_self`` are the two rows an operator may not deactivate or demote, and they travel on the row so the page can disable those controls rather than offering ones the server refuses. Neither is an authorization: the server refuses either way. ``is_self`` is answered here because nothing else the dashboard fetches names the caller's identity, so without it the page could not tell which row is the reader's own.
  - `created_at` string, date-time, required
  - `email` string, nullable, required
  - `full_name` string, nullable, required
  - `id` string, uuid, required
  - `is_active` boolean, required
  - `is_bootstrap_operator` boolean, required
  - `is_self` boolean, required
  - `is_superuser` boolean, required
  - `last_sign_in_at` string, date-time, nullable, required
  - `organizations` DeploymentUserOrganizationPublic[], required
    - `name` string, required
    - `organization_id` string, uuid, required
    - `role` string, required
    - `slug` string, required
    - `status` string, required

## Other responses

- `422` — Validation Error

## Changes

- **2026-08-26** `646574c2bdfc` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/mozilla-ai/apis/otari/changes/v1/admin/users/:user_id/patch.md)

---

[API](https://skmtc.dev/mozilla-ai/apis/otari.md) · [All operations](https://skmtc.dev/mozilla-ai/apis/otari/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/mozilla-ai/otari/revisions/7f178e92b56c/schema)
