documentation

API Reference

Add intelligent search to your application in minutes. Upload data sources, and let RenBase reason over them to deliver precise, cited answers.

getting started

Quick start

Four steps to go from zero to a working search endpoint.

1
Create a base
A base is a container for related data sources. Create one with a name.
2
Upload your data
Send files via multipart upload or connect an integration. RenBase processes everything automatically.
3
Wait for processing
Poll the job status endpoint until the status is completed.
4
Search
Call POST /ask with your query and base_id. Get a direct answer with citations.

security

Authentication

All requests require a Bearer token in the Authorization header.

Authorization: Bearer YOUR_API_KEY

API keys are created from the RenBase Dashboard. Each key is a 64-character string tied to your organization. It is shown only once at creation time.

overview

Core concepts

ConceptDescription
Organization Your account. All bases, files, and usage are scoped to it.
Base A knowledge base, a container for related data sources. You can have multiple.
File A document uploaded to a base. RenBase chunks, embeds, and indexes it automatically.
Search A query against a base. RenBase retrieves evidence and synthesizes an answer with citations.
Filters Key-value metadata attached to files at ingestion. Use them to narrow search scope.
Security Access-control metadata. Restrict which data sources a query can access.

search

POST /ask

Ask a question against a knowledge base. RenBase retrieves the most relevant evidence and synthesizes an answer with citations.

Request body

ParameterTypeRequiredDescription
query string Yes The question to answer. 3 to 2,000 characters.
base_id string (UUID) Yes The knowledge base to search.
max_sources integer No Number of source citations to return. Range: 1-20. Default: 5.
filters object No Key-value pairs to filter data sources by metadata.
security object No Access-control filters. Values can be a string or array.
stream boolean No Enable Server-Sent Events streaming. Default: false.
include_suggestions boolean No Include suggested follow-up queries. Default: true.

Example request

curl -X POST https://api.renbase.com/api/v1/ask \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "What is the notice period for contract termination?",
    "base_id": "550e8400-e29b-41d4-a716-446655440000"
  }'
import requests

headers = {"Authorization": "Bearer YOUR_API_KEY"}

result = requests.post(
    "https://api.renbase.com/api/v1/ask",
    headers=headers,
    json={
        "query": "What is the notice period for contract termination?",
        "base_id": "550e8400-e29b-41d4-a716-446655440000",
    }
).json()

print(result["answer"])
for cite in result["citations"]:
    print(f"  - {cite['source']}: {cite['text'][:80]} ...")
const result = await fetch("https://api.renbase.com/api/v1/ask", {
  method: "POST",
  headers: {
    Authorization: "Bearer YOUR_API_KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    query: "What is the notice period for contract termination?",
    base_id: "550e8400-e29b-41d4-a716-446655440000",
  }),
}).then((r) => r.json());

console.log(result.answer);
result.citations.forEach((c) =>
  console.log(`  - ${c.source}: ${c.text}`)
);

Response

200 OK
{
  "answer": "The contract stipulates a 30-day notice period for termination.",
  "confidence": 0.92,
  "citations": [
    {
      "text": "Either party may terminate this agreement with thirty (30) calendar days written notice.",
      "source": "service_agreement_2024.pdf",
      "chunk_id": "c7f3e2a1",
      "relevance_score": 0.95
    }
  ],
  "suggested_queries": [
    "What are the penalty clauses for early termination?"
  ],
  "latency_ms": 2340
}
FieldTypeDescription
answer string The synthesized answer based on your data sources.
confidence float Confidence score from 0.0 to 1.0.
citations array Source evidence used to generate the answer.
citations[].text string The relevant text excerpt from the source.
citations[].source string Filename of the source document.
citations[].chunk_id string Internal chunk identifier.
citations[].relevance_score float How relevant this citation is to the query (0.0-1.0).
suggested_queries array Follow-up questions the user might want to ask.
latency_ms integer Total processing time in milliseconds.

Streaming (SSE)

Set "stream": true to receive Server-Sent Events. The endpoint emits chunk, citations, and done events in sequence.

ingestion

POST /ingest

Upload one or more files to a knowledge base. RenBase extracts text, chunks semantically, generates embeddings, and builds a knowledge graph.

.pdf .docx .pptx .txt .md

Form fields (multipart/form-data)

FieldTypeRequiredDescription
base_id string (UUID) Yes Target knowledge base.
files file(s) Yes 1 to 20 files per request. Max 50 MB each.
force boolean No Re-ingest even if already uploaded (matched by hash). Default: false.
metadata string (JSON) No Attach filters and security metadata to the uploaded files.

