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

# Update all the tags from an AI contact

## Overview

Update (replace) all tags for a specific contact. This endpoint completely replaces the contact's current tags with a new set of tag IDs. Use this when you want to set the exact tag list for a contact.

Tags help you organize, filter, and segment contacts based on characteristics, behaviors, or any custom criteria relevant to your business.

## Use Cases

* **Contact Categorization**: Organize contacts by customer type, status, or segment
* **Workflow Automation**: Update tags based on customer actions or events
* **Data Sync**: Sync tags from external CRM systems
* **Bulk Updates**: Programmatically update contact tags in batch operations
* **Customer Journey**: Tag contacts as they progress through your funnel
* **Segmentation**: Create dynamic segments based on tag combinations

## Authentication

This endpoint requires authentication using an API key. Include your API key in the request header:

```
x-api-key: your_api_key_here
```

## Path Parameters

| Parameter     | Type          | Required | Description                      |
| ------------- | ------------- | -------- | -------------------------------- |
| `aiContactId` | string (UUID) | Yes      | Unique identifier of the contact |

## Request Body

| Field     | Type      | Required | Description                               |
| --------- | --------- | -------- | ----------------------------------------- |
| `tagsIds` | number\[] | Yes      | Array of tag IDs to assign to the contact |

## Response Structure

| Field                 | Type   | Description                                  |
| --------------------- | ------ | -------------------------------------------- |
| `status`              | string | Status of the operation (always "success")   |
| `aiContactTagsLength` | number | Total number of tags assigned to the contact |

## Example Request

```bash theme={null}
curl --request PATCH \
  'https://api.vambe.me/api/public/contact/tags/1937bd2c-a13c-4365-af06-43af9a988e36' \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: your_api_key_here' \
  --data-raw '{
    "tagsIds": [1, 5, 12, 23]
  }'
```

## Example Response

```json theme={null}
{
  "status": "success",
  "aiContactTagsLength": 4
}
```

## Common Use Cases

### 1. Replace All Contact Tags

```javascript theme={null}
const updateContactTags = async (contactId, tagIds) => {
  const response = await fetch(
    `https://api.vambe.me/api/public/contact/tags/${contactId}`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        tagsIds: tagIds,
      }),
    },
  );

  const result = await response.json();
  console.log(`Contact now has ${result.aiContactTagsLength} tags`);
  return result;
};

// Usage
updateContactTags('contact-uuid', [1, 5, 12]);
```

### 2. Remove All Tags from Contact

```javascript theme={null}
const removeAllTags = async (contactId) => {
  const response = await fetch(
    `https://api.vambe.me/api/public/contact/tags/${contactId}`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        tagsIds: [], // Empty array removes all tags
      }),
    },
  );

  const result = await response.json();
  console.log('All tags removed from contact');
  return result;
};
```

### 3. Update Tags Based on Customer Behavior

```javascript theme={null}
const updateTagsBasedOnPurchase = async (contactId, purchaseAmount) => {
  // Define tag IDs for different customer tiers
  const TAG_IDS = {
    customer: 1,
    vip: 5,
    high_value: 12,
    repeat_buyer: 23,
  };

  let tags = [TAG_IDS.customer, TAG_IDS.repeat_buyer];

  // Add VIP tag if purchase is over $500
  if (purchaseAmount > 500) {
    tags.push(TAG_IDS.vip, TAG_IDS.high_value);
  }

  const response = await fetch(
    `https://api.vambe.me/api/public/contact/tags/${contactId}`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        tagsIds: tags,
      }),
    },
  );

  return await response.json();
};
```

### 4. Sync Tags from External CRM

```javascript theme={null}
const syncTagsFromCRM = async (contactId, externalTags) => {
  // Map external tag names to your Vambe tag IDs
  const tagMapping = {
    'hot-lead': 1,
    'cold-lead': 2,
    qualified: 5,
    'needs-followup': 12,
  };

  const tagIds = externalTags
    .map((tagName) => tagMapping[tagName])
    .filter((id) => id !== undefined);

  const response = await fetch(
    `https://api.vambe.me/api/public/contact/tags/${contactId}`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        tagsIds: tagIds,
      }),
    },
  );

  return await response.json();
};

