Knowledge Sync API
Push FAQs, documents, rows and offerings from your own system.
On this page: Basics · Knowledge records · The 202 answer · Deletes · Credits · Offerings feed · Your original fields · Errors
Basics
| Endpoint | POST http://centralai.daffodil-bd.com/knowledge/api/v1/sync/ |
|---|---|
| Credential | Your external API key in the X-API-Key header.
It is secret: call this API from your own server only. See Security and keys. |
| Plans | Growth, Scale, Enterprise (the API Sync feature). |
| Body | JSON: action, records, and optionally source_name or "type": "offering". |
| Actions | create, update, upsert, delete. Default: upsert. |
Use it to keep your agent in step with a database, CRM, LMS or shop you already run: send a record when it changes, and delete it when it goes away. There are two destinations:
- Knowledge records (the default): text your chat agent answers from.
- Offerings (
"type": "offering"): rows in What you sell, with a price.
Knowledge records
Every record needs an id: your own, stable id for it. Sending the same id again updates the
record instead of adding a second one. The fields decide what kind of record it is:
| Shape | When | What the agent reads |
|---|---|---|
| FAQ | The record has question and answer. |
The question and answer. The FAQ also appears in Training Data, with title, description,
url and price when you send them. |
| Document | The record has content (and no question and answer). | The content as it is. |
| Row | Anything else. | Every non-empty field except id, as field: value | field: value. |
curl -X POST "http://centralai.daffodil-bd.com/knowledge/api/v1/sync/" \
-H "X-API-Key: YOUR_EXTERNAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"action": "upsert",
"source_name": "Help centre",
"records": [
{"id": "faq-001", "question": "Do you deliver outside Dhaka?",
"answer": "Yes, anywhere in Bangladesh in 3 to 5 days.", "url": "https://yourshop.com/delivery"},
{"id": "doc-001", "title": "Refund policy", "content": "You can return any item within 7 days..."},
{"id": "row-001", "branch": "Gulshan", "hours": "10 AM to 8 PM", "phone": "+880 1XXX-XXXXXX"}
]
}'
source_namegroups the records under one source in your knowledge base. Default:API Sync.- A record whose text is shorter than about ten characters is skipped.
- Each record is one piece of knowledge; it is not split. The agent is given about the first 4000 characters of a record, so send a long document as several records (one per section).
createrefuses anidyou already sent;updaterefuses one you never sent;upsertdoes either.
The 202 answer
Knowledge records are accepted at once and processed in the background, so the answer is 202 Accepted:
{"success": true, "status": "processing",
"message": "Accepted 3 records for processing in the background.",
"results": {"action": "upsert", "accepted": 3}}
The answer does not list per-record results. When processing finishes, your company admins get an in-app
notification, API Knowledge Sync Completed, with how many records were created, updated and deleted. A record
whose content has not changed is skipped. Records appear under their source in your knowledge base; check there if a
record you sent is missing (it may have had no id or too little text).
Deletes
{"action": "delete", "records": [{"id": "doc-001"}, {"id": "row-001"}]}
A delete names records by id and removes them from your knowledge base. An id you never sent
is ignored. An FAQ that a synced record created can stay listed in Training Data after the record is deleted; delete
it there too if you see it.
Credits and limits
- Each new record uses one knowledge credit. Updates, unchanged records and deletes use none.
- Deleting a record does not give its credit back.
- A
createorupsertcall is refused (403) when it carries more records than you have knowledge credits left, even if some of them are updates. Split the call, or buy more credits. - There is no other fixed limit on the number of knowledge records in one call; keep calls to a few hundred records.
Offerings feed ("type": "offering")
With "type": "offering" the records become offerings, the
structured rows (with prices) that the chat agent and the AI Sales Agent sell from.
curl -X POST "http://centralai.daffodil-bd.com/knowledge/api/v1/sync/" \
-H "X-API-Key: YOUR_EXTERNAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "offering",
"action": "upsert",
"records": [
{"id": "NN-101", "name": "Oslo 3-Seater Sofa", "kind": "product",
"price": "48500", "currency": "BDT", "stock": 6, "category": "Sofas",
"url": "https://yourshop.com/product/nn-101",
"image_url": "https://yourshop.com/images/nn-101.jpg"}
]
}'
Fields
| Field | What it is |
|---|---|
id | Required. Your own id for the offering. The same id always updates the same offering. |
name | Required to create. Up to 255 characters. |
kind | One of the offering kinds below. Default: product. |
price | A number that is not negative, such as 1250.00. Required unless quote_required is true. |
currency | Three-letter code such as BDT or USD. Default: your company currency. |
quote_required | true when the offering is priced on request (no list price). |
sku | Your SKU, up to 100 characters. |
description | Long description, up to 20,000 characters. |
subtitle | One or two lines for the chat card, up to 500 characters. |
category | Category name. Created when you do not have it yet; empty removes the category. |
stock | Whole number of units in stock; switches stock tracking on. Empty or null switches it off. |
url | The page where the customer buys, books or applies (https). Drives the card's page button. |
image_url | Image link (https). |
tags | A list of short words customers might search for. |
active | false archives the offering; true (or sending it again) brings it back. |
featured | true marks the offering as featured. |
Kinds: product (Product), service (Service), course_intake (Course intake), appointment (Appointment), event_date (Event date), plan (Plan), custom (Custom).
A field not in this list refuses that record. At most 20 tags are kept.
How the feed behaves
- At most 500 records per call. A larger call is refused whole.
- The answer is immediate (200) and lists every record that was refused, with its reason. One bad record never blocks the others.
- No knowledge credits. Offerings count against your plan’s offering limit instead: a record that
would add an active offering past it is refused with
Offering limit reached (N active offerings)(N is your limit). - Delete archives the offering (it is never erased). Sending the same
idagain brings it back. - Synced offerings are read-only on the offerings screen: change them in your system and sync again.
{"success": true, "type": "offering",
"results": {"action": "upsert", "processed": 1, "created": 1, "updated": 0,
"archived": 0, "skipped": 0, "errors": []}}
A refused record appears in errors as {"id": "NN-102", "error": "price: required unless quote_required is true."}.
Your original fields are kept
Central AI keeps each knowledge record exactly as you sent it (up to 32 KB of JSON per record), not
only the text it made from it. That lets later features use fields the text does not carry. Today:
Find what I sell takes a record’s page link from its
url, link, page_url field
(the first one that is an https:// address). So send a url with every record that has a
page on your site.
Errors
Knowledge Sync answers errors as {"error": "<message>"}, without a code.
| HTTP | Why |
|---|---|
| 401 | Missing X-API-Key header, Invalid API key,
or a message saying the widget key was sent (use your external API key). |
| 403 | No active subscription, API Sync not on your plan, or not enough knowledge credits. The answer
carries upgrade_url. |
| 400 | The body is not a JSON object, there are no records, the action is unknown, or (offerings) the call has too many records. |
| 500 | An unexpected error. Safe to retry later. |
Signed in? The full reference is on your dashboard’s API reference.
Signed in? Your own keys, endpoint addresses and the full error tables are
on the API reference inside your dashboard. These public pages never show
anyone’s key: examples use placeholders such as YOUR_EXTERNAL_API_KEY.