API v2 Sources and Training
List and create agent sources, upload files directly to storage, delete documents, inspect training status, and start web-source retraining.
Use these endpoints to manage text, Q&A, URL, and file sources and to retrain indexed web sources. Every endpoint on this page requires Authorization: Bearer YOUR_API_KEY and access to {agentId}.
See the error catalog for shared authentication, validation, quota, and resource errors.
Source Object
| Field | Type | Notes |
|---|---|---|
id | string | Document ID. |
title | string | Source title. |
sourceType | string | Stored source type, including web_crawl, file_upload, text_snippet, or qna_entry. |
createdAt | integer or null | Unix timestamp in seconds. |
lastCrawledAt | integer or null | Unix timestamp in seconds. |
sourceMetadata | any JSON value | Stored source metadata. |
List Sources
Path: /api/v2/agents/{agentId}/sources
GET /api/v2/agents/{agentId}/sources
Authentication: Bearer API key with access to {agentId}.
| Query | Required | Constraints |
|---|---|---|
limit | No | Integer from 1 to 100; defaults to 20. |
cursor | No | Opaque cursor returned by the preceding page. Replay it unchanged. |
sourceType | No | web_crawl, file_upload, text_snippet, or qna_entry. |
curl 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/sources?sourceType=text_snippet&limit=20' \ -H 'Authorization: Bearer YOUR_API_KEY'
Success: 200 OK
{
"data": [
{
"id": "41b4c1d3-887d-46a5-95ae-c761922c6bc7",
"title": "Refund policy",
"sourceType": "text_snippet",
"createdAt": 1784332800,
"lastCrawledAt": null,
"sourceMetadata": null
}
],
"pagination": {
"cursor": null,
"hasMore": false,
"total": 1
}
}
Invalid limits, cursors, and source types return 400 VALIDATION_INVALID_BODY.
Add a Text Source
Path: /api/v2/agents/{agentId}/sources/text
POST /api/v2/agents/{agentId}/sources/text
Authentication: Bearer API key with access to {agentId}.
| Body field | Required | Type and constraints |
|---|---|---|
title | Yes | String from 1 to 200 characters before trimming; the accepted value is trimmed. |
content | Yes | Nonempty string, no more than 262,144 UTF-8 bytes (256 KB), and not only whitespace. |
curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/sources/text' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"title":"Refund policy","content":"Refunds are available within 30 days."}'
Success: 201 Created
{
"documentId": "41b4c1d3-887d-46a5-95ae-c761922c6bc7"
}
Invalid input or a non-storage processing failure returns 400 VALIDATION_INVALID_BODY. A processing storage-limit failure returns 403 QUOTA_STORAGE_LIMIT.
Add a Q&A Source
Path: /api/v2/agents/{agentId}/sources/qna
POST /api/v2/agents/{agentId}/sources/qna
Authentication: Bearer API key with access to {agentId}.
| Body field | Required | Type and constraints |
|---|---|---|
title | Yes | String from 1 to 200 characters before trimming; the accepted value is trimmed. |
questions | Yes | Array of at most 10 strings, each at most 500 characters. At least one entry must contain a non-whitespace character. |
answer | Yes | Nonempty string, no more than 262,144 UTF-8 bytes (256 KB), and not only whitespace. |
curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/sources/qna' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"title":"Shipping time","questions":["How long does shipping take?","When will my order arrive?"],"answer":"Standard shipping takes 3–5 business days."}'
Success: 201 Created
{
"documentId": "531a3fbe-40c2-4d22-a524-1f4a70f509f1"
}
Invalid input or a non-storage processing failure returns 400 VALIDATION_INVALID_BODY. A processing storage-limit failure returns 403 QUOTA_STORAGE_LIMIT.
Add or Retrain a URL Source
Path: /api/v2/agents/{agentId}/sources/url
POST /api/v2/agents/{agentId}/sources/url
Authentication: Bearer API key with access to {agentId}.
| Body field | Required | Type and constraints |
|---|---|---|
url | Yes | Nonempty HTTP or HTTPS URL with a domain. A missing protocol is normalized to https://. Loopback, private, link-local, unique-local, reserved IP ranges, localhost variants, internal TLDs, and single-label hostnames are rejected. |
Submitting a URL already indexed for the agent creates a retraining job. A new URL first checks storage capacity. Video URLs also require video-transcription plan access.
curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/sources/url' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"url":"https://docs.example.com/getting-started"}'
Success: 202 Accepted
{
"jobId": "c3c61f67-70fe-42da-a843-24112ded8aeb",
"isRetrain": false
}
Invalid input returns 400 VALIDATION_INVALID_BODY. Missing video-transcription access returns 403 SUBSCRIPTION_API_RESTRICTED_PLAN; storage or queue quota failures return 403 QUOTA_STORAGE_LIMIT; a non-quota job-creation failure returns 500 INTERNAL_SERVER_ERROR.
Add File Sources with Signed Upload URLs
File sources use a two-step API flow so file bytes travel directly from your client to private storage instead of passing through the API route. Each file can be at most 50 MB, and one request can contain at most 20 files. Supported extensions are .pdf, .txt, .md, .docx, .xlsx, and .pptx.
1. Create Signed Upload URLs
Path: /api/v2/agents/{agentId}/sources/file/upload-url
POST /api/v2/agents/{agentId}/sources/file/upload-url
Send the original file names:
{
"files": [
{ "fileName": "product-guide.pdf" },
{ "fileName": "faq.md" }
]
}
curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/sources/file/upload-url' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"files":[{"fileName":"product-guide.pdf"},{"fileName":"faq.md"}]}'
Success: 200 OK
{
"files": [
{
"fileName": "product-guide.pdf",
"storagePath": "chatbot-955f28f1-8515-40bb-802c-f3f730bf0343/V1StGXR8_Z5jdHi6-product-guide.pdf",
"uploadUrl": "https://storage.example.com/storage/v1/object/upload/sign/training_files/chatbot-955f28f1-8515-40bb-802c-f3f730bf0343/V1StGXR8_Z5jdHi6-product-guide.pdf?token=SIGNED_TOKEN",
"token": "SIGNED_TOKEN"
},
{
"fileName": "faq.md",
"storagePath": "chatbot-955f28f1-8515-40bb-802c-f3f730bf0343/N5jFt4Z9kSC3vHqA-faq.md",
"uploadUrl": "https://storage.example.com/storage/v1/object/upload/sign/training_files/chatbot-955f28f1-8515-40bb-802c-f3f730bf0343/N5jFt4Z9kSC3vHqA-faq.md?token=SIGNED_TOKEN",
"token": "SIGNED_TOKEN"
}
]
}
2. Upload the File Bytes
Upload each file directly to its uploadUrl with PUT:
await fetch(uploadUrl, {
method: 'PUT',
headers: { 'Content-Type': file.type },
body: file,
});
When using the Supabase JavaScript client, pass the matching path and token from step 1:
await supabase.storage
.from('training_files')
.uploadToSignedUrl(storagePath, token, file);
Do not change or construct storage paths yourself. Registration only accepts paths returned for this agent by step 1.
3. Register the Uploaded Files
Path: /api/v2/agents/{agentId}/sources/file
POST /api/v2/agents/{agentId}/sources/file
After every direct upload completes, register the returned paths with their original file names:
{
"files": [
{
"storagePath": "chatbot-955f28f1-8515-40bb-802c-f3f730bf0343/V1StGXR8_Z5jdHi6-product-guide.pdf",
"fileName": "product-guide.pdf"
},
{
"storagePath": "chatbot-955f28f1-8515-40bb-802c-f3f730bf0343/N5jFt4Z9kSC3vHqA-faq.md",
"fileName": "faq.md"
}
]
}
Success: 202 Accepted
{
"jobId": 321,
"fileCount": 2
}
Registration verifies that each object exists, is nonempty, is no larger than 50 MB, and belongs to the requested agent before starting the processing job. Invalid or missing uploads return 400 VALIDATION_INVALID_BODY; a storage quota denial returns 403 QUOTA_STORAGE_LIMIT; Storage or queue failures return 500 INTERNAL_SERVER_ERROR.
Delete a Source
Path: /api/v2/agents/{agentId}/sources/{documentId}
DELETE /api/v2/agents/{agentId}/sources/{documentId}
Authentication: Bearer API key with access to {agentId}.
{documentId} must be a UUID returned by a source creation or list response.
curl -X DELETE 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/sources/41b4c1d3-887d-46a5-95ae-c761922c6bc7' \ -H 'Authorization: Bearer YOUR_API_KEY'
Success: 200 OK
{
"deleted": true
}
An invalid UUID returns 400 VALIDATION_INVALID_BODY. A valid UUID that does not identify a document for the agent returns 404 RESOURCE_DOCUMENT_NOT_FOUND.
Get Training Status
Path: /api/v2/agents/{agentId}/train
GET /api/v2/agents/{agentId}/train
Authentication: Bearer API key with access to {agentId}.
Success: 200 OK, with a bare status object.
| Field | Type | Notes |
|---|---|---|
status | string | training when a pending/running job exists, otherwise trained when a last-trained timestamp exists, otherwise idle. |
documentCount | integer | Number of source documents for the agent. |
lastTrainedAt | integer or null | Unix timestamp in seconds. |
activeJob | object or null | Most recent pending/running job. |
activeJob.id | string | Job ID. |
activeJob.status | string | Stored job status. |
activeJob.tasksCount | integer | Total task count. |
activeJob.tasksCompletedCount | integer | Completed task count. |
activeJob.createdAt | integer or null | Unix timestamp in seconds. |
{
"status": "training",
"documentCount": 12,
"lastTrainedAt": 1784246400,
"activeJob": {
"id": "c3c61f67-70fe-42da-a843-24112ded8aeb",
"status": "running",
"tasksCount": 8,
"tasksCompletedCount": 3,
"createdAt": 1784332800
}
}
Start Web-Source Retraining
POST /api/v2/agents/{agentId}/train
Authentication: Bearer API key with access to {agentId}. This endpoint takes no request body.
The endpoint retrains indexed web URLs, not text, Q&A, or uploaded-file sources.
When at least one indexed URL exists, success is 202 Accepted:
{
"jobId": "c3c61f67-70fe-42da-a843-24112ded8aeb",
"count": 8,
"message": "Retraining started for 8 URLs"
}
When no indexed URLs exist, success is 200 OK and no job is created:
{
"jobId": null,
"count": 0,
"message": "No web sources to retrain"
}
curl -X POST 'https://your-domain.com/api/v2/agents/955f28f1-8515-40bb-802c-f3f730bf0343/train' \ -H 'Authorization: Bearer YOUR_API_KEY'