Knowledge base Planned
The knowledge base grounds AI replies in your own content. Add a URL, we crawl up to two levels deep (typically 50 to 200 pages), chunk the text, embed each chunk with our self-hosted embeddings model, and store the vectors in our vector store. Used by Smart Hold, AI Receptionist, and agent assist for retrieval-augmented generation.
This endpoint is on the roadmap (Phase B, after the AI substrate ships). The surface here is the committed shape; details may move before launch.
Sources
A source is one starting URL plus the recursive pages we discover. Sources are workspace-scoped; chunks belong to sources.
List sources
Code samples
curl 'https://app.message.com/api/v1/kb/sources' \
-H 'Authorization: Bearer YOUR_WORKSPACE_JWT'const res = await fetch('https://app.message.com/api/v1/kb/sources', {
headers: { Authorization: 'Bearer ' + token }
});
const { sources } = await res.json();import requests
r = requests.get(
"https://app.message.com/api/v1/kb/sources",
headers={"Authorization": f"Bearer {token}"},
)
sources = r.json()["sources"]require "net/http"
require "json"
uri = URI("https://app.message.com/api/v1/kb/sources")
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
req = Net::HTTP::Get.new(uri)
req["Authorization"] = "Bearer #{token}"
http.request(req)
end
sources = JSON.parse(res.body)["sources"]<?php
$ctx = stream_context_create([
"http" => ["method" => "GET", "header" => "Authorization: Bearer $token"]
]);
$sources = json_decode(file_get_contents("https://app.message.com/api/v1/kb/sources", false, $ctx), true)["sources"];Add a source
Starts a crawl. Returns the source record with status: crawling; flips to ready when embeddings are computed.
| Field | Type | Description |
|---|---|---|
| urlrequired | string | Start URL. We crawl this domain only, up to 2 levels deep. |
| nameoptional | string | Display name. Defaults to the page title at the start URL. |
| maxPagesoptional | integer | Cap on pages crawled. Defaults to 200, maximum 1000. |
| respectRobotsTxtoptional | boolean | Honour robots.txt. Defaults to true; set false only for first-party domains you own. |
{
"id": "uuid",
"name": "Acme docs",
"url": "https://docs.acme.com",
"status": "ready",
"chunkCount": 1432,
"lastCrawledAt": "2026-05-13T15:00:00Z",
"createdAt": "2026-05-10T12:00:00Z"
}Refresh a source
Forces a fresh crawl. New chunks replace old chunks under the same source ID.
Delete a source
Removes the source and all its chunks from the vector store.
Semantic search
Run a semantic search across all chunks in the workspace. Embeds the query, runs cosine-similarity search over the vector store, returns the top-K chunks. Used by AI features internally; exposed for custom UIs.
{
"query": "How do I cancel a subscription?",
"topK": 5
}{
"results": [
{
"chunkId": "uuid",
"sourceId": "uuid",
"url": "https://docs.acme.com/billing/cancel",
"text": "To cancel your subscription, visit...",
"score": 0.82
}
]
}Chunks
List the chunks in a source. Cursor-paginated. Used for spot-checking that the right content was indexed.
Errors
| Code | When |
|---|---|
400 invalid_url | URL did not parse or scheme is not https. |
402 plan_limit | Workspace plan does not include AI / KB features. |
422 crawl_blocked | robots.txt disallows; you can override with respectRobotsTxt: false on first-party domains. |
Common pitfalls
- Pointing at a help-center hosted on a different domain. Crawls stay within one apex. Add the help-center as a separate source.
- Indexing a constantly-changing site without recrawling. Default cadence is weekly. Bump it via PATCH for high-churn docs.
- Searching without grounding. The search endpoint returns chunks; combining those chunks with an LLM is the AI engagement. See RAG concept.