Buscar en la base de conocimientos por full-text, vector o híbrido.
curl --request POST \
--url https://api.keebai.com/v1/knowledge/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "¿cómo cancelar suscripción?",
"mode": "hybrid",
"top_k": 5,
"node_ids": [
"<string>"
]
}
'import requests
url = "https://api.keebai.com/v1/knowledge/search"
payload = {
"query": "¿cómo cancelar suscripción?",
"mode": "hybrid",
"top_k": 5,
"node_ids": ["<string>"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '¿cómo cancelar suscripción?',
mode: 'hybrid',
top_k: 5,
node_ids: ['<string>']
})
};
fetch('https://api.keebai.com/v1/knowledge/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.keebai.com/v1/knowledge/search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => '¿cómo cancelar suscripción?',
'mode' => 'hybrid',
'top_k' => 5,
'node_ids' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.keebai.com/v1/knowledge/search"
payload := strings.NewReader("{\n \"query\": \"¿cómo cancelar suscripción?\",\n \"mode\": \"hybrid\",\n \"top_k\": 5,\n \"node_ids\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.keebai.com/v1/knowledge/search")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"¿cómo cancelar suscripción?\",\n \"mode\": \"hybrid\",\n \"top_k\": 5,\n \"node_ids\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.keebai.com/v1/knowledge/search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"¿cómo cancelar suscripción?\",\n \"mode\": \"hybrid\",\n \"top_k\": 5,\n \"node_ids\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"node_id": "<string>",
"score": 123,
"title": "<string>",
"snippet": "<string>"
}
]
}Knowledge base
POST /v1/knowledge/search
Search the knowledge base by full-text, vector, or hybrid.
POST
/
v1
/
knowledge
/
search
Buscar en la base de conocimientos por full-text, vector o híbrido.
curl --request POST \
--url https://api.keebai.com/v1/knowledge/search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "¿cómo cancelar suscripción?",
"mode": "hybrid",
"top_k": 5,
"node_ids": [
"<string>"
]
}
'import requests
url = "https://api.keebai.com/v1/knowledge/search"
payload = {
"query": "¿cómo cancelar suscripción?",
"mode": "hybrid",
"top_k": 5,
"node_ids": ["<string>"]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '¿cómo cancelar suscripción?',
mode: 'hybrid',
top_k: 5,
node_ids: ['<string>']
})
};
fetch('https://api.keebai.com/v1/knowledge/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.keebai.com/v1/knowledge/search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => '¿cómo cancelar suscripción?',
'mode' => 'hybrid',
'top_k' => 5,
'node_ids' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.keebai.com/v1/knowledge/search"
payload := strings.NewReader("{\n \"query\": \"¿cómo cancelar suscripción?\",\n \"mode\": \"hybrid\",\n \"top_k\": 5,\n \"node_ids\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.keebai.com/v1/knowledge/search")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"¿cómo cancelar suscripción?\",\n \"mode\": \"hybrid\",\n \"top_k\": 5,\n \"node_ids\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.keebai.com/v1/knowledge/search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"¿cómo cancelar suscripción?\",\n \"mode\": \"hybrid\",\n \"top_k\": 5,\n \"node_ids\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"results": [
{
"node_id": "<string>",
"score": 123,
"title": "<string>",
"snippet": "<string>"
}
]
}Runs a query over the indexed chunks of the knowledge base. Supports three search modes — pick the one that best fits the user’s query:
Results are grouped by
| Mode | When to use it | How it works internally |
|---|---|---|
full | Exact terms, keywords, numbers, IDs. | MongoDB text index over page_content with Spanish stemming. |
vector | Natural language questions, synonyms, paraphrasing. | MongoDB Atlas Vector Search with text-embedding-3-small embeddings. |
hybrid | Sensible default when you don’t know what kind of query is coming. | Runs both in parallel, normalizes scores, and combines them with a 0.6 vector / 0.4 full-text weight. |
node_id (the same document appears only once even if several chunks match) and sorted by descending score.
Endpoint
POST https://api.keebai.com/v1/knowledge/search
Required scope
knowledge:query
Headers
| Header | Required | Value |
|---|---|---|
Authorization | Yes | Bearer kbai_pk_<token> |
Content-Type | Yes | application/json |
Body
| Field | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Search text. |
mode | string | Yes | full, vector, or hybrid. |
top_k | number | No | Max number of results, between 1 and 25. Default 5. |
node_ids | string[] | No | Restrict the search to these node_id values (folders or documents). Useful to scope to a domain within the tree. Max 100 ids. |
Example request
curl -X POST https://api.keebai.com/v1/knowledge/search \
-H "Authorization: Bearer kbai_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"query": "¿cómo cancelar mi suscripción?",
"mode": "hybrid",
"top_k": 3
}'
const resp = await fetch("https://api.keebai.com/v1/knowledge/search", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KEEBAI_API_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query: "¿cómo cancelar mi suscripción?",
mode: "hybrid",
top_k: 3,
}),
});
const { results } = await resp.json();
import os, requests
resp = requests.post(
"https://api.keebai.com/v1/knowledge/search",
headers={
"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}",
"Content-Type": "application/json",
},
json={
"query": "¿cómo cancelar mi suscripción?",
"mode": "hybrid",
"top_k": 3,
},
timeout=15,
)
resp.raise_for_status()
results = resp.json()["results"]
Response
200 OK
{
"mode": "hybrid",
"results": [
{
"node_id": "65f3a1b2c3d4e5f6a7b8c9d3",
"title": "Política de devolución",
"snippet": "Las devoluciones se aceptan dentro de los 10 días posteriores a la compra...",
"score": 0.873,
"source": "vector"
},
{
"node_id": "65f3a1b2c3d4e5f6a7b8c9d4",
"title": "Cancelación de suscripciones",
"snippet": "Para cancelar tu suscripción, ingresá a Mi cuenta > Suscripciones...",
"score": 0.612,
"source": "full"
}
]
}
| Field | Type | Description |
|---|---|---|
mode | string | Mode applied (same as in the request). |
results[].node_id | string | ObjectId of the document in the knowledge base. Useful for cross-referencing with GET /v1/knowledge/tree. |
results[].title | string | Document title (no full content). |
results[].snippet | string | Fragment of the highest-scoring chunk, truncated to ~320 characters. |
results[].score | number | Normalized score. The scale depends on the mode: in vector and hybrid it’s in [0,1]; in full it’s the raw Mongo textScore. Only comparable between items in the same response. |
results[].source | string | vector or full, depending on which engine produced the top-scoring match (in hybrid it indicates which one won after combination). |
400 / 401 / 403 / 429
400 BAD_REQUEST:queryempty,modenot supported, ornode_idswith invalid format.403 FORBIDDENwithcode: INSUFFICIENT_SCOPE: the PAT doesn’t haveknowledge:query.
If you’re going to feed the results to an external LLM (RAG), prefer
hybrid with top_k=5 as a starting point. It’s the setup that best balances recall (vector) with precision on exact terms (full-text).Authorizations
Personal Access Token con prefijo kbai_pk_. Generar desde el portal con permiso developer.manage_tokens.
Body
application/json
Texto de búsqueda.
Example:
"¿cómo cancelar suscripción?"
Modo de búsqueda: full (full-text), vector (semántica) o hybrid (combinación con re-ranking).
Available options:
full, hybrid, vector Example:
"hybrid"
Cantidad máxima de resultados (1-25).
Example:
5
Limita la búsqueda a estos node ids (carpetas o documentos).
Was this page helpful?
⌘I