Batch sources
Up to 50 sources in one call. The normal way to sync a catalogue.
POST
/api/v1/kb/sources/batchSame per-source fields as the single endpoint, minus collectionId which moves to the top.
{
"collectionId": "col_…",
"sources": [
{ "externalId": "VIN-1", "title": "…", "content": "…" },
{ "externalId": "VIN-2", "title": "…", "content": "…", "contentRole": "historical" }
]
}1 to 50 sources. One failing source doesn't stop the others.
Always 200, even if every source failed. Read summary:
{
"data": {
"results": [
{ "externalId": "VIN-1", "documentId": "1f0a…", "status": "created" },
{ "externalId": "VIN-2", "documentId": "2b7c…", "status": "updated" },
{ "externalId": "VIN-3", "documentId": "3d1e…", "status": "unchanged" },
{ "externalId": "VIN-4", "documentId": "", "status": "failed", "error": "…" }
],
"summary": { "total": 4, "created": 1, "updated": 1, "unchanged": 1, "failed": 1 },
"message": "Processed 4 sources: 1 created, 1 updated, 1 unchanged, 1 failed"
},
"meta": { "timestamp": "…" }
}Validation is all-or-nothing though. One bad field anywhere and the whole batch is a 400 naming the path, like sources.3.content: content too long (max 500KB).
Sync recipe
Nightly catalogue sync, in pseudo code:
for chunk in chunks(catalogue, 50):
POST /v1/kb/sources/batch { collectionId, sources: chunk }
stale = GET /v1/kb/sources?collectionId=… minus ids in catalogue
for chunk in chunks(stale, 100):
DELETE /v1/kb/sources { collectionId, externalIds: chunk }Unchanged sources are free, so re-posting the full catalogue every night is fine. Don't put the same externalId twice in one batch, the second one creates a duplicate.