Example request

curl -X POST https://api.renbase.com/api/v1/ingest \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "base_id=550e8400-e29b-41d4-a716-446655440000" \
  -F "files=@contract_2024.pdf" \
  -F "files=@amendment_q3.docx" \
  -F 'metadata={"filters":{"department":"legal","year":"2024"}}'
import requests

with open("contract_2024.pdf", "rb") as f:
    result = requests.post(
        "https://api.renbase.com/api/v1/ingest",
        headers={"Authorization": "Bearer YOUR_API_KEY"},
        data={"base_id": "550e8400-e29b-41d4-a716-446655440000"},
        files={"files": ("contract_2024.pdf", f, "application/pdf")}
    ).json()

job_id = result["results"][0]["job_id"]
print(f"Queued: {job_id}")
const form = new FormData();
form.append("base_id", "550e8400-e29b-41d4-a716-446655440000");
form.append("files", new Blob([fileBuffer]), "contract_2024.pdf");

const result = await fetch("https://api.renbase.com/api/v1/ingest", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
  body: form,
}).then((r) => r.json());

const jobId = result.results[0].job_id;

Response

{
  "results": [
    { "status": "queued",  "job_id": "7c9e6679-...", "file_id": "6ba7b810-...", "name": "contract_2024.pdf" },
    { "status": "exists",  "file_id": "6ba7b810-...", "name": "amendment_q3.docx" }
  ]
}
StatusMeaning
queued File accepted and queued for processing. Use job_id to poll status.
exists File already indexed (same SHA-256 hash). Use force: true to re-ingest.

ingestion

GET /ingest/{job_id}/status

Check the processing status of an uploaded file.

curl https://api.renbase.com/api/v1/ingest/JOB_ID/status \
  -H "Authorization: Bearer YOUR_API_KEY"
StatusDescription
queued Waiting to be processed.
processing Currently being chunked, embedded, and indexed.
completed Ready to search. num_chunks shows how many chunks were created.
failed Processing failed. Check the error field.

bases

POST /bases

Create a new knowledge base. Returns the base object with its id to use in subsequent requests.

curl -X POST https://api.renbase.com/api/v1/bases \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "Product Documentation"}'
201 Created
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "org_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
  "name": "Product Documentation",
  "created_at": "2026-03-18T10:00:00Z",
  "updated_at": "2026-03-18T10:00:00Z"
}

files

Files

GET /bases/{base_id}/files

List all files in a knowledge base.

curl https://api.renbase.com/api/v1/bases/BASE_ID/files \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "files": [
    {
      "id": "6ba7b810-...",
      "name": "contract_2024.pdf",
      "status": "indexed",
      "mime_type": "application/pdf",
      "size": 2048576,
      "created_at": "2026-03-18T10:00:00Z"
    }
  ]
}
GET /bases/{base_id}/files/{file_id}

Get metadata for a specific file.

curl https://api.renbase.com/api/v1/bases/BASE_ID/files/FILE_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "id": "6ba7b810-...",
  "name": "contract_2024.pdf",
  "status": "indexed",
  "mime_type": "application/pdf",
  "size": 2048576,
  "connector_id": null
}
DELETE /bases/{base_id}/files/{file_id}

Delete a file and all its indexed data (vectors, graph nodes, storage).

curl -X DELETE https://api.renbase.com/api/v1/bases/BASE_ID/files/FILE_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
{ "deleted": "6ba7b810-9dad-11d1-80b4-00c04fd430c8" }
GET /bases/{base_id}/files/{file_id}/download

Get a temporary presigned URL to download the original file. Expires after 1 hour.

curl https://api.renbase.com/api/v1/bases/BASE_ID/files/FILE_ID/download \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "url": "https://storage.renbase.com/...",
  "expires_at": "2026-03-18T11:00:00Z"
}

security & privacy

Security

Privacy is a design constraint, not an afterthought. Every architectural decision ensures your data never leaves your control.

FeatureDescription
Tenant isolation Every organization runs in a fully isolated tenant. No shared infrastructure between customers, no cross-contamination of data.
No model training Your data is never used to train, fine-tune, or improve any AI model. What you upload stays in your knowledge base.
Metadata security Attach security metadata to files at ingestion. Queries are filtered at retrieval time so users only see what they're authorized to access.
Encryption Data encrypted at rest (AES-256) and in transit (TLS 1.2+). API keys are hashed and never stored in plain text.
LLM provider choice Bring your own OpenAI, Anthropic, Mistral, or self-hosted model. No hidden calls to third-party APIs.
On-premise deployment Deploy RenBase entirely within your own infrastructure. Docker Compose setup for regulated industries or strict data residency requirements.

