# Users

{% hint style="info" %}
**Classic API only**: the Platform API does not have user management endpoints. Patient context flows through the [World Model](/developer-guide/platform-api/platform-api/data-world-model.md) 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 are required                                                                                                                                       |
| **Custom Roles**     | Contact the 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. This is 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 happened.

**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="/pages/vX6z4zD2a8fjLjPeW9FZ" %}
[User Models](/developer-guide/classic-api/core-api/users/user-models.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.amigo.ai/developer-guide/classic-api/core-api/users.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
