Quickstart
Configure Turbopuffer, then upload and search your first document with bigRAG.
Follow these steps to go from zero to Turbopuffer-backed search over your documents.
Start bigRAG
docker compose up -dWait for all services to be healthy, then verify:
curl http://localhost:4000/healthCreate the first admin
A fresh install has no users. Create the first admin — this endpoint is only available while needs_setup: true.
export BASE="http://localhost:4000"
curl -X POST $BASE/v1/auth/setup \
-H "Content-Type: application/json" \
-d '{
"email": "admin@example.com",
"password": "a-strong-password",
"display_name": "Admin"
}' \
-c cookies.txtThe response sets a bigrag_session cookie. The admin UI exposes the same flow at http://localhost:3000/setup, then redirects to /onboarding where you create one verified embedding preset and use Save and Finish on the Turbopuffer step before collection work.
Complete provider onboarding
In the admin UI, finish /onboarding by adding one embedding preset and saving Turbopuffer connection details. A successful Turbopuffer save sends you to /overview.
You can skip Turbopuffer during onboarding for a read-only tour, but collections cannot ingest or query until the backend has a working Turbopuffer connection.
Mint an API key
For SDKs, CI jobs, and backend services, mint a long-lived API key. The plaintext key is returned once:
curl -X POST $BASE/v1/admin/api-keys \
-b cookies.txt \
-H "Content-Type: application/json" \
-d '{"name": "quickstart"}' \
| tee /tmp/api-key.json
export BIGRAG_API_KEY=$(jq -r .key /tmp/api-key.json)All further examples use $BIGRAG_API_KEY as a bearer token. See Authentication for scopes.
Create a collection
A collection groups documents that share the same embedding configuration and Turbopuffer namespace.
curl -X POST $BASE/v1/collections \
-H "Authorization: Bearer $BIGRAG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "knowledge_base",
"description": "Company knowledge base",
"embedding_provider": "openai",
"embedding_model": "text-embedding-3-small",
"embedding_api_key": "'"$OPENAI_API_KEY"'",
"chunk_size": 512,
"chunk_overlap": 50
}'import { BigRAG } from "@bigrag/client";
const client = new BigRAG({
apiKey: process.env.BIGRAG_API_KEY!,
baseUrl: "http://localhost:4000",
});
const collection = await client.collections.create({
name: "knowledge_base",
description: "Company knowledge base",
embedding_provider: "openai",
embedding_model: "text-embedding-3-small",
embedding_api_key: process.env.OPENAI_API_KEY,
chunk_size: 512,
chunk_overlap: 50,
});No managed embedding key handy? Use embedding_provider: "openai_compatible" with embedding_base_url pointing at Ollama, vLLM, TEI, or any OpenAI-compatible endpoint. For local gateways without auth, set embedding_api_key to any non-empty placeholder. See Embeddings.
Upload a document
curl -X POST $BASE/v1/collections/knowledge_base/documents \
-H "Authorization: Bearer $BIGRAG_API_KEY" \
-F "file=@handbook.pdf" \
-F 'metadata={"department": "engineering"}' \
| tee /tmp/document.json
export DOC_ID=$(jq -r .id /tmp/document.json)const doc = await client.documents.upload(
"knowledge_base",
new File([buffer], "handbook.pdf"),
{ department: "engineering" }
);The document starts as pending and transitions to processing then ready.
Watch ingestion status
while true; do
doc=$(curl -s "$BASE/v1/collections/knowledge_base/documents/$DOC_ID" \
-H "Authorization: Bearer $BIGRAG_API_KEY")
status=$(jq -r '.status' <<< "$doc")
jq -r '.progress.message // .status' <<< "$doc"
[[ "$status" == "ready" || "$status" == "failed" ]] && break
sleep 2
donelet current = doc;
while (current.status === "pending" || current.status === "processing") {
await new Promise((resolve) => setTimeout(resolve, 2000));
current = await client.documents.get("knowledge_base", doc.id);
console.log(current.progress?.message ?? current.status);
}Query the collection
Once documents are ready, you can query Turbopuffer-backed semantic search:
curl -X POST $BASE/v1/collections/knowledge_base/query \
-H "Authorization: Bearer $BIGRAG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What is the PTO policy?",
"top_k": 5
}'const { results, timings } = await client.queries.query("knowledge_base", {
query: "What is the PTO policy?",
top_k: 5,
});
for (const result of results) {
console.log(`[${result.score.toFixed(3)}] ${result.text}`);
}
console.log(`embed=${timings.embed_ms}ms search=${timings.search_ms}ms total=${timings.total_ms}ms`);Next Steps
- Open the admin UI at
http://localhost:3000to review collections, documents, and query analytics. - Learn about Collections and per-collection chunking, reranking, metadata schemas, and tenant-aware filtering.
- Explore Search modes backed by Turbopuffer — semantic, keyword, and hybrid.
- Set up Webhooks for collection and connector sync notifications.
- Read the full API Reference.