Items: single, batch, snapshot, deletes & tombstones
The staging set of a source is the full desired state of its content. You mutate it with four operations; a run later reads it.
Item shape
{ "externalItemId": "faq-1", // REQUIRED — stable id you own (≤ 1024 chars) "title": "Refund policy", // REQUIRED (≤ 2048 chars) "content": "Refunds take 14 days.", // REQUIRED — markdown or plain text "externalParentId": "section-billing", // optional "externalVersion": "v3", // optional, your version marker "contentType": "text/markdown", // optional (default text/markdown) "sourceUrl": "https://help.example.com/refunds", // optional "metadata": { "lang": "en" }, // optional, free-form JSON "visibility": "public", // public | internal | restricted | disabled "publishTarget": "public_widget" // public_widget | internal_assistant}visibility and publishTarget default to the source’s defaults when omitted.
Short content is fully supported: even a single sentence (well under the internal chunking minimum) is indexed as one searchable chunk — it is never silently dropped. Empty or whitespace/heading-only content contributes no searchable chunk. A publish that would turn real content into zero searchable chunks fails closed rather than publishing an empty result.
1. Single upsert
Re-using an externalItemId updates the same item (naturally idempotent).
curl -X POST "$CHATBOT_API/v1/sources/$SID/items" \ -H "Authorization: Bearer $CHATBOT_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{"externalItemId":"faq-1","title":"Refunds","content":"Refunds take 14 days."}'201 when created, 200 when updated.
2. Batch upsert (atomic, rolling)
Validates every item before writing — either the whole batch lands or none of it does, so a partial batch can never look like a deletion. A batch is a rolling upsert: items it does not name are left untouched. Max 1000 items, 8 MiB body.
curl -X POST "$CHATBOT_API/v1/sources/$SID/items/batch" \ -H "Authorization: Bearer $CHATBOT_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: import-7" \ -d '{"items":[ {"externalItemId":"faq-1","title":"Refunds","content":"…"}, {"externalItemId":"faq-2","title":"Shipping","content":"…"} ]}'# → { "batch": { "count": 2, "created": 1, "updated": 1 } }3. Full snapshot (replace the whole set)
PUT replaces the entire staging set atomically. Items present before but
absent now are tombstoned — a subsequent run with complete discovery turns
those tombstones into removals (subject to the source’s graceDays). Use this
when your system can produce the complete current state.
curl -X PUT "$CHATBOT_API/v1/sources/$SID/items" \ -H "Authorization: Bearer $CHATBOT_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: snapshot-2024-06-01" \ -d '{"items":[ …the complete current set… ]}'# → { "snapshot": { "count": 42 } }4. Delete / tombstone
Soft-delete one or many items. Deleted items become tombstones; a run propagates the removal to the published generation (after the grace window).
# singlecurl -X POST "$CHATBOT_API/v1/sources/$SID/items/delete" \ -H "Authorization: Bearer $CHATBOT_KEY" -H "Content-Type: application/json" \ -d '{"externalItemId":"faq-1"}'
# manycurl -X POST "$CHATBOT_API/v1/sources/$SID/items/delete" \ -H "Authorization: Bearer $CHATBOT_KEY" -H "Content-Type: application/json" \ -d '{"externalItemIds":["faq-1","faq-2"]}'# → { "delete": { "requested": 2, "deleted": 2 } }Listing
curl "$CHATBOT_API/v1/sources/$SID/items" # active itemscurl "$CHATBOT_API/v1/sources/$SID/items?includeDeleted=true" # + tombstonesChoosing rolling vs snapshot
| Use… | When |
|---|---|
| Single / batch upsert + delete | You receive incremental changes (webhooks, CDC) and know exactly what changed. |
Full snapshot (PUT) | You can re-export the complete current state and want removals handled automatically. |
Both are safe and atomic; pick whichever matches how your source system emits changes.