---
title: "Data sources API"
description: "Create, update, sync and delete a bot's manual data sources and their entries with the Chat Thing REST API, to keep its knowledge in step with your system."
canonical_url: "https://chatthing.ai/docs/developers/data-sources-api"
last_updated: "2026-09-25"
---

# Data sources API

**Available on:** Standard, Pro, Enterprise plans.

Use the data sources API to keep a bot's knowledge in step with your own system, such as a product catalogue, CMS or internal database. You push text to the bot as **manual** data sources, then sync them so the bot can answer from them.

> **Before you start**
>
> You need the API channel turned on for your bot, its **Channel ID** and a **Secret key**. The API channel is on the Standard, Pro and Enterprise plans. See [API overview](https://chatthing.ai/docs/developers/api-overview#authentication).

## How it works

1. [Create a manual data source](https://chatthing.ai/docs/developers/data-sources-api#create-a-manual-data-source) and keep its `id`.
2. [Add rows](https://chatthing.ai/docs/developers/data-sources-api#add-rows) to it. Each row is one document of markdown text, such as one product or one help article.
3. [Sync the data source](https://chatthing.ai/docs/developers/data-sources-api#sync-a-data-source). The bot only learns new or changed rows after a sync.
4. When your content changes, [update](https://chatthing.ai/docs/developers/data-sources-api#update-rows) or [delete](https://chatthing.ai/docs/developers/data-sources-api#delete-rows) rows, then sync again.

This API only works with **manual** data sources that belong to the bot the API channel is on. To add websites, feeds or YouTube from code, use the [MCP server](https://chatthing.ai/docs/mcp/tools#knowledge-data-sources). To learn about manual data sources in the dashboard, see [Add text manually](https://chatthing.ai/docs/knowledge/manual).

Syncing uses storage tokens, and each data source counts towards your plan's data source limit. See [Storage tokens](https://chatthing.ai/docs/account/storage-tokens) and [Plans](https://chatthing.ai/docs/account/plans).

## Endpoints

All paths start with `https://app.chatthing.ai/api/public/channels/{channelId}/2.0`. They also work with `1.0` in place of `2.0`.

| Method | Path | What it does |
| --- | --- | --- |
| `POST` | `/data-sources` | [Create a manual data source](https://chatthing.ai/docs/developers/data-sources-api#create-a-manual-data-source) |
| `POST` | `/data-sources/list` | [List manual data sources](https://chatthing.ai/docs/developers/data-sources-api#list-manual-data-sources) |
| `GET` | `/data-sources?dataSourceId=...` | [Get a manual data source](https://chatthing.ai/docs/developers/data-sources-api#get-a-manual-data-source) |
| `PUT` | `/data-sources` | [Update a manual data source](https://chatthing.ai/docs/developers/data-sources-api#update-a-manual-data-source) |
| `DELETE` | `/data-sources` | [Delete a manual data source](https://chatthing.ai/docs/developers/data-sources-api#delete-a-manual-data-source) |
| `POST` | `/data-sources/sync` | [Sync a data source](https://chatthing.ai/docs/developers/data-sources-api#sync-a-data-source) |
| `POST` | `/data-sources/row` | [Add rows](https://chatthing.ai/docs/developers/data-sources-api#add-rows) |
| `POST` | `/data-sources/row/list` | [List rows](https://chatthing.ai/docs/developers/data-sources-api#list-rows) |
| `GET` | `/data-sources/row?dataSourceId=...&dataSourceRowId=...` | [Get a row](https://chatthing.ai/docs/developers/data-sources-api#get-a-row) |
| `PUT` | `/data-sources/row` | [Update rows](https://chatthing.ai/docs/developers/data-sources-api#update-rows) |
| `DELETE` | `/data-sources/row` | [Delete rows](https://chatthing.ai/docs/developers/data-sources-api#delete-rows) |

Every request needs these headers:

```bash
Content-Type: application/json
X-API-Secret-Key: {secretKey}
```

## The data source object

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | The data source's id |
| `type` | string | Always `MANUAL` |
| `state` | string | `not_synced`, `syncing`, `synced` or `sync_error` |
| `lastSync` | string or null | When it last synced successfully (ISO 8601) |
| `syncInterval` | string or null | How often it re-syncs automatically: `day`, `week`, `month` or `null` for never |
| `createdAt` | string | When it was created (ISO 8601) |

## Create a manual data source

Creates an empty manual data source on the bot. There's no request body.

```text
POST /data-sources
```

**curl**

```bash
curl --request POST \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}'
```

**JavaScript**

```javascript
const response = await fetch(
  `https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Secret-Key": secretKey,
    },
  },
);
const { dataSource } = await response.json();
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}

response = requests.post(url, headers=headers)
data_source = response.json()["dataSource"]
```

```json
{
  "success": true,
  "dataSource": {
    "id": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "type": "MANUAL",
    "state": "not_synced",
    "lastSync": null,
    "syncInterval": null,
    "createdAt": "2026-01-27T15:02:51.970Z"
  }
}
```

If the bot already has as many data sources as your plan allows, you get `429` and `"success": false`.

## List manual data sources

Returns the bot's manual data sources, oldest first, a page at a time.

```text
POST /data-sources/list
```

| Field | Type | Description |
| --- | --- | --- |
| `limit` | integer | Optional. Items per page, from 1 to 100. Default `10` |
| `cursor` | string | Optional. To get the next page, send the `pagination.last` value from the previous response |

**curl**

```bash
curl --request POST \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources/list \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{ "limit": 10 }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources/list`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({ limit: 10 }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources/list"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}

response = requests.post(url, json={"limit": 10}, headers=headers)
```

```json
{
  "success": true,
  "dataSources": [
    {
      "id": "19d95fbc-8285-40bc-8cc0-3e1fe597b765",
      "type": "MANUAL",
      "state": "synced",
      "lastSync": "2026-01-27T14:39:03.038Z",
      "syncInterval": null,
      "createdAt": "2025-10-31T14:52:19.264Z"
    }
  ],
  "pagination": {
    "total": 1,
    "last": "19d95fbc-8285-40bc-8cc0-3e1fe597b765"
  }
}
```

`pagination.total` is the total number of manual data sources on the bot. `pagination.last` is the id of the last item on this page (`null` if the page is empty).

## Get a manual data source

Returns one manual data source. Use it to check whether a sync has finished.

```text
GET /data-sources?dataSourceId={dataSourceId}
```

**curl**

```bash
curl --request GET \
  --url 'https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources?dataSourceId={dataSourceId}' \
  --header 'X-API-Secret-Key: {secretKey}'
```

**JavaScript**

```javascript
await fetch(
  `https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources?dataSourceId=${dataSourceId}`,
  { headers: { "X-API-Secret-Key": secretKey } },
);
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources"
headers = {"X-API-Secret-Key": secret_key}

response = requests.get(url, params={"dataSourceId": data_source_id}, headers=headers)
```

The response is `{ "success": true, "dataSource": { ... } }` with the [data source object](https://chatthing.ai/docs/developers/data-sources-api#the-data-source-object). You get `404` if it doesn't exist, isn't manual or belongs to another bot.

## Update a manual data source

Changes how often a manual data source re-syncs on its own.

```text
PUT /data-sources
```

| Field | Type | Description |
| --- | --- | --- |
| `dataSourceId` | string | Required. The data source's id |
| `syncInterval` | string or null | `day`, `week`, `month`, or `null` to only sync when you ask. Defaults to `null` if left out |

**curl**

```bash
curl --request PUT \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "syncInterval": "week"
  }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources`, {
  method: "PUT",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({
    dataSourceId: "41559b21-b8ff-44c3-8658-1c9e34273070",
    syncInterval: "week",
  }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}
payload = {
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "syncInterval": "week",
}

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

The response is `{ "success": true, "dataSource": { ... } }`. The returned object shows the data source as it was before this change, so call [Get a manual data source](https://chatthing.ai/docs/developers/data-sources-api#get-a-manual-data-source) if you need to confirm the new value.

## Delete a manual data source

Deletes a manual data source and everything in it. The bot stops using it. This can't be undone.

```text
DELETE /data-sources
```

| Field | Type | Description |
| --- | --- | --- |
| `dataSourceId` | string | Required. The data source's id |

**curl**

```bash
curl --request DELETE \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{ "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070" }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources`, {
  method: "DELETE",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({ dataSourceId: "41559b21-b8ff-44c3-8658-1c9e34273070" }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}

response = requests.delete(url, json={"dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070"}, headers=headers)
```

Returns `{ "success": true }`.

## Sync a data source

Starts a sync, so the bot learns any rows you've added, changed or deleted. Syncing runs in the background: poll [Get a manual data source](https://chatthing.ai/docs/developers/data-sources-api#get-a-manual-data-source) until `state` is `synced` (or `sync_error`).

```text
POST /data-sources/sync
```

| Field | Type | Description |
| --- | --- | --- |
| `dataSourceId` | string | Required. The data source to sync |

**curl**

```bash
curl --request POST \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources/sync \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{ "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070" }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources/sync`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({ dataSourceId: "41559b21-b8ff-44c3-8658-1c9e34273070" }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources/sync"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}

response = requests.post(url, json={"dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070"}, headers=headers)
```

Returns `{ "success": true }` when the sync has started. You get `429` if the data source is already syncing or your team is out of storage tokens.

You can also trigger a sync from another system without the API key by using a [Sync trigger webhook](https://chatthing.ai/docs/developers/webhooks#sync-trigger-webhook), and get told when a sync finishes with the [Sync success and Sync failure webhooks](https://chatthing.ai/docs/developers/webhooks#sync-success-webhook).

## Add rows

Adds one or more rows to a manual data source. Each row is one document. Remember to [sync](https://chatthing.ai/docs/developers/data-sources-api#sync-a-data-source) afterwards.

```text
POST /data-sources/row
```

| Field | Type | Description |
| --- | --- | --- |
| `dataSourceId` | string | Required. The data source to add to |
| `dataSourceRows` | array | Required. The rows to add |
| `dataSourceRows[].name` | string | A name for the row that means something to you, such as a file name or product code. The bot isn't trained on it |
| `dataSourceRows[].content` | string | The row's content as markdown (UTF-8). This is what the bot learns |

**curl**

```bash
curl --request POST \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources/row \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "dataSourceRows": [
      { "name": "returns.md", "content": "# Returns\nYou can return any item within 30 days of delivery." },
      { "name": "delivery.md", "content": "# Delivery\nWe deliver to the UK and Ireland in 3 to 5 working days." }
    ]
  }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources/row`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({
    dataSourceId: "41559b21-b8ff-44c3-8658-1c9e34273070",
    dataSourceRows: [
      { name: "returns.md", content: "# Returns\nYou can return any item within 30 days of delivery." },
      { name: "delivery.md", content: "# Delivery\nWe deliver to the UK and Ireland in 3 to 5 working days." },
    ],
  }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources/row"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}
payload = {
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "dataSourceRows": [
        {"name": "returns.md", "content": "# Returns\nYou can return any item within 30 days of delivery."},
        {"name": "delivery.md", "content": "# Delivery\nWe deliver to the UK and Ireland in 3 to 5 working days."},
    ],
}

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

Returns `{ "success": true }`. The new row ids aren't returned: use [List rows](https://chatthing.ai/docs/developers/data-sources-api#list-rows) to find them.

## List rows

Returns the rows in a manual data source, oldest first, a page at a time.

```text
POST /data-sources/row/list
```

| Field | Type | Description |
| --- | --- | --- |
| `dataSourceId` | string | Required. The data source to list |
| `limit` | integer | Optional. Rows per page, from 1 to 100. Default `10` |
| `cursor` | string | Optional. To get the next page, send the `pagination.last` value from the previous response |

**curl**

```bash
curl --request POST \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources/row/list \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "limit": 10
  }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources/row/list`, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({
    dataSourceId: "41559b21-b8ff-44c3-8658-1c9e34273070",
    limit: 10,
  }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources/row/list"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}
payload = {"dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070", "limit": 10}

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

```json
{
  "success": true,
  "dataSourceRows": [
    { "id": "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62", "name": "returns.md" },
    { "id": "4f401205-5f76-46e1-a2b0-9adf66617d81", "name": "delivery.md" }
  ],
  "pagination": {
    "total": 2,
    "last": "4f401205-5f76-46e1-a2b0-9adf66617d81"
  }
}
```

`pagination.total` is the total number of rows in the data source.

## Get a row

Returns one row, including its content.

```text
GET /data-sources/row?dataSourceId={dataSourceId}&dataSourceRowId={dataSourceRowId}
```

**curl**

```bash
curl --request GET \
  --url 'https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources/row?dataSourceId={dataSourceId}&dataSourceRowId={dataSourceRowId}' \
  --header 'X-API-Secret-Key: {secretKey}'
```

**JavaScript**

```javascript
await fetch(
  `https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources/row?dataSourceId=${dataSourceId}&dataSourceRowId=${dataSourceRowId}`,
  { headers: { "X-API-Secret-Key": secretKey } },
);
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources/row"
headers = {"X-API-Secret-Key": secret_key}
params = {"dataSourceId": data_source_id, "dataSourceRowId": data_source_row_id}

response = requests.get(url, params=params, headers=headers)
```

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | The row's id |
| `type` | string | Always `MANUAL` |
| `state` | string | The row's sync state: `not_synced`, `syncing`, `synced` or `sync_error` |
| `lastSync` | string or null | When the row last synced (ISO 8601) |
| `lastModified` | string or null | When the row last changed (ISO 8601) |
| `createdAt` | string | When the row was created (ISO 8601) |
| `content` | string | The row's markdown content |

```json
{
  "success": true,
  "dataSourceRow": {
    "id": "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62",
    "type": "MANUAL",
    "state": "synced",
    "lastSync": "2026-01-27T14:39:03.014Z",
    "lastModified": null,
    "createdAt": "2026-01-27T14:30:01.216Z",
    "content": "# Returns\nYou can return any item within 30 days of delivery."
  }
}
```

## Update rows

Replaces the name and content of one or more rows. Remember to [sync](https://chatthing.ai/docs/developers/data-sources-api#sync-a-data-source) afterwards.

```text
PUT /data-sources/row
```

| Field | Type | Description |
| --- | --- | --- |
| `dataSourceId` | string | Required. The data source the rows belong to |
| `dataSourceRows` | array | Required. The rows to update |
| `dataSourceRows[].id` | string | The row's id |
| `dataSourceRows[].name` | string | The row's new name |
| `dataSourceRows[].content` | string | The row's new markdown content. This replaces the old content |

**curl**

```bash
curl --request PUT \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources/row \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "dataSourceRows": [
      {
        "id": "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62",
        "name": "returns.md",
        "content": "# Returns\nYou can return any item within 60 days of delivery."
      }
    ]
  }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources/row`, {
  method: "PUT",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({
    dataSourceId: "41559b21-b8ff-44c3-8658-1c9e34273070",
    dataSourceRows: [
      {
        id: "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62",
        name: "returns.md",
        content: "# Returns\nYou can return any item within 60 days of delivery.",
      },
    ],
  }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources/row"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}
payload = {
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "dataSourceRows": [
        {
            "id": "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62",
            "name": "returns.md",
            "content": "# Returns\nYou can return any item within 60 days of delivery.",
        }
    ],
}

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

Returns `{ "success": true }`. If any row id doesn't belong to the data source, the request fails with `"success": false`, and rows before it in the list may already have been updated.

## Delete rows

Deletes one or more rows. Remember to [sync](https://chatthing.ai/docs/developers/data-sources-api#sync-a-data-source) afterwards so the bot forgets them.

```text
DELETE /data-sources/row
```

| Field | Type | Description |
| --- | --- | --- |
| `dataSourceId` | string | Required. The data source the rows belong to |
| `dataSourceRows` | array | Required. The rows to delete, each as `{ "id": "..." }` |

**curl**

```bash
curl --request DELETE \
  --url https://app.chatthing.ai/api/public/channels/{channelId}/2.0/data-sources/row \
  --header 'Content-Type: application/json' \
  --header 'X-API-Secret-Key: {secretKey}' \
  --data '{
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "dataSourceRows": [
      { "id": "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62" },
      { "id": "4f401205-5f76-46e1-a2b0-9adf66617d81" }
    ]
  }'
```

**JavaScript**

```javascript
await fetch(`https://app.chatthing.ai/api/public/channels/${channelId}/2.0/data-sources/row`, {
  method: "DELETE",
  headers: {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secretKey,
  },
  body: JSON.stringify({
    dataSourceId: "41559b21-b8ff-44c3-8658-1c9e34273070",
    dataSourceRows: [
      { id: "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62" },
      { id: "4f401205-5f76-46e1-a2b0-9adf66617d81" },
    ],
  }),
});
```

**Python**

```python
import requests

url = f"https://app.chatthing.ai/api/public/channels/{channel_id}/2.0/data-sources/row"
headers = {
    "Content-Type": "application/json",
    "X-API-Secret-Key": secret_key,
}
payload = {
    "dataSourceId": "41559b21-b8ff-44c3-8658-1c9e34273070",
    "dataSourceRows": [
        {"id": "c4f85105-6d07-44c0-bdb7-eb0baf7c6f62"},
        {"id": "4f401205-5f76-46e1-a2b0-9adf66617d81"},
    ],
}

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

Returns `{ "success": true }`. Row ids that don't exist are skipped.

## Errors

| Code | When |
| --- | --- |
| `400` | A required field is missing, or an id isn't a valid UUID |
| `403` | The secret key doesn't match this channel |
| `404` | The channel isn't found or is turned off, or the data source doesn't exist, isn't manual or belongs to another bot |
| `429` | You've reached your plan's data source limit, the data source is already syncing, or your team is out of storage tokens |
| `500` | Saving a row failed. Try again |

Failed requests on most endpoints also return `"success": false` in the body. See [API overview](https://chatthing.ai/docs/developers/api-overview#status-codes).

## Related

- [Add content manually](https://chatthing.ai/docs/knowledge/manual): Write or paste content directly into Chat Thing to fill gaps in your knowledge, such as FAQs, policies or details that aren't published anywhere.
- [API overview](https://chatthing.ai/docs/developers/api-overview): Base URL, API keys, authentication headers, versions, error codes and usage limits for the Chat Thing REST API.
