Zum Inhalt springen

Knowledge Documents and Bases

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

The routes under /api/v1/knowledge/ let your backend keep a tenant’s knowledge library in sync with your own system of record, and attach what it pushes to the knowledge bases an operator has already assembled.

Every route on this page requires Authorization: Bearer <key> — see Overview and authentication.

Every document route is keyed by an external_id you choose, never by a Designer-internal id you would have to store and reconcile. Use whatever your system already calls the record — a CRM ticket id, a CMS slug, a file path.

An external_id is scoped to your integration. Two integrations in the same tenant can each use handbook-v3 without colliding, and an external_id you never pushed is a 404 whether it does not exist at all or belongs to someone else.

{
"externalId": "handbook-v3",
"name": "handbook.pdf",
"kind": "pdf",
"mimeType": "application/pdf",
"sizeBytes": 184320,
"contentHash": "b1946ac92492d2347c6235b4d2611184",
"createdAt": 1756100000,
"updatedAt": 1756186400
}
FieldTypeNotes
externalIdstringThe id you supplied.
namestringThe uploaded filename.
kindpdf | xlsx | csv | txt | mdDerived from the file extension.
mimeTypestringCanonical MIME type for the kind.
sizeBytesintegerStored size.
contentHashstringContent hash of the stored document.
createdAtintegerUnix epoch in seconds — when this external_id was first pushed.
updatedAtintegerUnix epoch in seconds — when it last changed.

The timestamps belong to your mapping, not to the underlying stored document. Identical content pushed under two external_ids is stored once and shared, so only the mapping’s timestamps are meaningful per-external_id values.

Both write routes take a multipart/form-data body.

FieldRouteNotes
filebothRequired. The document bytes.
external_idPOST onlyRequired on POST. Ignored by PUT, whose external_id is the path parameter.

Unknown fields are ignored rather than rejected, so you can send metadata this version does not read without breaking.

  • Accepted extensions: PDF, Excel (.xlsx), CSV, TXT, MD.
  • Maximum size: 5 MiB per file.

POST /api/v1/knowledge/documents

Create only. An external_id your integration already holds is a 409 — an accidental re-POST is never mistaken for an update.

Terminal window
curl -sS -X POST "$GREENTIC_DESIGNER/api/v1/knowledge/documents" \
-H "Authorization: Bearer $GREENTIC_KEY" \
-F "external_id=handbook-v3" \
-F "file=@./handbook.pdf"
StatusBody
201The document object — the content was genuinely new.
200The document object — the content matched a document already stored for this tenant and was shared rather than stored again.
400 missing_fileNo file field.
400 missing_external_idNo external_id field, or it was blank.
400 decodeThe multipart body could not be read.
409 external_id_existsThis external_id already exists for this integration — use PUT.
413 file_too_largeOver 5 MiB.
415 unsupported_file_typeExtension is not PDF / Excel / CSV / TXT / MD.
422 extraction_failedThe file was accepted but no text could be extracted from it.
500 internal_errorStorage or mapping write failed.

PUT /api/v1/knowledge/documents/{external_id}

Upsert: creates when the external_id is absent, replaces when it is present.

Terminal window
curl -sS -X PUT "$GREENTIC_DESIGNER/api/v1/knowledge/documents/handbook-v3" \
-H "Authorization: Bearer $GREENTIC_KEY" \
-F "file=@./handbook.pdf"
StatusBody
201The document object — there was no prior mapping, so this was a create.
200{ "unchanged": true, "externalId": "handbook-v3" } — the uploaded bytes are identical to what this external_id already resolved to.
200The document object — the content differed and the mapping was repointed.
400 / 413 / 415 / 422 / 500Same codes as POST.

When content does change, the mapping is repointed to the new stored document. If the document you were pointing at was one your integration created, its knowledge-base memberships are carried across, so a base that held the old version holds the new one and is marked stale. If you were pointing at a document you do not own — an operator’s, or another integration’s, reached because an earlier push happened to match its content — nothing about that document or its bases is touched. Only your mapping moves.

GET /api/v1/knowledge/documents/{external_id}

Terminal window
curl -sS "$GREENTIC_DESIGNER/api/v1/knowledge/documents/handbook-v3" \
-H "Authorization: Bearer $GREENTIC_KEY"

Metadata only — the original bytes are not served back by this API.

StatusBody
200The document object.
404 document_not_foundNo document with that external_id for this integration.
500 internal_errorThe read failed.

GET /api/v1/knowledge/documents

Cursor-paginated by external_id.

