Skip to content

Knowledge Base ​

Upload documents into your Knowledge Base from your own systems, search it, and organise its files and folders — the same Knowledge Base your agents answer from.

OperationEndpointScope
Upload a filePOST /api/v1/kb/fileskb:write
List filesGET /api/v1/kb/fileskb:read
Get a file's detailsGET /api/v1/kb/files/{id}kb:read
Download a fileGET /api/v1/kb/files/{id}/downloadkb:read
Move a filePOST /api/v1/kb/files/{id}/movekb:write
Delete a fileDELETE /api/v1/kb/files/{id}kb:write
SearchPOST /api/v1/kb/searchkb:read
List foldersGET /api/v1/kb/folderskb:read
Create a folderPOST /api/v1/kb/folderskb:write
Rename a folderPATCH /api/v1/kb/folders/{id}kb:write
Delete an empty folderDELETE /api/v1/kb/folders/{id}kb:write

Uploading a file ​

Send the file as multipart/form-data, in a field named file (up to 200 MB):

bash
curl -X POST "https://<your-workspace>-api.perfox.ai/api/v1/kb/files" \
  -H "Authorization: Bearer sk_…" \
  -F "file=@product-manual.pdf" \
  -F "name=Product manual" \
  -F "folder_id=fld_abc123"
FieldRequiredWhat
fileyesThe document. The same formats the Knowledge Base page accepts — PDF, Office documents, spreadsheets, text, email files, images, audio and video. An unsupported type returns 415 unsupported_mime.
namenoDisplay name. Defaults to the filename.
folder_idnoThe folder to put it in. Omit for the root.

The response is 201 with the new file and status: "pending". Indexing runs in the background: poll GET /api/v1/kb/files/{id} until status is active (ready to answer from) or error.

File details ​

Every file — from an upload, a get or a list — has this shape:

FieldMeaning
idFile id
nameDisplay name
statuspending → processing → active, or error
mime_type, file_sizeWhat was uploaded, and its size in bytes
folder_idIts folder, or null at the root
chunk_countHow many searchable passages it was split into
created_at / updated_atTimestamps

GET /api/v1/kb/files/{id}/download returns the original bytes with their content type, so you can show a preview or hand the file back to a user.

Listing files ​

Files come back newest first, with limit up to 200 (50 by default).

bash
curl "https://<your-workspace>-api.perfox.ai/api/v1/kb/files?limit=50" \
  -H "Authorization: Bearer sk_…"

Pass folder_id to list a single folder. Omit it to list the root — the same spelling the folder listing uses, so you do not need a second convention for "top level". Pass status (for example active) to list only files in that state.

When more rows exist the response carries next_cursor; send it back as cursor. The cursor is a position in time rather than an offset, so files uploaded while you are paging cannot make you skip or repeat a row.

Moving and deleting files ​

POST /api/v1/kb/files/{id}/move with {"folder_id": "…"} moves a file into a folder; send {"folder_id": null} to move it to the root. A folder that does not exist returns 404 folder_not_found.

DELETE /api/v1/kb/files/{id} removes the file completely — the document, and everything agents used to search it. It is the same as deleting it on the Knowledge Base page. If the file was the current version of a document you had uploaded more than once, the previous version becomes current again, so agents keep answering from the latest one that remains.

Searching ​

bash
curl -X POST "https://<your-workspace>-api.perfox.ai/api/v1/kb/search" \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{"query": "warranty on refurbished units", "top_k": 5}'
FieldValues
queryRequired. What to look for, in plain language.
top_kHow many matches to return, 1–20 (default 8).
folder_idSearch only the files in this folder.
kb_idSearch only this knowledge base record.

Omit both folder_id and kb_id to search everything. The response is { "matches": [ { "name", "id", "score" } ] }, best match first. This is a meaning-based search, so a match does not need to share the query's exact words.

Folders ​

GET /api/v1/kb/folders lists one level of folders, sorted by name: omit parent_id for the top level, or pass a folder's id to list its subfolders. Each folder has id, name, parent_id, path, created_at and updated_at.

POST /api/v1/kb/folders with {"name": "Manuals", "parent_id": "…"} creates a folder (omit parent_id for the top level) and returns 201. An unknown parent returns 404 parent_not_found.

Renaming a folder ​

bash
curl -X PATCH "https://<your-workspace>-api.perfox.ai/api/v1/kb/folders/{id}" \
  -H "Authorization: Bearer sk_…" \
  -H "Content-Type: application/json" \
  -d '{"name": "Product manuals"}'

Renaming changes what the folder is called (1–200 characters), not which files are in it. Agents that select the folder keep working.

Deleting a folder — empty folders only ​

DELETE /api/v1/kb/folders/{id} removes a folder that holds no files and no subfolders.

If it still holds either, the call fails with 409 folder_not_empty and tells you exactly what is in the way:

json
{
  "error": "folder_not_empty",
  "message": "Folder still contains 12 file(s) and 3 subfolder(s). Delete its contents first — this endpoint will not cascade.",
  "files": 12,
  "subfolders": 3
}

This is narrower than deleting a folder in the workspace, on purpose

Deleting a folder in the workspace shows you everything inside it and asks you to confirm. An API call has no such moment, so a single request is not allowed to destroy files you never listed. To remove a whole folder tree, delete its contents first.

Agents are reported, not repaired ​

If any published agent still selects the folder you deleted, the response lists them:

json
{
  "success": true,
  "affected_agents": [
    { "id": "…", "name": "Support Assistant", "status": "published" }
  ]
}

Their Knowledge Base selection is left exactly as you configured it — the platform does not rewrite a published agent behind your back. But until you point them somewhere else, those agents retrieve nothing from that selection. This response is the one moment the connection between the deletion and the silence is visible, which is why it is reported here rather than quietly cleaned up.