Contact Overview 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 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 in the user manual. For the differences from members and roles, see Roles and Contacts Compared. This page covers API integration only.
What can you associate with a contact?
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
Query metadata (query_metadata)
Restricts the knowledge bases, documents, and tags the user can retrieve
MCP/API tool credentials
Allows the AI to call external tools with the user's identity and permissions
Conversation history
Continues conversations across devices
Takes effect when the frontend provides contactId
Four ways to create and synchronize contacts
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
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
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
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
Request body for POST /api/v1/contacts/ (both camelCase and snake_case are accepted):
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 for the key-value array 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
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?
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). 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.
Integration workflow
Three steps:
Check the mapping: Look up member data using the enterprise system's user ID and check for an existing MaiAgent
contact_idCreate 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 permissionsInitialize Web Chat: Include
contactIdin the frontend config; see Web Chat Embedding and SDK
Bulk contact import (Excel)
During the initial integration of an existing system, use Excel to create (or update) many contacts at once:
Fill in the data
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)
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
API Credentials
JSON array [{"tool": "<tool ID>", "headers": {...}}] binding API tool credentials; a blank cell preserves existing credentials
Upload and import
POST /api/v1/contacts/bulk-import/ (multipart/form-data, with Authorization: Api-Key authentication, as with the Contact API):
file: Completed.xlsxfile (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 inboxinboxMode(optional, defaults toreplace): Withreplace, each imported contact's inbox set is entirely replaced byinboxes; withmerge,inboxesare added while preserving existing inboxesdryRun(optional, defaults tofalse): Withtrue, only parses and validates the file and reports the number of contacts to create and update, without writing any data (returns200; an actual import returns201)
Response: { "created": N, "updated": M, "dryRun": false }
Send a request with dryRun=true first, verify the counts, then run the actual import.
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 foundUpsert
API Credentialsusing (contact, tool) as the key; credentials for tools not mentioned in the file remain unchangedThe 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
Create contacts in the graphical interface
For small numbers of contacts, add them manually in the admin interface or use Excel bulk import (with preview). See Add a Contact and 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.
Implementation recommendations
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 traceableImplement idempotency: Check for an existing mapping before creating a contact, or use the identity sync API directly (
sourceIdis idempotent, so repeated calls do not create duplicates)Log API calls to help investigate mapping issues
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
Last updated
Was this helpful?