> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scute.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage Users

> Create, read, update, and delete users within an app via the User Management API.

Programmatic CRUD over users in an app.

## Authentication (same for all endpoints)

```http theme={null}
Authorization: Bearer <api_secret_key>
Content-Type: application/json
```

The key must own the app you're calling against:

* **App key** (`scapp_…`) — can only manage users in its own app
* **Workspace key** (`scwor_…`) — can manage users in any app within the workspace (or any child workspace, if you're an MSP parent)

Wrong scope → `403 "API key not authorized for this app"`.

***

## Create a user

```
POST /v1/:app_id/users
```

`:app_id` is the **Client App ID** (`app_…`) — the app the user should belong to.

### Body

Either `email` or `phone` is required. Everything else is optional.

| Field                                    | Type                   | Description                                             |
| ---------------------------------------- | ---------------------- | ------------------------------------------------------- |
| `email`                                  | string                 | Primary email identifier                                |
| `phone`                                  | string                 | E.164 phone identifier                                  |
| `identifier`                             | string                 | Back-compat: pass either, type is auto-detected         |
| `first_name`, `middle_name`, `last_name` | string                 | Stored together as `name`                               |
| `external_id`                            | string                 | Your own ID for cross-system mapping (unique per app)   |
| `user_meta`                              | object                 | Arbitrary key/value metadata                            |
| `status`                                 | `active` \| `inactive` | Defaults to `active`                                    |
| `send_invite`                            | bool                   | Send magic-link invitation email                        |
| `add_as_workspace_member`                | bool                   | Also add the underlying user as a workspace team member |
| `workspace_role`                         | string                 | Role if `add_as_workspace_member: true`                 |

### Example

```bash theme={null}
curl -X POST https://api.scute.io/v1/app_l3Rx.../users \
  -H "Authorization: Bearer scapp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@acme.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "external_id": "acme-user-42",
    "user_meta": { "plan": "pro", "org": "acme" }
  }'
```

### Response — `200 OK`

```json theme={null}
{
  "user": {
    "id": "57f9b630-eb98-4ef4-...",
    "app_id": "app_l3Rx...",
    "workspace_id": "8a1c...",
    "user_id": "9d4e1f02-...",
    "msp_id": "msp_xxx",
    "external_id": "acme-user-42",
    "status": "active",
    "name": "Jane Doe",
    "email": "jane@acme.com",
    "phone": null,
    "email_verified": false,
    "phone_verified": false,
    "meta": { "plan": "pro", "org": "acme" },
    "signup_date": "2026-05-25T10:00:00Z",
    "...": "..."
  },
  "invite_sent": false,
  "workspace_membership_error": null
}
```

`app_id` and `workspace_id` echo the parent — use them to map users back to the right client in your own database.

***

## Get a user

```
GET /v1/:app_id/users/:id
```

`:id` is the user UUID returned at creation.

***

## List / search users

```
GET /v1/:app_id/users?page=1&per_page=50&search=jane
```

### Query parameters

* `page`, `per_page` — pagination
* `search` — fuzzy match on name / email / phone (requires `pg_trgm`)
* `status` — filter by `active` or `inactive`

### Response

```json theme={null}
{
  "users": [ /* ... */ ],
  "pagination": {
    "total": 1234,
    "page": 1,
    "per_page": 50,
    "total_pages": 25
  }
}
```

***

## Update a user

```
PATCH /v1/:app_id/users/:id    # partial update (only fields you send)
PUT   /v1/:app_id/users/:id    # force-replace (use carefully)
```

Same body shape as create. `PATCH` leaves untouched fields alone; `PUT` overwrites the whole record.

***

## Activate / deactivate

```
POST /v1/:app_id/users/:id/activate
POST /v1/:app_id/users/:id/deactivate
```

No body. Toggles `status` between `active` and `inactive`. Deactivated users can't sign in but aren't deleted.

***

## Delete a user

```
DELETE /v1/:app_id/users/:id
```

Hard-deletes the user, their sessions, credentials, and challenges within that app. Other apps in the workspace are untouched.

***

## Bulk: invite / import

```
POST /v1/:app_id/users/invite    # send magic-link invites to a list
POST /v1/:app_id/users/import    # bulk create
```

Both accept arrays. See the individual endpoint references for body shapes.

***

## Errors

| Status | When                                                 |
| ------ | ---------------------------------------------------- |
| `400`  | Invalid identifier (malformed email / phone)         |
| `401`  | Missing or invalid API key                           |
| `403`  | API key not authorized for this app                  |
| `404`  | App or user not found                                |
| `422`  | Validation error (e.g. `external_id` already in use) |
