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

# POST /api/v1/channels/{channelId}/messages

> Send text, image, audio, video, or document messages through a BluBash API channel. Responses are generated by your workspace AI agent.

The Channels API lets you send messages to contacts through a configured API channel in your workspace. When you post a message, the platform creates or resolves the contact by `contactIdentifier`, routes the message to your AI agent, and returns the agent's response synchronously in the same API call.

<Info>
  Conversations through an API channel are handled exclusively by AI agents. There is no interface for human agents to join these conversations, so transfer to a human is not supported.
</Info>

## Endpoint

```http theme={null}
POST /api/v1/channels/{channelId}/messages
```

## Authentication

Include your Workspace API Key and, optionally, an idempotency key in the request headers.

```http theme={null}
X-API-Key: your_workspace_api_key
Content-Type: application/json
X-Idempotency-Key: optional_key_to_prevent_duplicates
```

## Path parameters

<ParamField path="channelId" type="string" required>
  The ID of the API channel configured in your workspace.
</ParamField>

## Request body parameters

<ParamField body="type" type="string" required>
  The message type. One of: `TEXT`, `IMAGE`, `AUDIO`, `VIDEO`, `DOCUMENT`.
</ParamField>

<ParamField body="contactIdentifier" type="string" required>
  A unique identifier for the contact. Used to create or look up the contact across requests. We recommend using the contact's email address.
</ParamField>

<ParamField body="contactName" type="string">
  Display name for the contact. Used when creating a new contact record.
</ParamField>

<ParamField body="content" type="object" required>
  The message payload. The shape of this object depends on the `type` field — see the message type examples below.
</ParamField>

<Warning>
  Always use the same `contactIdentifier` value for the same person. Using different identifiers for the same contact (for example, `joao@example.com` in one request and `user@example.com` in another) creates separate contact records and breaks conversation history.
</Warning>

## Message types

### Text

<CodeGroup>
  ```json request theme={null}
  {
    "content": {
      "text": {
        "body": "Hello, how can I help you?"
      }
    },
    "type": "TEXT",
    "contactIdentifier": "user@example.com",
    "contactName": "User Name"
  }
  ```

  ```json response theme={null}
  {
    "success": true,
    "contactId": "cmg5gdkb60000sb75h4yu6mam",
    "conversationId": "cmg6etn5u000dsbx2htkjot8r",
    "messageId": "cmg6zqegm0001sbw9ip35juiq",
    "conversation": {
      "status": "ACTIVE",
      "assignedToHuman": false,
      "aiAgentId": "cmdi03x0z0003sbz6ubwtdrml",
      "aiAgentName": "Aurora",
      "teamId": "0fb043a2-75f7-42d7-b542-1ffcc1f75ccf",
      "teamName": "Technical Support"
    },
    "aiMessages": [
      {
        "content": {
          "text": {
            "body": "Hello! How can I help you today?"
          },
          "type": "text"
        },
        "type": "TEXT",
        "sender_type": "AI",
        "sender_name": "Aurora",
        "channel_message_id": null
      }
    ],
    "usage": {
      "credits": 1
    }
  }
  ```
</CodeGroup>

### Image

<CodeGroup>
  ```json request theme={null}
  {
    "content": {
      "image": {
        "url": "https://example.com/image.jpg",
        "caption": "Image caption"
      }
    },
    "type": "IMAGE",
    "contactIdentifier": "user@example.com"
  }
  ```

  ```json response theme={null}
  {
    "success": true,
    "contactId": "cmg5gdkb60000sb75h4yu6mam",
    "conversationId": "cmg6etn5u000dsbx2htkjot8r",
    "messageId": "cmg6zqegm0001sbw9ip35juiq",
    "conversation": {
      "status": "ACTIVE",
      "assignedToHuman": false,
      "aiAgentId": "cmdi03x0z0003sbz6ubwtdrml",
      "aiAgentName": "Aurora",
      "teamId": "0fb043a2-75f7-42d7-b542-1ffcc1f75ccf",
      "teamName": "Technical Support"
    },
    "aiMessages": [
      {
        "content": {
          "text": {
            "body": "I see an interesting image! How can I help you with that?"
          },
          "type": "text"
        },
        "type": "TEXT",
        "sender_type": "AI",
        "sender_name": "Aurora",
        "channel_message_id": null
      }
    ],
    "usage": {
      "credits": 1
    }
  }
  ```