// Usage
syncTagsFromCRM('contact-uuid', ['hot-lead', 'qualified']);
```

### 5. Bulk Tag Update for Multiple Contacts

```javascript theme={null}
const bulkUpdateTags = async (contactIds, tagIds) => {
  const results = [];

  for (const contactId of contactIds) {
    try {
      const response = await fetch(
        `https://api.vambe.me/api/public/contact/tags/${contactId}`,
        {
          method: 'PATCH',
          headers: {
            'Content-Type': 'application/json',
            'x-api-key': 'your_api_key_here',
          },
          body: JSON.stringify({
            tagsIds: tagIds,
          }),
        },
      );

      const result = await response.json();
      results.push({ contactId, success: true, ...result });
    } catch (error) {
      results.push({ contactId, success: false, error: error.message });
    }
  }

  console.log(
    `Updated ${results.filter((r) => r.success).length} of ${contactIds.length} contacts`,
  );

  return results;
};
```

### 6. Add Tag Without Removing Existing Ones

```javascript theme={null}
// First get current tags, then add new one
const addTagToContact = async (contactId, newTagId) => {
  // Get current contact info to see existing tags
  const contactResponse = await fetch(
    `https://api.vambe.me/api/public/contact/${contactId}/info`,
    {
      headers: {
        'x-api-key': 'your_api_key_here',
      },
    },
  );

  const contact = await contactResponse.json();

  // Get current tag IDs (you'll need to extract from contact.tags)
  const currentTagIds = contact.tags?.map((t) => t.tag_id) || [];

  // Add new tag if not already present
  if (!currentTagIds.includes(newTagId)) {
    currentTagIds.push(newTagId);
  }

  // Update with combined list
  const response = await fetch(
    `https://api.vambe.me/api/public/contact/tags/${contactId}`,
    {
      method: 'PATCH',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': 'your_api_key_here',
      },
      body: JSON.stringify({
        tagsIds: currentTagIds,
      }),
    },
  );

  return await response.json();
};
```

## Important Behavior

### ⚠️ Replaces All Tags

This endpoint **replaces** the contact's tags completely. If a contact has tags `[1, 2, 3]` and you send `tagsIds: [4, 5]`, the contact will end up with only `[4, 5]`.

**Before**: Contact has tags \[1, 2, 3]
**Request**: `{ "tagsIds": [4, 5] }`
**After**: Contact has tags \[4, 5]

### Adding vs Replacing

* **To add a tag**: First get existing tags, append new ID, then update
* **To remove a tag**: Get existing tags, filter out the unwanted ID, then update
* **To replace all**: Simply send the new list (this endpoint)

### Tag ID Requirements

* All tag IDs must exist in your organization
* All tag IDs must belong to your account
* Invalid tag IDs will cause the request to fail with a 400 error
* Tag IDs are numeric integers, not UUIDs

## Error Responses

| Status Code | Description                                       |
| ----------- | ------------------------------------------------- |
| 400         | Bad Request - Invalid tag IDs or tags don't exist |
| 401         | Unauthorized - Invalid or missing API key         |
| 404         | Not Found - Contact not found                     |
| 500         | Internal Server Error - Something went wrong      |

## Getting Tag IDs

To get available tag IDs for your organization, use the **Get All Tags** endpoint:

```
GET /api/public/tags
```

[View Documentation](/reference/tags/get-all-tags)

This returns all your tags with their IDs, names, types, and colors.

**Workflow**:

1. Call `GET /api/public/tags` to get all available tags
2. Find the tag IDs you need (by name or other criteria)
3. Use those IDs with this endpoint to update contact tags

## Best Practices

### 1. Validate Tag IDs Before Updating

```javascript theme={null}
const validateAndUpdateTags = async (contactId, tagIds) => {
  // Ensure tag IDs are numbers
  const validTagIds = tagIds.filter((id) => typeof id === 'number' && id > 0);

  if (validTagIds.length !== tagIds.length) {
    console.warn('Some tag IDs were invalid and removed');
  }

  return await updateContactTags(contactId, validTagIds);
};
```

### 2. Handle Errors Gracefully

```javascript theme={null}
const safeUpdateTags = async (contactId, tagIds) => {
  try {
    const result = await fetch(
      `https://api.vambe.me/api/public/contact/tags/${contactId}`,
      {
        method: 'PATCH',
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': 'your_api_key_here',
        },
        body: JSON.stringify({ tagsIds: tagIds }),
      },
    );

    if (!result.ok) {
      throw new Error(`HTTP ${result.status}: ${await result.text()}`);
    }

    return await result.json();
  } catch (error) {
    console.error('Failed to update tags:', error);
    throw error;
  }
};
```

### 3. Remove Duplicates

```javascript theme={null}
const updateWithUniqueTags = async (contactId, tagIds) => {
  // Remove duplicate tag IDs
  const uniqueTagIds = [...new Set(tagIds)];

  return await updateContactTags(contactId, uniqueTagIds);
};
```

## Related Endpoints

* [GET /api/public/tags](/reference/tags/get-all-tags) - Get all available tags and their IDs
* [POST /api/public/channels/{channelType}/{platformIdentifier}/tags](/reference/tags/create-tags-by-channel) - Create and assign tags using phone/username
* [GET /api/public/contact/{aiContactId}/info](/reference/contact/get-info-of-an-ai-contact) - Get contact info including current tags

## Tag Types

Tags can be of two types:

1. **CONTACT Tags**: Associated with the contact permanently
2. **TICKET Tags**: Only assigned when a contact has an active ticket

When using this endpoint, both types can be updated, but TICKET tags will only appear when the contact has an active ticket.

## Notes

* **Atomic Operation**: The tag update is atomic - either all tags are updated or none
* **No Partial Updates**: You cannot update tags one at a time with this endpoint
* **Immediate Effect**: Changes take effect immediately
* **Activity Logged**: Tag changes are logged in the contact's activity history


## OpenAPI

````yaml patch /api/public/contact/tags/{aiContactId}
openapi: 3.0.0
info:
  title: Vambe AI API
  description: Vambe AI documentation
  version: '1.0'
  contact: {}
servers:
  - url: https://api.vambe.me
    description: Production Server
security: []
tags:
  - name: Vambe AI
    description: ''
paths:
  /api/public/contact/tags/{aiContactId}:
    patch:
      tags:
        - Contact
      summary: Update all the tags from an AI contact
      operationId: PublicAiContactController_updateTagsFromAiContact
      parameters:
        - name: x-api-key
          in: header
          description: API key required to authorize the request
          required: true
          schema:
            type: string
        - name: aiContactId
          required: true
          in: path
          description: ID of the AI contact
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                tagsIds:
                  type: array
                  items:
                    type: number
      responses:
        '200':
          description: Tags updated successfully.
        '404':
          description: AI contact not found.

````