Knowledge Base
The knowledge base stores question-answer pairs that the assistant references when composing replies. Entries are scoped to a workspace and organised by topic. You can manage entries via the API to keep the knowledge base in sync with your documentation, product catalogues, or support articles.
Required scope: kb:read for GET endpoints, kb:write for write endpoints.
List entries
Section titled “List entries”Retrieve the knowledge base entries of a workspace, of every status, in creation order. Without limit and cursor, the response is every entry, as a bare JSON array.
curl "https://api.ohallo.eu/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/kb-entries" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"Response:
[ { "id": "11223344-5566-4788-99aa-bbccddeeff00", "workspaceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "question": "What are the standard shipping rates?", "answer": "Standard shipping is free for orders over EUR 100. For orders under EUR 100, shipping costs EUR 9.95. Express shipping (1-2 business days) is available for EUR 19.95 regardless of order value.", "topics": ["shipping", "pricing"], "sourceType": "manual", "status": "approved", "confidence": null, "usageCount": 47, "lastUsedAt": "2026-03-15T11:20:00.000Z", "createdAt": "2026-01-15T10:00:00.000Z", "updatedAt": "2026-02-20T14:30:00.000Z" }]Paging
Section titled “Paging”Send limit, cursor or both to read the list one page at a time. This request asks for one entry a page:
curl "https://api.ohallo.eu/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/kb-entries?limit=1" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Entries per page, from 1 to 100. A request with cursor and no limit returns 50 entries per page. |
cursor | string | No | The nextCursor of the previous page. |
Response:
{ "data": [ { "id": "11223344-5566-4788-99aa-bbccddeeff00", "workspaceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "question": "What are the standard shipping rates?", "answer": "Standard shipping is free for orders over EUR 100. For orders under EUR 100, shipping costs EUR 9.95. Express shipping (1-2 business days) is available for EUR 19.95 regardless of order value.", "topics": ["shipping", "pricing"], "sourceType": "manual", "status": "approved", "confidence": null, "usageCount": 47, "lastUsedAt": "2026-03-15T11:20:00.000Z", "createdAt": "2026-01-15T10:00:00.000Z", "updatedAt": "2026-02-20T14:30:00.000Z" } ], "nextCursor": "eyJjIjoiMjAyNi0wMS0xNVQxMDowMDowMC4wMDAwMDBaIiwiaSI6IjExMjIzMzQ0LTU1NjYtNDc4OC05OWFhLWJiY2NkZGVlZmYwMCJ9"}A page holds at most limit entries, ordered by createdAt and then id. nextCursor is present when more entries follow: send it as cursor to read the next page. The last page carries no nextCursor.
curl "https://api.ohallo.eu/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/kb-entries?limit=1&cursor=eyJjIjoiMjAyNi0wMS0xNVQxMDowMDowMC4wMDAwMDBaIiwiaSI6IjExMjIzMzQ0LTU1NjYtNDc4OC05OWFhLWJiY2NkZGVlZmYwMCJ9" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"A limit that is not an integer from 1 to 100, an empty cursor, and a cursor that is not a nextCursor value each answer 422 with { "error": "Invalid request", "details": { ... } }.
Get entry
Section titled “Get entry”Retrieve one knowledge base entry by its id, whatever its status.
Required scope: kb:read
curl "https://api.ohallo.eu/api/kb-entries/11223344-5566-4788-99aa-bbccddeeff00" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"Response:
{ "id": "11223344-5566-4788-99aa-bbccddeeff00", "workspaceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "question": "What are the standard shipping rates?", "answer": "Standard shipping is free for orders over EUR 100. For orders under EUR 100, shipping costs EUR 9.95. Express shipping (1-2 business days) is available for EUR 19.95 regardless of order value.", "topics": ["shipping", "pricing"], "sourceType": "manual", "status": "approved", "confidence": null, "usageCount": 47, "lastUsedAt": "2026-03-15T11:20:00.000Z", "createdAt": "2026-01-15T10:00:00.000Z", "updatedAt": "2026-02-20T14:30:00.000Z"}An id that names no entry of your account answers 404 with { "error": "KB entry not found" }. For an API key restricted to a brand or workspace, so does an entry in a workspace outside the restriction.
List topics
Section titled “List topics”Retrieve the topics in use in a workspace’s knowledge base: the topic tags of its approved entries, each once, sorted by name. Use them to tag a new entry, so entries on the same subject share a tag.
Required scope: kb:read
curl "https://api.ohallo.eu/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/kb-entries/topics" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"Response:
{ "topics": ["delivery", "pricing", "returns", "shipping"]}Search entries
Section titled “Search entries”Search knowledge base entries by the meaning of a query and by its words. The response is a bare JSON array, the best match first; rrf_score is how well an entry matches, the higher the better.
curl "https://api.ohallo.eu/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/kb-entries/search?q=how%20long%20does%20delivery%20take" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"Query parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query. An empty query returns an empty array. |
Response:
[ { "id": "11223344-5566-4788-99aa-bbccddeeff00", "question": "What are the standard delivery times?", "answer": "Standard delivery takes 3-5 business days within Germany and 5-7 business days for other EU countries. Express delivery (1-2 business days) is available at checkout.", "topics": ["shipping", "delivery"], "rrf_score": 0.0327 }]List pending entries
Section titled “List pending entries”Retrieve the entries awaiting review, newest first: proposals drafted by oHallo (proposed), for example by the learning loop from resolved conversations, and entries created for review (pending_review). The response is a bare JSON array.
curl "https://api.ohallo.eu/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/kb-entries/pending" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"Response:
[ { "id": "aabbccdd-eeff-4788-9233-445566778899", "workspaceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "question": "Can I change the delivery address after placing an order?", "answer": "You can change the delivery address up to 2 hours after placing the order by contacting support. After the order enters the packing stage, address changes are no longer possible.", "topics": ["shipping", "orders"], "sourceType": "extracted", "sourceConversationId": "c9f8e7d6-b5a4-3210-fedc-ba9876543210", "status": "proposed", "confidence": 0.78, "usageCount": 0, "lastUsedAt": null, "createdAt": "2026-03-14T16:00:00.000Z", "updatedAt": "2026-03-14T16:00:00.000Z" }]Create entry
Section titled “Create entry”Create a new knowledge base entry. An entry created with the sourceType manual is approved at once, and the assistant draws on it; an entry with any other sourceType starts as pending_review and waits for approval.
Required scope: kb:write
curl -X POST "https://api.ohallo.eu/api/workspaces/a1b2c3d4-e5f6-7890-abcd-ef1234567890/kb-entries" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx" \ -H "Content-Type: application/json" \ -d '{ "question": "What is your return policy?", "answer": "We accept returns within 30 days of delivery for unused items in original packaging. Contact support to initiate a return. Refunds are processed within 5 business days after we receive the item.", "sourceType": "manual", "topics": ["returns", "refunds"] }'Request body:
| Field | Type | Required | Description |
|---|---|---|---|
question | string | Yes | The question this entry answers |
answer | string | Yes | The answer content |
sourceType | string | Yes | Origin of the entry, e.g. "manual" |
topics | string[] | No | List of topic tags for categorisation |
sourceConversationId | string | No | The conversation this entry was derived from |
confidence | number | No | A score between 0.0 and 1.0 |
Response: 201 Created, with the entry.
{ "id": "ffeeddcc-bbaa-4788-9776-554433221100", "workspaceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "question": "What is your return policy?", "answer": "We accept returns within 30 days of delivery for unused items in original packaging. Contact support to initiate a return. Refunds are processed within 5 business days after we receive the item.", "topics": ["returns", "refunds"], "sourceType": "manual", "status": "approved", "confidence": null, "usageCount": 0, "lastUsedAt": null, "createdAt": "2026-03-15T15:00:00.000Z", "updatedAt": "2026-03-15T15:00:00.000Z"}One entry per question
Section titled “One entry per question”A workspace holds one entry per question, compared without case or surrounding spaces; a rejected entry holds none. A create, an update, an approval or a restore that would give a second entry a question the workspace already has answers 409:
{ "error": "An entry with this question already exists in the workspace", "code": "duplicate_question", "entryId": "11223344-5566-4788-99aa-bbccddeeff00"}entryId is the entry that holds the question: update that entry, or give the new one a question of its own. When your account reviews knowledge base changes before they apply, an update is saved for approval in the dashboard (202), and its question is checked when it is approved.
Update entry
Section titled “Update entry”Update an existing knowledge base entry. Only question, answer, and topics can be changed, and only the fields you include in the request body are modified.
Required scope: kb:write
curl -X PATCH "https://api.ohallo.eu/api/kb-entries/ffeeddcc-bbaa-4788-7766-554433221100" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx" \ -H "Content-Type: application/json" \ -d '{ "answer": "We accept returns within 30 days of delivery for unused items in original packaging. Extended holiday returns: items purchased between November 15 and December 31 can be returned until January 31. Contact support to initiate a return.", "topics": ["returns", "refunds", "holiday-policy"] }'Response: Returns the full updated entry. When your account reviews knowledge base changes before they apply, the change is saved as a version that waits for approval in the dashboard, the entry stays as it is, and the response is 202 with { "pending": true, "versionId": "..." }.
Approve entry
Section titled “Approve entry”Approve an entry that awaits review, making it available to the assistant. The response is the approved entry, or for a proposal that changes an existing entry, the entry it changed.
An entry that awaits review, with status proposed or pending_review, can be approved with edits in the body: the question, answer and topics you send are approved in place of the entry’s own, and the fields you do not send stay as they are. A proposal that changes an existing entry is applied to that entry: it takes the proposal’s answer, and the proposal’s topics when it has any, with your edits in place of the ones you send, and keeps its own question. When that entry was edited after the proposal was written, the approval answers 409 with the entry as it stands in currentTarget; approving again with expectedTargetVersionId set to its publishedVersionId applies the proposal onto it.
Required scope: kb:write
curl -X POST "https://api.ohallo.eu/api/kb-entries/aabbccdd-eeff-4788-2233-445566778899/approve" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx" \ -H "Content-Type: application/json" \ -d '{ "answer": "You can change the delivery address up to 2 hours after placing the order by contacting support." }'Approving an entry that is already approved answers with it unchanged, and approving one that was rejected answers 400.
Reject entry
Section titled “Reject entry”Reject an entry that awaits review. A proposal can be rejected with a rejectionReason; the learning loop reads recent rejections, with their reasons, before it drafts new proposals. Rejecting an entry that is already rejected answers with it unchanged, and rejecting one that was approved answers 400.
Required scope: kb:write
curl -X POST "https://api.ohallo.eu/api/kb-entries/aabbccdd-eeff-4788-2233-445566778899/reject" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx" \ -H "Content-Type: application/json" \ -d '{ "rejectionReason": "This information is outdated; our return window changed to 45 days in March 2026." }'Delete entry
Section titled “Delete entry”Permanently delete a knowledge base entry.
Required scope: kb:write
curl -X DELETE "https://api.ohallo.eu/api/kb-entries/ffeeddcc-bbaa-4788-7766-554433221100" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"Response: 200 OK with { "ok": true } on success.
Version history
Section titled “Version history”Every change to an approved entry publishes a version, recording who made it: a user ID for a person, api-key:<id> for a key.
Required scope: kb:read to read versions, kb:write to restore one.
curl "https://api.ohallo.eu/api/kb-entries/ffeeddcc-bbaa-4788-9776-554433221100/versions" \ -H "Authorization: Bearer sf_live_v1_a3Bx9kLmP2qR7wYz4nDfGhJkQpStUvWx"The response is { "versions": [...] }, newest first. GET /api/kb-entries/versions/{versionId} returns what one version held, and answers for a version of a deleted entry too. POST /api/kb-entries/{entryId}/versions/{versionId}/restore publishes that content again as a new version, leaving the history complete. It answers { "versionId": "...", "created": true, "restoredFrom": 2 }, with created false when the entry already holds that content.
Entry statuses
Section titled “Entry statuses”| Status | Meaning |
|---|---|
approved | Active; the assistant uses this entry when composing replies |
pending_review | Created for review, through the API with a sourceType other than manual; not used until it is approved |
proposed | Drafted by oHallo, for example by the learning loop from a resolved conversation; not used until it is approved. A proposal that changes an existing entry is applied to that entry when it is approved |
rejected | Rejected by a human reviewer; not used when composing replies |
archived | No longer in use, kept for the record |
Source types
Section titled “Source types”| Source | Meaning |
|---|---|
manual | Created by a human via the dashboard or API |
extracted | Proposed by the learning loop from a resolved conversation |
Extracted entries include a confidence score (0.0 to 1.0) and a sourceConversationId linking back to the conversation they were derived from.