</CodeGroup>

### Audio

<CodeGroup>
  ```json request theme={null}
  {
    "content": {
      "audio": {
        "url": "https://example.com/audio.mp3"
      }
    },
    "type": "AUDIO",
    "contactIdentifier": "user@example.com"
  }
  ```

  ```json response theme={null}
  {
    "success": true,
    "contactId": "cmg5gdkb60000sb75h4yu6mam",
    "conversationId": "cmg6etn5u000dsbx2htkjot8r",
    "messageId": "cmg6zqegm0001sbw9ip35juiq",
    "conversation": {
      "status": "ACTIVE",
      "assignedToHuman": false,
      "aiAgentId": "cmdi03x0z0003sbz6ubwtdrml",
      "aiAgentName": "Aurora",
      "teamId": "0fb043a2-75f7-42d7-b542-1ffcc1f75ccf",
      "teamName": "Technical Support"
    },
    "aiMessages": [
      {
        "content": {
          "text": {
            "body": "Audio transcription: Hello, I need help with my order"
          },
          "type": "text"
        },
        "type": "TEXT",
        "sender_type": "AI",
        "sender_name": "Aurora",
        "channel_message_id": null
      }
    ],
    "usage": {
      "credits": 1
    }
  }
  ```
</CodeGroup>

### Video

<CodeGroup>
  ```json request theme={null}
  {
    "content": {
      "video": {
        "url": "https://example.com/video.mp4",
        "caption": "Video caption"
      }
    },
    "type": "VIDEO",
    "contactIdentifier": "user@example.com"
  }
  ```

  ```json response theme={null}
  {
    "success": true,
    "contactId": "cmg5gdkb60000sb75h4yu6mam",
    "conversationId": "cmg6etn5u000dsbx2htkjot8r",
    "messageId": "cmg6zqegm0001sbw9ip35juiq",
    "conversation": {
      "status": "ACTIVE",
      "assignedToHuman": false,
      "aiAgentId": "cmdi03x0z0003sbz6ubwtdrml",
      "aiAgentName": "Aurora",
      "teamId": "0fb043a2-75f7-42d7-b542-1ffcc1f75ccf",
      "teamName": "Technical Support"
    },
    "aiMessages": [
      {
        "content": {
          "text": {
            "body": "I received your video! How can I help you with that?"
          },
          "type": "text"
        },
        "type": "TEXT",
        "sender_type": "AI",
        "sender_name": "Aurora",
        "channel_message_id": null
      }
    ],
    "usage": {
      "credits": 1
    }
  }
  ```
</CodeGroup>

### Document

<CodeGroup>
  ```json request theme={null}
  {
    "content": {
      "document": {
        "url": "https://example.com/document.pdf",
        "filename": "document.pdf",
        "caption": "Document description"
      }
    },
    "type": "DOCUMENT",
    "contactIdentifier": "user@example.com"
  }
  ```

  ```json response theme={null}
  {
    "success": true,
    "contactId": "cmg5gdkb60000sb75h4yu6mam",
    "conversationId": "cmg6etn5u000dsbx2htkjot8r",
    "messageId": "cmg6zqegm0001sbw9ip35juiq",
    "conversation": {
      "status": "ACTIVE",
      "assignedToHuman": false,
      "aiAgentId": "cmdi03x0z0003sbz6ubwtdrml",
      "aiAgentName": "Aurora",
      "teamId": "0fb043a2-75f7-42d7-b542-1ffcc1f75ccf",
      "teamName": "Technical Support"
    },
    "aiMessages": [
      {
        "content": {
          "text": {
            "body": "I received your document! How can I help you with that?"
          },
          "type": "text"
        },
        "type": "TEXT",
        "sender_type": "AI",
        "sender_name": "Aurora",
        "channel_message_id": null
      }
    ],
    "usage": {
      "credits": 1
    }
  }
  ```
</CodeGroup>

## Response fields

<ResponseField name="success" type="boolean" required>
  Indicates whether the operation succeeded.
</ResponseField>

