# Users

{% hint style="info" %}
**Classic API only** - The Platform API does not have user management endpoints. Patient context flows through the [World Model](https://docs.amigo.ai/developer-guide/platform-api/platform-api/data-world-model) instead.
{% endhint %}

## User Management Lifecycle

{% @mermaid/diagram content="%%{init: {"theme": "base", "themeVariables": {"actorBkg": "#083241", "actorTextColor": "#FFFFFF", "actorBorder": "#083241", "signalColor": "#575452", "signalTextColor": "#100F0F", "labelBoxBkgColor": "#F1EAE7", "labelBoxBorderColor": "#D7D2D0", "labelTextColor": "#100F0F", "loopTextColor": "#100F0F", "noteBkgColor": "#F1EAE7", "noteBorderColor": "#D7D2D0", "noteTextColor": "#100F0F", "activationBkgColor": "#E8E2EB", "activationBorderColor": "#083241", "altSectionBkgColor": "#F1EAE7", "altSectionColor": "#100F0F"}}}%%
sequenceDiagram
autonumber
participant C as Customer System
participant A as Amigo System

C->>A: POST /v1/{org\_id}/user/
Note over C,A: Body: first\_name, last\_name, email
A-->>C: 201 Created { user\_id }
Note over C: Persist mapping in Customer DB<br/>customer\_user\_id ↔ user\_id

C->>A: POST /v1/{org\_id}/user/{user\_id}
Note over C,A: Body: additional\_context: \[patient\_history]
A-->>C: 204 OK" %}

{% tabs %}
{% tab title="cURL" %}

```bash
curl --request POST \
     --url 'https://api.amigo.ai/v1/<YOUR-ORG-ID>/user/' \
     --header 'Authorization: Bearer <AUTH-TOKEN-OF-USER>' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '{
  "email": "user@example.com",
  "role": "DefaultUserRole",
  "user_preferences": {
    "timezone": "America/New_York"
  }
}'
```

{% endtab %}

{% tab title="Python SDK" %}

```python
from amigo_sdk import AmigoClient
from amigo_sdk.models import UserInviteRequest

with AmigoClient() as client:
    result = client.user.invite_user(
        UserInviteRequest(
            email="user@example.com",
            role="DefaultUserRole",
            user_preferences={
                "timezone": "America/New_York"
            }
        )
    )
    print(f"User ID: {result.user_id}")
```

{% hint style="info" %}
**Async Support**\
Async version available with `async with AsyncAmigoClient()`
{% endhint %}
{% endtab %}

{% tab title="TypeScript SDK" %}

```typescript
import { AmigoClient } from "@amigo-ai/sdk";

const client = new AmigoClient({ ...config });
const result = await client.users.inviteUser({
  email: "user@example.com",
  role: "DefaultUserRole",
  user_preferences: {
    timezone: "America/New_York",
  },
});

console.log(`User ID: ${result.user_id}`);
```

{% endtab %}

{% tab title="CLI" %}

```bash
# Create a user
forge user create -e myorg --first-name "Jane" --last-name "Doe" --email "jane@example.com"

# Create with initial context
forge user create -e myorg --first-name "Jane" --last-name "Doe" --email "jane@example.com" \
  -c "Care Recipient: Bella, Age 5"

# Create with context from file
forge user create -e myorg --first-name "Jane" --last-name "Doe" --email "jane@example.com" \
  -f context.txt
```

{% endtab %}
{% endtabs %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% hint style="warning" %}
**Deprecated Endpoint** The old endpoint `POST /v1/{organization}/user/invite` is deprecated. Use `POST /v1/{organization}/user/` instead.
{% endhint %}

## Configuration Notes

{% hint style="warning" %}
**Timezone Configuration**\
The `timezone` field uses IANA tz database format (e.g., "America/New\_York"). This setting affects how the Amigo agent interprets time for the user, including timestamps and time-related queries. If not specified, the organization's default timezone is used, or UTC if no default is set.
{% endhint %}

| Setting              | Description                                                                                                                                                                                  |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **User Preferences** | Recommended settings for integrations                                                                                                                                                        |
| **Role Assignment**  | Use `DefaultUserRole` unless custom roles required                                                                                                                                           |
| **Custom Roles**     | Contact Amigo team for custom role definitions                                                                                                                                               |
| **Actions Access**   | Set `enable_actions_access` to `true` to grant a user access to actions features (tool repository browsing, action management). Returned in the `GetUserInfo` response. Defaults to `false`. |

## List Users

Retrieve users with optional filters:

{% tabs %}
{% tab title="cURL" %}

```bash
curl --request GET \
     --url 'https://api.amigo.ai/v1/<YOUR-ORG-ID>/user/?limit=10&offset=0' \
     --header 'Authorization: Bearer <AUTH-TOKEN-OF-USER>' \
     --header 'Accept: application/json'
```

{% endtab %}

{% tab title="Python SDK" %}

```python
from amigo_sdk import AmigoClient
from amigo_sdk.models import GetUsersParametersQuery

with AmigoClient() as client:
    users = client.user.get_users(
        GetUsersParametersQuery(
            limit=10,
            offset=0
        )
    )

    for user in users.users:
        print(f"User: {user.email} (ID: {user.id})")
```

{% hint style="info" %}
**Async Support**\
Async version available with `async with AsyncAmigoClient()`
{% endhint %}
{% endtab %}

{% tab title="TypeScript SDK" %}

```typescript
import { AmigoClient } from "@amigo-ai/sdk";

const client = new AmigoClient({ ...config });
const users = await client.users.getUsers({
  limit: 10,
  offset: 0,
});

users.users?.forEach((user) => {
  console.log(`User: ${user.email} (ID: ${user.id})`);
});
```

{% endtab %}

{% tab title="CLI" %}

```bash
# List all users
forge user list -e myorg

# Search by name or email
forge user list -e myorg --search "jane"

# Filter by exact email
forge user list -e myorg --email "jane@example.com"

# Limit results
forge user list -e myorg --limit 20

# JSON output for scripting
forge user list -e myorg --json

# Get a single user by ID
forge user get -e myorg -u USER_ID

# Get a single user by email
forge user get -e myorg --email "jane@example.com"
```

{% endtab %}
{% endtabs %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Update User

Modify user details:

{% tabs %}
{% tab title="cURL" %}

```bash
curl --request POST \
     --url "https://api.amigo.ai/v1/<YOUR-ORG-ID>/user/<USER-ID>" \
     --header 'Authorization: Bearer <AUTH-TOKEN-OF-USER>' \
     --header 'Accept: application/json' \
     --header 'Content-Type: application/json' \
     --data '
{
  "first_name": "Joe",
  "last_name": "Smith",
  "enable_response_recommendation": true,
  "preferred_language": {},
  "conversations_visible_to_admins": true,
  "timezone": "America/Los_Angeles"
}'
```

{% endtab %}

{% tab title="Python SDK" %}

```python
from amigo_sdk import AmigoClient
from amigo_sdk.models import UserUpdateUserInfoRequest

with AmigoClient() as client:
    client.user.update_user(
        user_id,
        UserUpdateUserInfoRequest(
            first_name="Joe",
            last_name="Smith",
            enable_response_recommendation=True,
            preferred_language={},
            conversations_visible_to_admins=True,
            timezone="America/Los_Angeles"
        )
    )
```

{% hint style="info" %}
**Async Support**\
Async version available with `async with AsyncAmigoClient()`
{% endhint %}
{% endtab %}

{% tab title="TypeScript SDK" %}

```typescript
import { AmigoClient } from "@amigo-ai/sdk";

const client = new AmigoClient({ ...config });
await client.users.updateUser(userId, {
  first_name: "Joe",
  last_name: "Smith",
  enable_response_recommendation: true,
  preferred_language: {},
  conversations_visible_to_admins: true,
  timezone: "America/Los_Angeles",
});
```

{% endtab %}

{% tab title="CLI" %}

```bash
# Update user context with inline strings
forge user update -e myorg -u USER_ID -c "New context entry"

# Update with multiple context entries
forge user update -e myorg -u USER_ID \
  -c "Care Recipient: Bella, Age 5" \
  -c "User ID: xyz789"

# Update context from file
forge user update -e myorg -u USER_ID -f context.txt
```

{% endtab %}
{% endtabs %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/{requested\_user\_id}" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

{% hint style="warning" %}
**Deprecated Endpoint** The old endpoint `POST /v1/{organization}/user/{requested_user_id}/user` is deprecated. Use `POST /v1/{organization}/user/{requested_user_id}` instead.
{% endhint %}

## Delete User

Remove a user from the organization:

{% tabs %}
{% tab title="cURL" %}

```bash
curl --request DELETE \
     --url "https://api.amigo.ai/v1/<YOUR-ORG-ID>/user/<USER-ID>" \
     --header 'Authorization: Bearer <AUTH-TOKEN-OF-AN-ADMIN>' \
     --header 'Accept: application/json'
```

{% endtab %}

{% tab title="Python SDK" %}

```python
from amigo_sdk import AmigoClient

with AmigoClient() as client:
    client.user.delete_user(user_id)
```

{% hint style="info" %}
**Async Support**\
Async version available with `async with AsyncAmigoClient()`
{% endhint %}
{% endtab %}

{% tab title="TypeScript SDK" %}

```typescript
import { AmigoClient } from "@amigo-ai/sdk";

const client = new AmigoClient({ ...config });
await client.users.deleteUser(userId);
```

{% endtab %}

{% tab title="CLI" %}

```bash
forge user delete -e myorg -u USER_ID
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Deletion Types**\
A 200 response indicates successful deletion. The deletion may be hard or soft based on the `not_deletable_reasons` array in the response.
{% endhint %}

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/{requested\_user\_id}" method="delete" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## User Impersonation (CLI)

The `--user` flag on conversation commands lets you run conversations as an existing user, useful for testing user-specific agent behaviors (personalized context, memory, conversation history).

```bash
# Smoke test as a specific user
forge conversation smoke-test -s "My Service" -e myorg --user USER_ID -m "Hello"

# Use email instead of ID (auto-resolves)
forge conversation smoke-test -s "My Service" -e myorg --user "jane@example.com" -m "Hello"

# Simulate as a user with temporary additional context
forge conversation simulate -s "My Service" -e myorg --user USER_ID \
  --additional-context "Temporary test context" --max-turns 5
```

{% hint style="warning" %}
**API Key Auth Required** User impersonation via `--user` requires API key authentication. Firebase authentication does not support impersonation. When `--user` is combined with `--additional-context`, the user's original context is saved and restored after the test.
{% endhint %}

## Best Practices

| Practice             | Description                                         |
| -------------------- | --------------------------------------------------- |
| **User ID Mapping**  | Save returned `user_id` and map to internal systems |
| **Token Management** | Generate and manage auth tokens per user            |
| **State Tracking**   | Maintain user state for smooth experiences          |

## Search Users

Search for users in the organization by name or email.

**Permission required:** `User:GetUserInfo` (only users the caller has permission for are returned)

| Parameter | Type   | Required | Description                                   |
| --------- | ------ | -------- | --------------------------------------------- |
| `query`   | string | Yes      | Search query to match against names or emails |
| `user_id` | array  | No       | Filter by specific user IDs (repeatable)      |

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/search/" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Modify User Variables

Upsert or delete user variables. Variables are key-value pairs that are passed to tool invocations. Changes only affect tool invocations that have not yet been made.

**Permission required:** `User:UpdateUserInfo`

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/{requested\_user\_id}/variable" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

The request body supports two operations:

| Field     | Type  | Description                             |
| --------- | ----- | --------------------------------------- |
| `upserts` | array | A list of variables to create or update |
| `deletes` | array | A list of variable names to remove      |

## Get User Memories

Retrieve memories extracted from conversations for a specific user. Memories are key observations the agent stores for future context recall.

**Permission note:** Only memories with references that the caller has `Conversation:GetMessage` permission on are returned.

Query parameters:

* `id` - filter by specific memory IDs (repeatable)
* `conversation_id` - filter by source conversation (repeatable)
* `limit` - results per page (integer)
* `continuation_token` - pagination token (integer)
* `sort_by` - sort order (repeatable)

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/{user\_id}/memory" method="get" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

## Sign In with Email

Send a magic link to a user's email for authentication. If the email does not correspond to an existing user, the endpoint succeeds silently (to prevent user enumeration).

{% openapi src="<https://api.amigo.ai/v1/openapi.json>" path="/v1/{organization}/user/signin" method="post" %}
<https://api.amigo.ai/v1/openapi.json>
{% endopenapi %}

| Field           | Type   | Required | Description                                                                    |
| --------------- | ------ | -------- | ------------------------------------------------------------------------------ |
| `email`         | string | Yes      | Email of the user (must correspond to an existing, verified user)              |
| `redirect_link` | string | Yes      | An Amigo platform link the user is redirected to after clicking the login link |

## User Model Management

{% content-ref url="users/user-models" %}
[user-models](https://docs.amigo.ai/developer-guide/classic-api/core-api/users/user-models)
{% endcontent-ref %}
