> For the complete documentation index, see [llms.txt](https://docs.maiagent.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.maiagent.ai/tech/en/serve/contacts.md).

# Introduction to Contacts and Integration

Contact overview and integration — map your system's users to end users with sourceId, four ways to create and synchronize contacts, Excel bulk import, and implementation recommendations.

## What is a contact? <a href="#what-is-contact" id="what-is-contact"></a>

A Contact represents an **end user** who talks to an Agent and does not need a MaiAgent account. Once your organization maps users in its own system to contacts using `sourceId`, the AI can identify who is asking and retrieve that person's conversation history and permission settings correctly. For contact concepts, the differences between anonymous and identified contacts, and admin operations, see [Contacts](https://docs.maiagent.ai/serve/daily-operations/contact) in the user manual. For the differences from members and roles, see [Roles and Contacts Compared](https://docs.maiagent.ai/org/roles/contact-role-comparison). This page covers API integration only.

### What can you associate with a contact? <a href="#contact-capabilities" id="contact-capabilities"></a>

| Data                                      | Purpose                                                                                                                             | Details                                                                                                                                                 |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Basic profile (`name`, `email`, `avatar`) | Displayed in the admin contact list and conversation records                                                                        | API details below                                                                                                                                       |
| Custom attributes (`metadata`)            | Background information such as department and membership tier; **the AI reads this information and incorporates it into responses** | [Contact Identity Sync and Token Updates](/tech/en/serve/contacts/contact-credentials-sync.md#sync-contact-profile)                                     |
| Query metadata (`query_metadata`)         | Restricts the knowledge bases, documents, and tags the user can retrieve                                                            | [Knowledge Access Permissions (Query Metadata)](/tech/en/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan.md) |
| MCP/API tool credentials                  | Allows the AI to call external tools **with the user's identity and permissions**                                                   | [Contact Identity Sync and Token Updates](/tech/en/serve/contacts/contact-credentials-sync.md)                                                          |
| Conversation history                      | Continues conversations across devices                                                                                              | Takes effect when the frontend provides `contactId`                                                                                                     |

## Four ways to create and synchronize contacts <a href="#three-paths" id="three-paths"></a>

| Method                                              | Best for                                                                                                          | Description                                                                                                                                                                                                                                                                                                 |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Identity sync API** (`setup-contact-credentials`) | Synchronizing users at login, binding tool credentials, or creating missing contacts in bulk for existing systems | Idempotent (the same `sourceId` does not create duplicate contacts) and requires no API Key. Includes a version called automatically by Web Chat frontend `auth`. **Recommended for most integrations**; see [Contact Identity Sync and Token Updates](/tech/en/serve/contacts/contact-credentials-sync.md) |
| **Contact API** (`POST /api/v1/contacts/`)          | Full backend control over the contact lifecycle, or setting query\_metadata when creating contacts                | Requires an API Key. Update with `PATCH /api/v1/contacts/{contact_id}/` (only submitted fields are updated). For the schema, see [API Documentation — Contacts](https://docs.maiagent.ai/api/api-reference/lian-luo-ren)                                                                                    |
| **Bulk import** (Excel)                             | Creating many missing users at once during the initial integration of an existing system                          | Up to 10,000 rows, with support for query\_metadata and API tool credentials; see [below](#bulk-import)                                                                                                                                                                                                     |
| **Admin graphical interface**                       | Small-scale, manual management                                                                                    | See the [instructions below](#tu-xing-hua-jie-mian-jian-li-lian-luo-ren)                                                                                                                                                                                                                                    |

All four methods create the same type of contact and can be combined (for example, bulk import for initial integration and identity sync for routine logins).

### Contact API request fields <a href="#contact-api-fields" id="contact-api-fields"></a>

Request body for `POST /api/v1/contacts/` (both camelCase and snake\_case are accepted):

| Field                            | Required                | Description                                                                                                                                                                                                                                                                                                                    |
| -------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `name`                           | Yes                     | Display name, up to 255 characters                                                                                                                                                                                                                                                                                             |
| `inboxes`                        | Yes (one of two fields) | `[{"id": "<conversation platform ID>"}]`, the conversation platforms the contact belongs to; these must belong to the organization associated with the key. The legacy `inbox` field (a single `{"id": …}`) is still accepted. If both are provided, `inboxes` takes precedence; if neither is provided, the API returns `400` |
| `sourceId`                       | No                      | User ID in your system, up to 255 characters. Must be unique within a conversation platform; duplicates return `400`. If omitted, the contact can only be identified by `contactId`                                                                                                                                            |
| `email`, `phoneNumber`, `avatar` | No                      | Basic profile; `avatar` accepts a full URL or a platform-relative path                                                                                                                                                                                                                                                         |
| `metadata`                       | No                      | Custom attributes; see [Contact Identity Sync and Token Updates](/tech/en/serve/contacts/contact-credentials-sync.md#sync-contact-profile) for the key-value array format                                                                                                                                                      |
| `queryMetadata`                  | No                      | Knowledge retrieval scope; see [Query Metadata](/tech/en/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan.md) for the format                                                                                                                                                         |

The smallest valid request is `{"name": "John Smith", "inboxes": [{"id": "<conversation platform ID>"}]}`. The `201` response includes the complete contact object. Its `mcpCredentials`, `apiCredentials`, `contactConnectors`, and `tags` fields are read-only; use their respective endpoints to write credentials.

### Contact ownership and visibility <a href="#contact-ownership" id="contact-ownership"></a>

Contacts belong to an **organization**, not to the API key that created them. Any key in the same organization can read, update, and delete the same contact, provided its associated member has contact permissions. Both `contactId` and `sourceId` remain usable after key rotation. Contacts are completely invisible across organizations (returns `404`).

### Do members become contacts when they log in? <a href="#member-as-contact" id="member-as-contact"></a>

Yes, but not at login. When a member (including a member who signs in through SSO) starts a conversation using a platform account in MaiGPT or admin test conversations, the platform creates (or reuses) a contact on that conversation platform whose `sourceId` equals the member's user ID and links it to that account. The same rule applies when calling `completions` with an API key without a `sender` (see [Identity When `message.sender` Is Omitted](/tech/en/api-integration/dui-hua-yu-xun-xi-hui-fu-chuan-liu-tong-bu.md#anonymous-sender)). MCP/API tool credentials and `queryMetadata` attached to this contact therefore also apply in the member's own conversations. Contacts are created per conversation platform, so the same member has different contacts on different platforms. Member role permissions and contact settings are independent; see [Roles and Contacts Compared](/tech/en/serve/contacts/role-vs-contact.md).

## Integration workflow <a href="#e5-ae-8c-e6-95-b4-e6-b5-81-e7-a8-8b-e5-9c-96" id="e5-ae-8c-e6-95-b4-e6-b5-81-e7-a8-8b-e5-9c-96"></a>

```mermaid
sequenceDiagram
    participant CU as User
    participant ES as Enterprise System
    participant MA as MaiAgent
    CU ->> ES: Open the website and log in (with an enterprise system user ID)
    ES ->> ES: Check member data for an existing Contact ID mapping
    alt No mapping exists
        ES ->> MA: Create a contact (identity sync API or POST /api/v1/contacts/)
        MA -->> ES: Return contactId
        ES ->> ES: Store contactId in the member table
    end
    ES ->> CU: Load Web Chat embed code (include contactId in config)
    CU ->> MA: Initialize Web Chat as this contact
    MA -->> CU: Display the user's conversation history and applicable permissions
```

Three steps:

1. **Check the mapping**: Look up member data using the enterprise system's user ID and check for an existing MaiAgent `contact_id`
2. **Create or update**: If none exists, create one (and save `contact_id`). When the user's name, Email, or permissions change, update the contact (`PATCH /api/v1/contacts/{contact_id}/`) so subsequent conversations use the correct personalized information and permissions
3. **Initialize Web Chat**: Include `contactId` in the frontend config; see [Web Chat Embedding and SDK](/tech/en/serve/web-chat-sdk.md#identify-users)

{% hint style="info" %}
If you need to create a contact and update Token credentials when a user logs in to your enterprise system (for example, to let the AI call MCP tools with the user's permissions), see [Contact Identity Sync and Token Updates](/tech/en/serve/contacts/contact-credentials-sync.md). One call creates the contact and binds credentials.
{% endhint %}

## Bulk contact import (Excel) <a href="#bulk-import" id="bulk-import"></a>

During the initial integration of an existing system, use Excel to create (or update) many contacts at once:

{% stepper %}
{% step %}

### Download the template

Use `GET /api/v1/contacts/bulk-import-template/` to download the Excel template (including header and example rows).
{% endstep %}

{% step %}

### Fill in the data

| Field                 | Required | Description                                                                                                                                                                                                                                                                  |
| --------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Name(required)`      | ✅        | Contact display name                                                                                                                                                                                                                                                         |
| `Email(required)`     | ✅        | One of the matching keys (case-insensitive)                                                                                                                                                                                                                                  |
| `Phone Number`        |          | Phone number                                                                                                                                                                                                                                                                 |
| `Source ID(required)` | ✅        | User identifier in the enterprise system and one of the matching keys. Use an unguessable value (see the [identity sync API security note](/tech/en/serve/contacts/contact-credentials-sync.md#request-body))                                                                |
| `Query Metadata`      |          | JSON object defining the contact's knowledge query scope; **a blank cell preserves the existing value**. For the format, see the [JSON Format Guide](/tech/en/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan/json-interfaces.md) |
| `API Credentials`     |          | JSON array `[{"tool": "<tool ID>", "headers": {...}}]` binding API tool credentials; a blank cell preserves existing credentials                                                                                                                                             |
| {% endstep %}         |          |                                                                                                                                                                                                                                                                              |

{% step %}

### Upload and import

`POST /api/v1/contacts/bulk-import/` (`multipart/form-data`, with `Authorization: Api-Key` authentication, as with the Contact API):

* `file`: Completed `.xlsx` file (up to 10 MB and 10,000 rows)
* `inboxes`: List of inbox UUIDs (at least one). If you plan to use Web Chat login sync, make sure it includes the corresponding Web Chat inbox
* `inboxMode` (optional, defaults to `replace`): With `replace`, each imported contact's inbox set is **entirely replaced** by `inboxes`; with `merge`, `inboxes` are added while preserving existing inboxes
* `dryRun` (optional, defaults to `false`): With `true`, only parses and validates the file and reports the number of contacts to create and update, without writing any data (returns `200`; an actual import returns `201`)

Response: `{ "created": N, "updated": M, "dryRun": false }`

Send a request with `dryRun=true` first, verify the counts, then run the actual import.
{% endstep %}
{% endstepper %}

Import matching and update rules:

* Upsert using (`Source ID`, `Email`) as the key: update the name, phone number, and Query Metadata of an existing contact (leave blank cells unchanged), or create a contact if no match is found
* Upsert `API Credentials` using (contact, tool) as the key; credentials for tools not mentioned in the file remain unchanged
* The entire batch runs in one transaction. Any row with an invalid format (such as incorrect field names or invalid JSON) prevents the whole batch from being written; the error message identifies the row number

{% hint style="info" %}
Import only creates mappings and attributes. User Token credentials are still updated at each login by the [identity sync API](/tech/en/serve/contacts/contact-credentials-sync.md) in the login flow.
{% endhint %}

## Create contacts in the graphical interface <a href="#tu-xing-hua-jie-mian-jian-li-lian-luo-ren" id="tu-xing-hua-jie-mian-jian-li-lian-luo-ren"></a>

For small numbers of contacts, add them manually in the admin interface or use Excel bulk import (with preview). See [Add a Contact](https://docs.maiagent.ai/serve/daily-operations/contact#add-contact) and [Bulk Import Contacts](https://docs.maiagent.ai/serve/daily-operations/contact#bulk-import-contacts) in the user manual. After creation, copy the contact ID from the contact list; this is the `contactId` parameter for Web Chat initialization.

{% hint style="info" %}
Identity information configured on a contact is used to generate the corresponding combination of `query_metadata` conditions during queries.

[**👉 Learn About Query Metadata**](/tech/en/identity-and-access/zhi-shi-guan-li-quan-xian-query-metadata-cha-xun-yuan-zi-liao-zong-lan.md)
{% endhint %}

## Implementation recommendations <a href="#e5-af-a6-e4-bd-9c-e5-bb-ba-e8-a-d-b0" id="e5-af-a6-e4-bd-9c-e5-bb-ba-e8-a-d-b0"></a>

1. **Add a mapping field to the member table** (such as `maiagent_contact_id`, a nullable UUID), and record creation/update timestamps so the enterprise user ID ↔ Contact ID mapping is traceable
2. **Implement idempotency**: Check for an existing mapping before creating a contact, or use the identity sync API directly (`sourceId` is idempotent, so repeated calls do not create duplicates)
3. **Log API calls** to help investigate mapping issues
4. **Use asynchronous calls**: Run contact-related API calls in parallel with other login requests. Do not block login on failure; retry at the next login


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

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

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.maiagent.ai/tech/en/serve/contacts.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
