# Integrating Custom Channels with the Chat API

Our platform offers a robust Chat API that allows you to seamlessly **integrate your AI-powered agents into custom channels**, enabling communication across a variety of platforms, including **proprietary interfaces, third-party tools, and voice-based systems like Salesforce, WhatsApp, or custom web applications**.

For instance, if you want your AI assistant to work within Salesforce for handling customer support or sales inquiries, or WhatsApp for customer engagement, you can integrate our API to make this happen seamlessly.

Our API lets you interact with your assistant using HTTPS requests, making it compatible with any programming language or development tool. Here’s an overview of how to set up and use the API.

## Requirements

To use the Chat API, you’ll need two things:

1. **PROJECT TOKEN**: This token is retrieved from your workspace under the "Install Your Widget" section, as explained here: [Your Project Token](/tech-deep-dives/your-project-token.md).
2. **PERSONAL ACCESS TOKEN**: This token is generated by our [Customer Success Team](/need-help/our-customer-success-team.md) and is linked to your account. It allows you to use the API for a specific project.

## Making a Request

To send a request to the assistant, use a **POST** request to the following endpoint:

**Endpoint**: [`https://platform.indigo.ai/chat/:project_token/send`](https://platform.indigo.ai/chat/:project_token/send)

The request must be authenticated using your **PERSONAL ACCESS TOKEN** in the authorization header. Here's an example of how to make the request using **curl**:

```bash
PROJECT_TOKEN="abcd-1234"
PERSONAL_ACCESS_TOKEN="12345678"
REQUEST_BODY='{...}'

curl -X POST "https://platform.indigo.ai/chat/$PROJECT_TOKEN/send" \
	-H "content-type: application/json" \
	-H "authorization: Bearer pat-$PERSONAL_ACCESS_TOKEN" \
	-d $REQUEST_BODY
```

### Request Body Structure

The request body is a JSON object that must contain the following required fields:

* `sender`: The unique identifier for the conversation (typically the user ID). This ensures that all messages related to the same conversation are tracked and enables retrieval of the message history.
* `source`: Identifies the message source. This is useful when the assistant is integrated into multiple channels (e.g., WhatsApp, Zendesk, or web).
* `data`: Specifies the type of message and its content. We support three types of data content:
  1. **payload**: Used when you want to emulate a button click. You provide the destination agent or workflow label, with an optional label.

     ```json
     {"type": "payload", "payload": "general", "label": "Click here!"}
     ```
  2. **text**: A simple text message to be processed by the assistant.

     ```json
     {"type": "text", "text": "How are you?"}
     ```
  3. **profile**: A set of user information to be associated with the conversation. This can be retrieved from corresponding variables in your workspace.

     ```json
     {"type": "profile", "profile": {"variable1": "some data", "variable2": "other info"}}
     ```

## Starting a Conversation

Every conversation must start with a **payload** message with the label `init`. This is essential to properly initialize the conversation state in our platform. Here's an example to start a conversation:

```bash
PROJECT_TOKEN="abcd-1234"
PERSONAL_ACCESS_TOKEN="12345678"
REQUEST_BODY='{"type": "payload", "payload": "init", "label": "START"}'

curl -X POST "https://platform.indigo.ai/chat/$PROJECT_TOKEN/send" \
	-H "content-type: application/json" \
	-H "authorization: Bearer pat-$PERSONAL_ACCESS_TOKEN" \
	-d $REQUEST_BODY
```

## Parsing the Response

Our API returns responses in **chunks**, similar to how OpenAI’s API handles streaming. Each chunk represents a block or a fragment of processing, especially for complex elements like carousels.

Each response starts with a **`processing.start`** chunk and ends with a **`processing.end`** chunk. Between these chunks, you will receive one or more content chunks.

Each chunk type corresponds to different message content (e.g., text, media, buttons). Multiple chunks may be sent in response, especially when there are multiple buttons or links.

Below is a table of the different chunk types:

<table><thead><tr><th width="182.80859375">Type</th><th width="301.98046875">Description</th><th width="296.62890625">Example</th></tr></thead><tbody><tr><td><strong>processing.start</strong></td><td>The first chunk returned in a response</td><td>{ "type": "processing.start" }</td></tr><tr><td><strong>processing.end</strong></td><td>The last chunk returned in a response</td><td>{ "type": "processing.end" }</td></tr><tr><td><strong>text</strong></td><td>Contains a text block content. The text content keeps all HTML tags to preserve styling.<br>The <code>is_generated</code> attribute tells us if the text is static or generated by an LLM.</td><td><p>{<br>“type”: “text”,<br>"data": {<br>"is_caption": false,<br>"text": "&#x3C;p class="slate-p">Hi 👋I’m your virtual assistant</p><p>"<br>},<br>"is_generated": false,<br>}</p></td></tr><tr><td><strong>image</strong></td><td>Contains an image block content.<br>Media content is hosted on our platform storage if uploaded from a pc.</td><td>{<br>"type": "image",<br>"data": {<br>"alt": "An alt text",<br>"src": "https://platform.indigo.ai/…/image_1.jpg"<br>}<br>}</td></tr><tr><td><strong>video</strong></td><td>Contains a video block content.<br>Media content is hosted on our platform storage if uploaded from a pc.<br></td><td>{<br>"type": "video",<br>"data": {<br>"alt": "An alt text",<br>"src": "https://platform.indigo.ai/…/video_1.jpg"<br>}<br>}</td></tr><tr><td><strong>button</strong></td><td>Contains a single button defined in a quick replies block.<br>When multiple buttons are defined multiple chunks are sent in the response.</td><td>{<br>"type":"button",<br>"data": {<br>"label": "Click here",<br>"payload": "target_answer_label"<br>}<br>}</td></tr><tr><td><strong>url</strong></td><td>Contains a single url defined in a quick replies block.<br>When multiple urls are defined multiple chunks are sent in the response.<br>When a phonecall button is defined it’s returned as a link chunk with url value equal to tel: {{phone-number}} (Ex. tel: +393333333333)</td><td>{<br>"type":"link",<br>"data": {<br>"label": "Visit our website",<br>"url": "https://indigo.ai"<br>}<br>}</td></tr><tr><td><strong>generation.start</strong></td><td>The first chunk of an LLM generation.<br>Contains an id for the generation repeated in every chunk for the same generation.</td><td>{<br>"type":"generation.start",<br>"data": {<br>"generation_id": 1234<br>}<br>}</td></tr><tr><td><strong>generation.end</strong></td><td>The chunk ending an LLM generation.<br>Contains an id for the generation repeated in every chunk for the same generation.</td><td>{<br>"type":"generation.start",<br>"data": {<br>"generation_id": 1234<br>}<br>}</td></tr><tr><td><strong>generation.chunk</strong></td><td><p>A chunk with the partial content for generated text.<br>Contains an id for the generation repeated in every chunk for the same generation.<br>There are 2 contents returned in this chunk:</p><ul><li>Chunk, the text added to the generation</li><li>Deltas, a list of operation to apply to current text to obtain the actual text. It is helpful when we work with HTML that is usually converted from a generated Markdown; in this case the previously generated text can be updated. The instructions are derived from the Myers difference algorithm</li></ul></td><td>{<br>"type":"generation.chunk",<br>"data": {<br>"chunk": "!",<br>"deltas": [<br>{<br>"command": "mov",<br>"value": 90<br>},<br>{<br>"command":"ins",<br>"value":"!"<br>}<br>],<br>"generation_id":1271<br>}<br>}</td></tr><tr><td><strong>carousel.start</strong></td><td>The chunk starting a carousel streaming.<br>Contains an id for the carousel repeated in every chunk for the same carousel’s elements.</td><td>{<br>"type":"carousel.start",<br>"data": {<br>"carousel_id": 1234<br>}<br>}</td></tr><tr><td><strong>carousel.end</strong></td><td>The chunk ending a carousel streaming.</td><td>{<br>"type":"carousel.end",<br>"data": {<br>"carousel_id": 1234<br>}<br>}</td></tr><tr><td><strong>carousel.card.start</strong></td><td>The chunk starting a carousel card.<br>It also contains the main cards information like text and image contents.<br>Contains a card index (from 1 to 10) repeated in every chunk for the same card’s element.</td><td>{<br>"type": "carousel.card.start",<br>"card_index": 1,<br>"carousel_id": 1234,<br>"data": {<br>"description": "A card",<br>"image": null,<br>"title": "Card 1"<br>}<br>}</td></tr><tr><td><strong>carousel.card.end</strong></td><td>The chunk ending a carousel card.</td><td>{<br>"type": "carousel.card.end",<br>"card_index": 1,<br>"carousel_id": 1234<br>}</td></tr><tr><td><strong>carousel.card.button</strong></td><td>A button contained in a card.<br>Data is the same as button chunk.</td><td>{<br>"type": "carousel.card.button",<br>"card_index": 1,<br>"carousel_id": 1234,<br>"data": {<br>"label": "Button Label",<br>"payload": target_answer_label<br>}<br>}</td></tr><tr><td><strong>carousel.card.link</strong></td><td>A link contained in a card.<br>Data is the same as link chunk.</td><td>{<br>"type": "carousel.card.link",<br>"card_index": 1,<br>"carousel_id": 1234,<br>"data": {<br>"label": "Visit our website",<br>"url": "https://indigo.ai"<br>}<br>}</td></tr></tbody></table>


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://guide.indigo.ai/tech-deep-dives/integrating-custom-channels-with-the-chat-api.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