<ResponseField name="contactId" type="string" required>
  The unique ID of the contact that was created or matched by `contactIdentifier`.
</ResponseField>

<ResponseField name="conversationId" type="string" required>
  The unique ID of the conversation.
</ResponseField>

<ResponseField name="messageId" type="string" required>
  The unique ID of the message that was sent.
</ResponseField>

<ResponseField name="conversation" type="object" required>
  Details about the conversation and its assignment.

  <Expandable title="properties">
    <ResponseField name="status" type="string">
      Current conversation status (e.g. `ACTIVE`).
    </ResponseField>

    <ResponseField name="assignedToHuman" type="boolean">
      Whether the conversation is assigned to a human agent.
    </ResponseField>

    <ResponseField name="aiAgentId" type="string">
      ID of the AI agent handling the conversation.
    </ResponseField>

    <ResponseField name="aiAgentName" type="string">
      Display name of the AI agent.
    </ResponseField>

    <ResponseField name="teamId" type="string">
      ID of the team the conversation belongs to.
    </ResponseField>

    <ResponseField name="teamName" type="string">
      Display name of the team.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="aiMessages" type="array" required>
  The AI agent's response messages, ordered ascending (earliest first). This is an array because the AI may split its response across multiple sequential messages.
</ResponseField>

<ResponseField name="usage" type="object" required>
  Credit consumption information.

  <Expandable title="properties">
    <ResponseField name="credits" type="number">
      Number of credits consumed by this request.
    </ResponseField>
  </Expandable>
</ResponseField>

## HTTP status codes

| Code  | Description                               |
| ----- | ----------------------------------------- |
| `200` | Success — message processed               |
| `400` | Invalid request data or channel not found |
| `401` | Missing or invalid API key                |
| `404` | Channel not found                         |
| `500` | Internal server error                     |

## Integration examples

<CodeGroup>
  ```javascript JavaScript (Fetch) theme={null}
  async function sendMessage(channelId, apiKey, message) {
    const response = await fetch(`/api/v1/channels/${channelId}/messages`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': apiKey
      },
      body: JSON.stringify({
        content: {
          text: {
            body: message
          }
        },
        type: 'TEXT',
        contactIdentifier: 'user@example.com'
      })
    });

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    return await response.json();
  }

  try {
    const result = await sendMessage('channel_123', 'your_api_key', 'Hello!');
    console.log('Message sent:', result);
  } catch (error) {
    console.error('Error:', error);
  }
  ```

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

  def send_message(channel_id, api_key, message_data):
      url = f"https://your-domain.com/api/v1/channels/{channel_id}/messages"

      headers = {
          'Content-Type': 'application/json',
          'X-API-Key': api_key
      }

      response = requests.post(url, headers=headers, json=message_data)

      if response.status_code == 200:
          return response.json()
      else:
          raise Exception(f"HTTP {response.status_code}: {response.text}")

  message_data = {
      "content": {
          "text": {
              "body": "Hello, I need help!"
          }
      },
      "type": "TEXT",
      "contactIdentifier": "customer@example.com",
      "contactName": "John Smith"
  }

  try:
      result = send_message('channel_123', 'your_api_key', message_data)
      print('Message sent:', result)
  except Exception as e:
      print('Error:', e)
  ```

  ```bash cURL theme={null}
  curl -X POST "https://your-domain.com/api/v1/channels/channel_123/messages" \
    -H "Content-Type: application/json" \
    -H "X-API-Key: your_api_key" \
    -d '{
      "content": {
        "text": {
          "body": "Hello, I need help!"
        }
      },
      "type": "TEXT",
      "contactIdentifier": "customer@example.com",
      "contactName": "John Smith"
    }'
  ```
</CodeGroup>

## Limitations

* **AI only**: Conversations are exclusive to AI agents — human agent handoff is not available.
* **Consistent `contactIdentifier`**: Always use the same value for the same contact. We recommend using the contact's email address.
* **Public media URLs**: Image, audio, video, and document URLs must be publicly accessible.
* **File size limit**: Maximum 10 MB per file.
* **Download timeout**: Media downloads time out after 30 seconds.
* **Idempotency**: Use `X-Idempotency-Key` to avoid duplicate messages on retried requests.
