Sources
These endpoints add knowledge to an agent and remove it again. Sources are what the agent answers from: files, texts, websites and Q&A pairs. Sources overview explains them for people who use the dashboard.
For example, when your team publishes a new policy in your own system, a script can add it to the support agent as a text. The agent can answer from it a few seconds later.
Read the overview first for the base URL, keys, errors and paging.
The source object
Files, texts and websites share one shape. A field that doesn't apply to a kind is null.
{
"id": "0199f3c1-2b3a-7d4e-9f50-6a7b8c9d0e1f",
"kind": "file",
"name": "returns-policy.pdf",
"mime_type": "application/pdf",
"size_kb": 412,
"length_pages": null,
"status": "uploaded",
"created_at": "2026-10-25T09:20:11+00:00"
}| Field | Type | Meaning |
|---|---|---|
id |
string | The source's id. Use it to delete the source. |
kind |
string | file, text or url (a website). |
name |
string | The file name, the first 60 characters of the text, or the website address. |
mime_type |
string or null | The file's type, such as application/pdf. Files only. |
size_kb |
integer or null | The file's size in kilobytes. Files only. |
length_pages |
integer or null | The text's length in pages of about 450 words. Texts only. |
status |
string | Where the source is in training. See below. |
created_at |
string | When the source was added. |
Training turns a source into small, searchable pieces called chunks. The status tells you how far it got:
| Status | Meaning |
|---|---|
uploaded |
A file is stored and waits for someone to click Train in the dashboard. The dashboard shows it as Ready to Train. |
crawling |
Chatvia is finding the pages of a website. |
crawled |
The website's pages were found. They wait for someone to click Train in the dashboard. |
pending |
The source waits in line to be trained. |
ingesting |
The source is being trained. |
ingested |
Training finished. The agent can answer from it. |
failed |
Training failed. Open the source in the dashboard to see why. |
To know when a source is ready, call List sources every few seconds and watch its status. There is no notification.
List sources
Returns the agent's files, texts and websites, newest first. Q&A pairs are not in this list.
GET /api/v1/agents/{agent}/sourcesWho can call it: anyone with access to the agent.
curl https://chat.example.com/api/v1/agents/a3f9c2e17b4d08/sources \
-H "Authorization: Bearer $CHATVIA_API_KEY"The answer is { "data": [source, …], "next_cursor": … }. See Pagination.
Add a file
Uploads a document, spreadsheet, presentation, image, recording or video as a source.
POST /api/v1/agents/{agent}/sources/filesWho can call it: the owner, or a teammate with Train Files. This one permission covers audio and video files too.
Send the file as multipart/form-data in a field called file:
curl https://chat.example.com/api/v1/agents/a3f9c2e17b4d08/sources/files \
-H "Authorization: Bearer $CHATVIA_API_KEY" \
-F "[email protected]"The answer is 201 Created with { "data": source }. The status is uploaded.
The file is not trained yet
A file added through the API waits as Ready to Train. The agent can't answer from it until a teammate opens the agent's Sources in the dashboard and clicks Train. The API has no endpoint to start training.
The upload is refused with a 422 when:
- the file type is not turned on. The admin of your Chatvia server chooses the types in Knowledge settings. File sources lists every type Chatvia can read.
- the type is turned on but the server can't read this file. For example, the program it needs is missing, or a recording is in a format the speech to text service doesn't take. See AI models.
- the file is a PDF locked with a password.
Unlike the dashboard, the API does not refuse a file your workspace has uploaded before. Uploading the same file twice gives you two sources.
Add a text
Adds a block of plain text as a source. Training starts on its own.
POST /api/v1/agents/{agent}/sources/textsWho can call it: the owner, or a teammate with Train Text.
| Body field | Type | Required | Notes |
|---|---|---|---|
content |
string | yes | At least 500 characters. Your workspace can hold each text only once. The same text again is a 422. |
curl https://chat.example.com/api/v1/agents/a3f9c2e17b4d08/sources/texts \
-H "Authorization: Bearer $CHATVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "content": "Our return policy. You can return any item within 30 days of delivery. ..." }'{
"data": {
"id": "0199f3c4-8e1f-7a2b-b3c4-d5e6f7a8b9c0",
"kind": "text",
"name": "Our return policy. You can return any item within 30 day...",
"mime_type": null,
"size_kb": null,
"length_pages": 1,
"status": "pending",
"created_at": "2026-10-25T09:22:40+00:00"
}
}The status moves from pending to ingesting to ingested, usually within seconds.
Add a website
Adds a website as a source and starts finding its pages.
POST /api/v1/agents/{agent}/sources/urlsWho can call it: the owner, or a teammate with Train Web.
| Body field | Type | Required | Notes |
|---|---|---|---|
url |
string | yes | The website address. It must be a public address. |
include_paths |
string | no | Only keep these paths, separated by commas, such as /docs/*,/help/*. Leave it out for the whole site. |
exclude_paths |
string | no | Skip these paths, separated by commas, such as /blog/*. |
curl https://chat.example.com/api/v1/agents/a3f9c2e17b4d08/sources/urls \
-H "Authorization: Bearer $CHATVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://help.example.com", "include_paths": "/articles/*" }'{
"data": {
"id": "0199f3c6-1a2b-7c3d-8e4f-5a6b7c8d9e0f",
"kind": "url",
"name": "https://help.example.com",
"mime_type": null,
"size_kb": null,
"length_pages": null,
"status": "crawling",
"created_at": "2026-10-25T09:25:02+00:00"
}
}Chatvia opens the address once to follow a redirect. When the address redirects, the source keeps the address it lands on. Then the pages are found in the background, up to 1,000 of them, and the status becomes crawled.
The pages are not trained yet
Like a file, a website added through the API waits after the crawl. A teammate selects it on the agent's Website page and clicks Train. Web sources explains the rest.
The request is refused with a 422 when:
- the agent already has this website.
- the address is not public, for example a private network address.
- Chatvia can't open the address.
Finding the pages needs Firecrawl, set by the admin of your Chatvia server in Knowledge settings. Without it the crawl fails.
Add a Q&A pair
Adds a question and the exact answer the agent should give. When a chatter asks one of the questions, or something very close, the agent replies with your answer word for word. Q&A pairs explains how the match works. Q&A pairs need no training, so they have no status.
POST /api/v1/agents/{agent}/sources/qasWho can call it: the owner, or a teammate with Train Q&A.
| Body field | Type | Required | Notes |
|---|---|---|---|
title |
string | yes | A short label shown in the dashboard's Q&A list. Up to 255 characters. |
questions |
array of strings | yes | The ways people ask it. At least one, each up to 1,000 characters. |
answer |
string | yes | The reply, at least 10 characters. |
curl https://chat.example.com/api/v1/agents/a3f9c2e17b4d08/sources/qas \
-H "Authorization: Bearer $CHATVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Cancel a subscription",
"questions": ["How do I cancel my subscription?", "Where do I unsubscribe?"],
"answer": "You can cancel from Settings, then Billing. Your access continues until the end of the billing period."
}'{
"data": {
"id": "0199f3c8-5d6e-7f80-9a1b-2c3d4e5f6a7b",
"title": "Cancel a subscription",
"questions": ["How do I cancel my subscription?", "Where do I unsubscribe?"],
"answer": "You can cancel from Settings, then Billing. Your access continues until the end of the billing period.",
"created_at": "2026-10-25T09:27:31+00:00"
}
}Keep the id from this answer. The API has no endpoint that lists Q&A pairs, so it is the only way to delete the pair later through the API.
Delete a source
Each kind has its own delete endpoint. Use the id of the source.
DELETE /api/v1/agents/{agent}/sources/files/{id}
DELETE /api/v1/agents/{agent}/sources/texts/{id}
DELETE /api/v1/agents/{agent}/sources/urls/{id}
DELETE /api/v1/agents/{agent}/sources/qas/{id}Who can call it: the owner, or a teammate with Delete sources.
curl -X DELETE https://chat.example.com/api/v1/agents/a3f9c2e17b4d08/sources/files/0199f3c1-2b3a-7d4e-9f50-6a7b8c9d0e1f \
-H "Authorization: Bearer $CHATVIA_API_KEY"The answer is 204 No Content. A source that the agent in the path doesn't use is a 404.
Good to know:
- Deleting removes the source and its chunks. A source that is still training stops first.
- A file, text or website is deleted for good, also from other agents that use it. The dashboard can remove a file from one agent only. The API can't.
- Past conversations keep their text. New questions can't find the deleted source.