# Users · Profiles

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /profile/whoami

**Get the current user**

`operationId: UsersController_whoAmI`

Returns the caller's own identity as the server sees it — the read a client makes on load to establish who is signed in.

#### Signature

```http
GET /profile/whoami () -> The current user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /who-is`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The current user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /user/whoami

**Get the current user**

`operationId: UsersController_whoAmI`

Returns the caller's own identity as the server sees it — the read a client makes on load to establish who is signed in.

#### Signature

```http
GET /user/whoami () -> The current user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /who-is`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The current user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /profile/who-is

**Identify a user**

`operationId: UsersController_whoIs`

Resolves who a given identifier belongs to.

#### Signature

```http
GET /profile/who-is (value?: string) -> The identified user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /whoami`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `authorization` | header | string | yes |  |
| `token` | query | string | yes |  |
| `value` | query | string | — | Identifier to resolve. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The identified user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /user/who-is

**Identify a user**

`operationId: UsersController_whoIs`

Resolves who a given identifier belongs to.

#### Signature

```http
GET /user/who-is (value?: string) -> The identified user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /whoami`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `authorization` | header | string | yes |  |
| `token` | query | string | yes |  |
| `value` | query | string | — | Identifier to resolve. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The identified user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /profile/user/meta

**Update my metadata**

`operationId: UsersController_updateMyMeta`

Writes arbitrary metadata against the caller's account, namespaced so different features do not collide. `mode` chooses whether the value merges into what is there or replaces it outright.

#### Signature

```http
POST /profile/user/meta (body) -> The updated metadata
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- `mode: "replace"` discards everything else in the namespace.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | NAMESPACE_REQUIRED | A valid meta namespace is required | `namespace` is missing or invalid. | Namespaces keep features from overwriting each other. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /user/{userId}/meta`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The metadata to write.

