> ## Documentation Index
> Fetch the complete documentation index at: https://docs.theomnibot.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Upsert Contact: Create or Update by Identifier

> Create a new contact or update an existing one in ChatbotX using a flexible identifier. Ideal for syncing contacts from external CRM systems.

The Upsert Contact endpoint creates a contact if one does not exist for the given identifier, or updates the existing contact's fields if one is found. This makes it ideal for syncing contacts from external CRM systems, webhooks, or data pipelines where you cannot always guarantee whether a contact already exists in your Workspace. The response returns the full contact object regardless of whether it was created or updated.

<Info>
  **POST** `/api/v1/contacts/{identifier}/upsert`
</Info>

## Path Parameters

<ParamField path="identifier" type="string" required>
  A contact lookup string used to find an existing contact or create a new one. Minimum length: 1 character.

  | Format          | Example                  |
  | --------------- | ------------------------ |
  | `id:<value>`    | `id:123456789`           |
  | `email:<value>` | `email:user@example.com` |
  | `phone:<value>` | `phone:+84708123123`     |
</ParamField>

## Request Body

All fields are optional. When a contact is found, only the fields you include are updated; omitted fields remain unchanged. When a new contact is created, any fields you provide are set at creation time.

<ParamField body="firstName" type="string">
  Contact's first name. Maximum 100 characters.
</ParamField>

<ParamField body="lastName" type="string">
  Contact's last name. Maximum 100 characters.
</ParamField>

<ParamField body="email" type="string">
  Contact's email address. Must be a valid email format.
</ParamField>

<ParamField body="phoneNumber" type="string">
  Contact's phone number. Must be 10–20 digits. Pattern: `\+?\d{10,20}`.
</ParamField>

<ParamField body="avatar" type="string">
  URL of the contact's profile image.
</ParamField>

<ParamField body="gender" type="string">
  One of: `male`, `female`, `unknown`.
</ParamField>

## Code Examples

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
    --url "https://app.chatbotx.io/api/v1/contacts/email:jane@example.com/upsert" \
    --header "Authorization: Bearer YOUR_API_TOKEN" \
    --header "Content-Type: application/json" \
    --data '{
      "firstName": "Jane",
      "lastName": "Doe",
      "phoneNumber": "+84708123123",
      "gender": "female"
    }'
  ```

  ```python Python theme={null}
  import requests

  identifier = "email:jane@example.com"
  url = f"https://app.chatbotx.io/api/v1/contacts/{identifier}/upsert"
  headers = {
      "Authorization": "Bearer YOUR_API_TOKEN",
      "Content-Type": "application/json"
  }
  payload = {
      "firstName": "Jane",
      "lastName": "Doe",
      "phoneNumber": "+84708123123",
      "gender": "female"
  }

  response = requests.post(url, json=payload, headers=headers)
  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const identifier = 'email:jane@example.com';
  const options = {
    method: 'POST',
    headers: {
      Authorization: 'Bearer YOUR_API_TOKEN',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      firstName: 'Jane',
      lastName: 'Doe',
      phoneNumber: '+84708123123',
      gender: 'female'
    })
  };

  fetch(`https://app.chatbotx.io/api/v1/contacts/${identifier}/upsert`, options)
    .then(res => res.json())
    .then(data => console.log(data))
    .catch(err => console.error(err));
  ```
</CodeGroup>

## Response Fields

<ResponseField name="id" type="string" required>Unique contact ID.</ResponseField>
<ResponseField name="createdAt" type="string (date-time)" required>When the contact was created.</ResponseField>
<ResponseField name="updatedAt" type="string (date-time)" required>When the contact was last updated.</ResponseField>
<ResponseField name="avatar" type="string | null" required>Profile image URL.</ResponseField>
<ResponseField name="phoneNumber" type="string | null" required>Contact's phone number.</ResponseField>
<ResponseField name="email" type="string | null" required>Contact's email address.</ResponseField>
<ResponseField name="emailVerified" type="boolean" required>Whether the email has been verified.</ResponseField>
<ResponseField name="emailOptIn" type="boolean" required>Whether the contact opted in to email communications.</ResponseField>
<ResponseField name="firstName" type="string | null" required>Contact's first name.</ResponseField>
<ResponseField name="lastName" type="string | null" required>Contact's last name.</ResponseField>
<ResponseField name="fullName" type="string | null" required>Computed full name.</ResponseField>
<ResponseField name="gender" type="string | null" required>One of `male`, `female`, `unknown`.</ResponseField>
<ResponseField name="workspaceId" type="string" required>ID of the owning Workspace.</ResponseField>
<ResponseField name="contactCustomFields" type="array" required>Custom field values.</ResponseField>
<ResponseField name="tags" type="array" required>Tags applied to the contact.</ResponseField>
<ResponseField name="contactNotes" type="array" required>Notes attached to the contact.</ResponseField>
<ResponseField name="contactInboxes" type="array" required>Active inbox connections.</ResponseField>
<ResponseField name="conversation" type="object | null" required>Most recent conversation, or `null`.</ResponseField>

## Example Response

```json theme={null}
{
  "id": "clx1abc123",
  "createdAt": "2024-01-15T09:00:00Z",
  "updatedAt": "2024-01-15T12:30:00Z",
  "avatar": null,
  "phoneNumber": "+84708123123",
  "email": "jane@example.com",
  "emailVerified": false,
  "emailOptIn": false,
  "firstName": "Jane",
  "lastName": "Doe",
  "fullName": "Jane Doe",
  "gender": "female",
  "lastReadAt": null,
  "ref": null,
  "country": null,
  "state": null,
  "city": null,
  "location": null,
  "locale": null,
  "timezone": null,
  "subscribedAt": null,
  "broadcastSubscribedAt": null,
  "blockedAt": null,
  "workspaceId": "ws123",
  "contactCustomFields": [],
  "tags": [],
  "contactNotes": [],
  "contactInboxes": [],
  "conversation": null
}
```
