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

FieldTypeNotes
idstringDocument ID.
titlestringSource title.
sourceTypestringStored source type, including web_crawl, file_upload, text_snippet, or qna_entry.
createdAtinteger or nullUnix timestamp in seconds.
lastCrawledAtinteger or nullUnix timestamp in seconds.
sourceMetadataany JSON valueStored source metadata.

List Sources

Path: /api/v2/agents/{agentId}/sources

GET /api/v2/agents/{agentId}/sources

Authentication: Bearer API key with access to {agentId}.

QueryRequiredConstraints
limitNoInteger from 1 to 100; defaults to 20.
cursorNoOpaque cursor returned by the preceding page. Replay it unchanged.
sourceTypeNoweb_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 fieldRequiredType and constraints
titleYesString from 1 to 200 characters before trimming; the accepted value is trimmed.
contentYesNonempty 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 fieldRequiredType and constraints
titleYesString from 1 to 200 characters before trimming; the accepted value is trimmed.
questionsYesArray of at most 10 strings, each at most 500 characters. At least one entry must contain a non-whitespace character.
answerYesNonempty 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 fieldRequiredType and constraints
urlYesNonempty 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.

FieldTypeNotes
statusstringtraining when a pending/running job exists, otherwise trained when a last-trained timestamp exists, otherwise idle.
documentCountintegerNumber of source documents for the agent.
lastTrainedAtinteger or nullUnix timestamp in seconds.
activeJobobject or nullMost recent pending/running job.
activeJob.idstringJob ID.
activeJob.statusstringStored job status.
activeJob.tasksCountintegerTotal task count.
activeJob.tasksCompletedCountintegerCompleted task count.
activeJob.createdAtinteger or nullUnix 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'