```json
{
  "namespace": "preferences",
  "value": {
    "theme": "dark"
  },
  "mode": "merge"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated metadata |
| `400` | A valid meta namespace is required — `namespace` is missing or invalid. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /profile/meta

**Update my metadata**

`operationId: UsersController_updateMyMeta`

Writes arbitrary metadata against the caller's account, namespaced so different features do not collide. `mode` chooses whether the value merges into what is there or replaces it outright.

#### Signature

```http
POST /profile/meta (body) -> The updated metadata
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- `mode: "replace"` discards everything else in the namespace.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | NAMESPACE_REQUIRED | A valid meta namespace is required | `namespace` is missing or invalid. | Namespaces keep features from overwriting each other. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /user/{userId}/meta`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The metadata to write.

```json
{
  "namespace": "preferences",
  "value": {
    "theme": "dark"
  },
  "mode": "merge"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated metadata |
| `400` | A valid meta namespace is required — `namespace` is missing or invalid. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /user/user/meta

**Update my metadata**

`operationId: UsersController_updateMyMeta`

Writes arbitrary metadata against the caller's account, namespaced so different features do not collide. `mode` chooses whether the value merges into what is there or replaces it outright.

#### Signature

```http
POST /user/user/meta (body) -> The updated metadata
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- `mode: "replace"` discards everything else in the namespace.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | NAMESPACE_REQUIRED | A valid meta namespace is required | `namespace` is missing or invalid. | Namespaces keep features from overwriting each other. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /user/{userId}/meta`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The metadata to write.

```json
{
  "namespace": "preferences",
  "value": {
    "theme": "dark"
  },
  "mode": "merge"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated metadata |
| `400` | A valid meta namespace is required — `namespace` is missing or invalid. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /user/meta

**Update my metadata**

`operationId: UsersController_updateMyMeta`

Writes arbitrary metadata against the caller's account, namespaced so different features do not collide. `mode` chooses whether the value merges into what is there or replaces it outright.

#### Signature

```http
POST /user/meta (body) -> The updated metadata
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- `mode: "replace"` discards everything else in the namespace.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | NAMESPACE_REQUIRED | A valid meta namespace is required | `namespace` is missing or invalid. | Namespaces keep features from overwriting each other. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /user/{userId}/meta`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The metadata to write.

```json
{
  "namespace": "preferences",
  "value": {
    "theme": "dark"
  },
  "mode": "merge"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated metadata |
| `400` | A valid meta namespace is required — `namespace` is missing or invalid. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /profile/user/profile/{emailOrUsername}

**Get a user profile (admins only)**

`operationId: UsersController_userProfile`

Fetches a user’s full profile by email or username. Admins only (ConfigAdmin) — anyone else gets 403. To look up a colleague (name, title, email, phone) use `POST /repository/find/user` with `{ "query": { "data.email": "someone@company.com" } }`.

#### Signature

```http
GET /profile/user/profile/{emailOrUsername} (emailOrUsername: string) -> The user profile
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /repository/find/{datatype}`
- `POST /update`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `emailOrUsername` | path | string | yes | Email address or username. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The user profile |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /user/user/profile/{emailOrUsername}

**Get a user profile (admins only)**

`operationId: UsersController_userProfile`

Fetches a user’s full profile by email or username. Admins only (ConfigAdmin) — anyone else gets 403. To look up a colleague (name, title, email, phone) use `POST /repository/find/user` with `{ "query": { "data.email": "someone@company.com" } }`.

#### Signature

```http
GET /user/user/profile/{emailOrUsername} (emailOrUsername: string) -> The user profile
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /repository/find/{datatype}`
- `POST /update`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `emailOrUsername` | path | string | yes | Email address or username. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The user profile |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /profile/user/delete/{emailOrUsername}

**Delete a user**

`operationId: UsersController_deleteUser`

Deletes a user account properly — notifying them, unwinding sessions and recording the removal. This is the endpoint the generic repository delete refuses in favour of.

#### Signature

```http
DELETE /profile/user/delete/{emailOrUsername} (emailOrUsername: string) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Use this rather than deleting the record through the repository API.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /repository/delete/{datatype}/{id}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `emailOrUsername` | path | string | yes | Email address or username. |
| `reason` | query | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /user/user/delete/{emailOrUsername}

**Delete a user**

`operationId: UsersController_deleteUser`

Deletes a user account properly — notifying them, unwinding sessions and recording the removal. This is the endpoint the generic repository delete refuses in favour of.

#### Signature

```http
DELETE /user/user/delete/{emailOrUsername} (emailOrUsername: string) -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Use this rather than deleting the record through the repository API.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /repository/delete/{datatype}/{id}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `emailOrUsername` | path | string | yes | Email address or username. |
| `reason` | query | string | yes |  |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /profile/user/self

**Delete my account**

`operationId: UsersController_deleteSelfUser`

Deletes the caller's own account. Irreversible, and the caller is signed out as a consequence.

#### Signature

```http
DELETE /profile/user/self () -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /user/delete/{emailOrUsername}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /user/user/self

**Delete my account**

`operationId: UsersController_deleteSelfUser`

Deletes the caller's own account. Irreversible, and the caller is signed out as a consequence.

#### Signature

```http
DELETE /user/user/self () -> Deletion result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /user/delete/{emailOrUsername}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Deletion result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /profile/update

**Update a user**

`operationId: UsersController_update`

Updates a user record: the body is merged over the stored record, so roles and groups sent here are written too. Admin only, and root roles or root groups in `data.roles` / `data.groups` are refused outside the root org.

#### Signature

```http
POST /profile/update (body) -> The updated user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `ConfigAdmin`, `RootAdmin`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `403` | ROOT_ORG_REQUIRED | Only the root organization can give a user a root role. Blocked: RootAdmin. | A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. | Root access is managed from the root org only. |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `POST /role/add`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The user to update.

```json
{
  "email": "ada@example.com",
  "firstName": "Ada",
  "lastName": "Lovelace"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | Only the root organization can give a user a root role. Blocked: RootAdmin. — A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /profile/user/update

**Update a user**

`operationId: UsersController_update`

Updates a user record: the body is merged over the stored record, so roles and groups sent here are written too. Admin only, and root roles or root groups in `data.roles` / `data.groups` are refused outside the root org.

#### Signature

```http
POST /profile/user/update (body) -> The updated user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `ConfigAdmin`, `RootAdmin`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `403` | ROOT_ORG_REQUIRED | Only the root organization can give a user a root role. Blocked: RootAdmin. | A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. | Root access is managed from the root org only. |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `POST /role/add`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The user to update.

```json
{
  "email": "ada@example.com",
  "firstName": "Ada",
  "lastName": "Lovelace"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | Only the root organization can give a user a root role. Blocked: RootAdmin. — A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /user/update

**Update a user**

`operationId: UsersController_update`

Updates a user record: the body is merged over the stored record, so roles and groups sent here are written too. Admin only, and root roles or root groups in `data.roles` / `data.groups` are refused outside the root org.

#### Signature

```http
POST /user/update (body) -> The updated user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `ConfigAdmin`, `RootAdmin`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `403` | ROOT_ORG_REQUIRED | Only the root organization can give a user a root role. Blocked: RootAdmin. | A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. | Root access is managed from the root org only. |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `POST /role/add`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The user to update.

```json
{
  "email": "ada@example.com",
  "firstName": "Ada",
  "lastName": "Lovelace"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | Only the root organization can give a user a root role. Blocked: RootAdmin. — A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /user/user/update

**Update a user**

`operationId: UsersController_update`

Updates a user record: the body is merged over the stored record, so roles and groups sent here are written too. Admin only, and root roles or root groups in `data.roles` / `data.groups` are refused outside the root org.

#### Signature

```http
POST /user/user/update (body) -> The updated user
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`). Required role(s): `ConfigAdmin`, `RootAdmin`, `RootPowerUser`.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `403` | ROOT_ORG_REQUIRED | Only the root organization can give a user a root role. Blocked: RootAdmin. | A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. | Root access is managed from the root org only. |

Plus the standard platform errors: `401`, `429`, `500`.

#### See also

- `POST /role/add`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The user to update.

```json
{
  "email": "ada@example.com",
  "firstName": "Ada",
  "lastName": "Lovelace"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated user |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | Only the root organization can give a user a root role. Blocked: RootAdmin. — A root role or root group is named (or a custom role/group resolves to one) and the caller's org is not the root org. The sentence names the act and the blocked names; the body also carries `code: "ROOT_ORG_REQUIRED"` and `blocked`. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