Terminal window
curl -sS "$GREENTIC_DESIGNER/api/v1/knowledge/documents?limit=100" \
-H "Authorization: Bearer $GREENTIC_KEY"
Query parameterDefaultNotes
limit50Clamped to the range 1–200.
afterThe previous page’s nextCursor.
{
"documents": [
{
"externalId": "handbook-v3",
"name": "handbook.pdf",
"kind": "pdf",
"mimeType": "application/pdf",
"sizeBytes": 184320,
"contentHash": "b1946ac92492d2347c6235b4d2611184",
"createdAt": 1756100000,
"updatedAt": 1756186400
}
],
"nextCursor": null
}

nextCursor is null on the last page. Pass it back as after to fetch the next one.

Only documents this integration pushed are listed.

StatusBody
200{ "documents": [...], "nextCursor": ... }
500 internal_errorThe query failed.

DELETE /api/v1/knowledge/documents/{external_id}

Terminal window
curl -sS -X DELETE "$GREENTIC_DESIGNER/api/v1/knowledge/documents/handbook-v3" \
-H "Authorization: Bearer $GREENTIC_KEY" \
-i

Removes your mapping. The stored document itself is removed only when no mapping of any kind still references it and your integration is the one that created it.

StatusBody
204Empty.
404 document_not_foundNo document with that external_id for this integration.
500 internal_errorThe delete failed.

A knowledge base is a collection an operator assembles and a deployed worker retrieves from. This API can discover bases and change their membership, but not create or destroy them.

GET /api/v1/knowledge/bases

Terminal window
curl -sS "$GREENTIC_DESIGNER/api/v1/knowledge/bases" \
-H "Authorization: Bearer $GREENTIC_KEY"
{
"bases": [
{
"id": "<kb-id>",
"name": "Support handbook",
"description": "Everything the tier-1 desk needs",
"documentCount": 42,
"createdAt": 1756000000,
"updatedAt": 1756186400,
"indexState": "stale"
}
]
}
FieldNotes
idUse this as {kb_id} on the two routes below.
descriptionMay be null.
documentCountDocuments currently in the base, from every source.
indexStateThe one field you can use to observe the effect of your own attach and detach calls.

Bases are listed for the key’s tenant and team — this route shows what that team has, not only what your integration pushed. Embedding configuration and vector-build metadata are operator concerns and are deliberately not exposed here.

StatusBody
200{ "bases": [...] }
500 internal_errorThe query failed.

POST /api/v1/knowledge/bases/{kb_id}/documents

Terminal window
curl -sS -X POST "$GREENTIC_DESIGNER/api/v1/knowledge/bases/<kb-id>/documents" \
-H "Authorization: Bearer $GREENTIC_KEY" \
-H "Content-Type: application/json" \
-d '{ "externalIds": ["handbook-v3", "refund-policy-2026"] }'
{ "linked": 2 }

linked counts the membership rows actually created — re-attaching a document that is already a member adds nothing and is not an error.

StatusBody
200{ "linked": <count> }
404 knowledge_base_not_foundNo knowledge base with that id for this tenant and team.
404 document_not_foundOne of the externalIds does not resolve under this integration.
500 internal_errorThe lookup or write failed.

DELETE /api/v1/knowledge/bases/{kb_id}/documents/{external_id}

Terminal window
curl -sS -X DELETE "$GREENTIC_DESIGNER/api/v1/knowledge/bases/<kb-id>/documents/handbook-v3" \
-H "Authorization: Bearer $GREENTIC_KEY" \
-i

Idempotent: detaching a document that was never a member of that base still answers 204. Only an id that cannot be resolved at all is an error.

StatusBody
204Empty.
404 knowledge_base_not_foundNo knowledge base with that id for this tenant and team.
404 document_not_foundNo document with that external_id for this integration.
500 internal_errorThe lookup or write failed.

Attaching or detaching marks the affected base’s index stale — its published index no longer matches its contents, and the outbound sync reads that flag to know it must rebuild. Poll indexState on GET /api/v1/knowledge/bases to watch it settle.

Marking is best-effort and happens after the membership change has already succeeded, so a 200 or 204 means the membership changed; it does not on its own guarantee the stale flag was written.

  1. Confirm the key’s scope with GET /api/v1/knowledge/whoami.

  2. Discover the target base with GET /api/v1/knowledge/bases and keep its id.

  3. Push each record with PUT /api/v1/knowledge/documents/{your-id}. Unchanged records cost nothing, so a full resync is safe to run on a schedule.

  4. Attach the new ones with POST /api/v1/knowledge/bases/{kb_id}/documents. Already-attached ids are harmless.

  5. Remove retired records with DELETE /api/v1/knowledge/documents/{your-id}.

  6. Stay under the rate limit — see Rate limiting before sizing your batch loop.