Security metadata

Attach security metadata to files during ingestion. When a query includes a security parameter, only files matching those access-control values are searched.

metadata format
{
  "filters": {
    "department": "legal",
    "year": "2024"
  },
  "security": {
    "team": ["legal", "compliance"],
    "clearance": "confidential"
  }
}

Compliance

GDPR Compliant
CCPA Compliant
SOC 2 II In progress
ISO 27001 Roadmap

errors

Errors

All errors return a JSON object with a detail field describing the problem.

{ "detail": "Query must be between 3 and 2000 characters" }
HTTP CodeMeaning
400 Bad request. Invalid parameters or validation error.
401 Unauthorized. Missing or invalid API key.
403 Forbidden. Quota exceeded, or the base does not belong to your organization.
404 Not found. The resource does not exist.
409 Conflict. A base with that name already exists.
413 Payload too large. File exceeds the 50 MB limit.
429 Too many requests. Quota exceeded.
504 Timeout. The search took too long to complete.

limits

Limits

ResourceLimit
Query length 3 - 2,000 characters
Max sources 1 - 20 per query (default: 5)
Files per upload 1 - 20
File size 50 MB per file
Supported formats .pdf .docx .pptx .txt .md
Metadata keys Max 20 per object
Metadata key format Alphanumeric, hyphens, underscores. 1-50 chars.
Metadata value 1 - 200 characters
Download URL expiry 1 hour

code examples

Full end-to-end example

Create a base, upload a file, wait for processing, then search. The complete flow in each language.

# 1. Create a base
curl -X POST https://api.renbase.com/api/v1/bases \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Knowledge Base"}'

# 2. Upload a file (use the id from step 1 as BASE_ID)
curl -X POST https://api.renbase.com/api/v1/ingest \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "base_id=BASE_ID" \
  -F "files=@document.pdf"

# 3. Poll until completed (use job_id from step 2)
curl https://api.renbase.com/api/v1/ingest/JOB_ID/status \
  -H "Authorization: Bearer YOUR_API_KEY"

# 4. Search
curl -X POST https://api.renbase.com/api/v1/ask \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "What is the cancellation policy?", "base_id": "BASE_ID"}'
import requests, time

API_KEY = "your_api_key"
BASE_URL = "https://api.renbase.com/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# 1. Create a base
base = requests.post(
    f"{BASE_URL}/bases", headers=headers,
    json={"name": "My Knowledge Base"}
).json()

# 2. Upload a file
with open("document.pdf", "rb") as f:
    upload = requests.post(
        f"{BASE_URL}/ingest", headers=headers,
        data={"base_id": base["id"]},
        files={"files": ("document.pdf", f, "application/pdf")}
    ).json()

job_id = upload["results"][0]["job_id"]

# 3. Poll until ready
while True:
    status = requests.get(
        f"{BASE_URL}/ingest/{job_id}/status", headers=headers
    ).json()
    if status["status"] in ("completed", "failed"):
        break
    time.sleep(2)

# 4. Search
answer = requests.post(
    f"{BASE_URL}/ask", headers=headers,
    json={"query": "What is the cancellation policy?", "base_id": base["id"]}
).json()

print(answer["answer"])
for cite in answer["citations"]:
    print(f"  - {cite['source']}: {cite['text'][:80]} ...")
const API_KEY = "your_api_key";
const BASE_URL = "https://api.renbase.com/api/v1";
const headers = { Authorization: `Bearer ${API_KEY}` };

// 1. Create a base
const base = await fetch(`${BASE_URL}/bases`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ name: "My Knowledge Base" }),
}).then((r) => r.json());

// 2. Upload a file
const form = new FormData();
form.append("base_id", base.id);
form.append("files", new Blob([fileBuffer]), "document.pdf");

const upload = await fetch(`${BASE_URL}/ingest`, {
  method: "POST", headers, body: form,
}).then((r) => r.json());

const jobId = upload.results[0].job_id;

// 3. Poll until ready
let status;
do {
  await new Promise((r) => setTimeout(r, 2000));
  status = await fetch(`${BASE_URL}/ingest/${jobId}/status`, { headers }).then((r) => r.json());
} while (![ "completed", "failed" ].includes(status.status));

// 4. Search
const result = await fetch(`${BASE_URL}/ask`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ query: "What is the cancellation policy?", base_id: base.id }),
}).then((r) => r.json());

console.log(result.answer);
result.citations.forEach((c) => console.log(`  - ${c.source}: ${c.text}`));