Batch sources
Up to 50 sources in one call. The normal way to sync a catalogue.
/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.
409 for the whole batch if the collection is an AI employee's Corrections collection, which takes Corrections filed in Heppu only.
Otherwise 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.
