# Attach a lead to a conversation

`POST https://api.chat-data.com/api/v2/attach-lead`

Canonical: https://www.chat-data.com/api-reference/attach-lead

## Authentication

Send an API key as a Bearer token: `Authorization: Bearer $CHAT_DATA_API_KEY`. Workspace keys reach every chatbot in the workspace; chatbot-scoped keys reach only their chatbot. Keep keys on the server.

## Description

Attach or update a lead for a specific conversation. This endpoint allows you to associate customer information with a conversation.

**UUID immutability:** Once a lead exists, its uuid can never be changed. Attempting to change an existing lead's uuid returns a 400 error.

**Behavior:**
- If the conversation already has a lead attached, that lead is updated with the provided fields (its uuid cannot be changed).
- If no lead is attached, the system searches for an existing lead using ALL provided identifiers together in a single query (best-effort matching).
- If an existing lead is found, it is updated and attached to the conversation (its uuid cannot be changed).
- If no lead is found, a new lead is created with the provided information and attached to the conversation.

**Search strategy:** Best-effort matching using all provided fields in a single query. For example, if you provide both email and phone, the system will search for a lead that matches BOTH values, not just email OR phone.

**Name matching:** Names are compared with an exact, case-sensitive string match. If several leads match the provided fields (for example, two leads share the same name), one of them is used, and which one is not guaranteed. For deterministic matching, use unique identifiers (email, phone, `leadId`, etc.).

**Creating new leads:** To create a new lead, provide at least one field besides `leadId` (name, email, phone, psid, ig_username, username, or info); `info` must come with another lead field. UUID alone is not sufficient for creation.

**UUID handling:** Pass a lead's uuid as `leadId`. When creating a new lead, the provided `leadId` becomes its uuid; otherwise a new UUID is generated. A uuid must be unique within the chatbot; creating a lead with a uuid that is already in use returns a 400 error.

Example body, updating an existing lead found by email:
```json
{
  "chatbotId": "6650f1c2a9e4b83d2c7a1f05",
  "conversationId": "3f2b8c1e-9a4d-4e7b-8c2a-5d1e6f7a8b9c",
  "email": "jane@chat-data.com",
  "phone": "+14155550123"
}
```

Example body, creating a lead with a specific `leadId`:
```json
{
  "chatbotId": "6650f1c2a9e4b83d2c7a1f05",
  "conversationId": "3f2b8c1e-9a4d-4e7b-8c2a-5d1e6f7a8b9c",
  "leadId": "8d0c2b6e-4f1a-4b7c-9e3d-2a5f6b7c8d9e",
  "name": "Jane Doe",
  "email": "jane@chat-data.com"
}
```

## Request body (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| chatbotId | string | yes | The unique identifier of the chatbot. |
| conversationId | string | yes | The unique identifier of the conversation. |
| leadId | string | no | Lead UUID. Can be used alone to find an existing lead, but is not sufficient for creating a new lead. **Important:** Once a lead exists, its uuid can never be changed. Attempting to change it returns a 400 error. When creating a new lead, this value becomes its uuid; otherwise a new UUID is generated. |
| name | string | no | Lead name. Can be used to find an existing lead with an exact, case-sensitive string match. If several leads share the same name, one of them is used, and which one is not guaranteed. Use unique identifiers for deterministic matching. |
| email | string | no | Lead email address. Must be a valid, deliverable email address of at most 254 characters (RFC 5321). |
| phone | string | no | Lead phone number. It must be a valid phone number in international format, starting with `+`. |
| psid | string | no | Page-scoped ID (typically for Facebook Messenger). |
| ig_username | string | no | Instagram username. |
| username | string | no | Slack or Telegram username. A platform-specific identifier, distinct from `ig_username` (Instagram) and `psid` (Messenger). |
| info | string | no | Additional information about the lead, up to 1,000,000 characters. It may be truncated to 1,000 tokens if "User Info Truncation" is turned on in Settings > Limits Control. |

## Example request

```bash
curl 'https://api.chat-data.com/api/v2/attach-lead' \
  -H "Authorization: Bearer $CHAT_DATA_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "chatbotId": "6650f1c2a9e4b83d2c7a1f05",
  "conversationId": "3f2b8c1e-9a4d-4e7b-8c2a-5d1e6f7a8b9c",
  "name": "Jane Doe"
}'
```

## Example response (200)

```json
{
  "status": "success",
  "lead": {
    "leadId": "8d0c2b6e-4f1a-4b7c-9e3d-2a5f6b7c8d9e",
    "name": "Jane Doe",
    "email": "jane@chat-data.com",
    "phone": "+14155550123",
    "info": "Interested in the annual plan; asked about SSO.",
    "source": "api"
  }
}
```

## Responses

| Status | Description |
| --- | --- |
| 200 | Successful response. |
| 400 | Bad request (validation errors). |
| 401 | Authentication failed: the `Authorization` header is missing or not in the `Bearer <key>` format, the API key does not exist, its workspace is unavailable or has no owner, or the workspace's plan does not include API access. `message` says which. |
| 403 | The API key cannot access the requested chatbot. A chatbot-scoped key used with another chatbot's ID gets `Access denied to this chatbot`. A workspace key gets `Chatbot <id> was not found in this API key's workspace. It may have been deleted or moved to another workspace.` when the chatbot does not exist or belongs to another workspace. |
| 404 | The chatbot has no conversation with this ID. |
| 429 | The workspace sent more than 600 API requests in the last minute. Wait the number of seconds given in the `Retry-After` header (and in `message`) before retrying. |
