Developer guide

Tour RAG API documentation

Multi-tenant RAG chatbot backend for East African tourism companies. One deployment, many operators — each with an API key, system prompt, and knowledge base. Designed so other products and websites can consume the API as a demo / MVP.

Base URL (production): https://tourragapi.vercel.app/api/v1
Interactive demo: /demo · Website snippet: /integrate

Quick start

Same flow as most payment / platform docs: create credentials → push data → call the action endpoint.

  1. Create a tenant with admin key → receive api_key once.
  2. Ingest chunks (tour packages, FAQs, routes).
  3. Chat with the tenant x-api-key.
# 1) Create tenant curl -s -X POST https://tourragapi.vercel.app/api/v1/tenants \ -H "Content-Type: application/json" \ -H "x-admin-key: $ADMIN_API_KEY" \ -d '{ "name": "Serengeti Trails", "system_prompt": "You are a helpful safari booking assistant. Be concise." }' # 2) Ingest knowledge curl -s -X POST https://tourragapi.vercel.app/api/v1/ingest \ -H "Content-Type: application/json" \ -H "x-admin-key: $ADMIN_API_KEY" \ -d '{ "tenant_id": "TENANT_UUID", "chunks": [ { "content": "3-day Serengeti safari from Arusha. From $890 pp.", "metadata": { "type": "package", "days": 3 } } ] }' # 3) Chat as the tenant curl -s -X POST https://tourragapi.vercel.app/api/v1/chat \ -H "Content-Type: application/json" \ -H "x-api-key: $TENANT_API_KEY" \ -d '{ "message": "How much is a 3-day Serengeti safari?", "session_id": "web-session-001" }'

Authentication

HeaderUsed byNotes
x-admin-keyTenants, IngestServer secret from env ADMIN_API_KEY
x-api-keyChatPer-tenant key returned on create (shown once)
Content-TypeAll POSTapplication/json

Errors

All failures share one shape (easy for clients to parse):

{ "error": "Human-readable message", "code": "MACHINE_CODE" }
HTTPcodeWhen
400VALIDATION_ERROR, INVALID_JSONMissing fields / bad body
401UNAUTHORIZEDBad or missing API / admin key
404NOT_FOUNDUnknown tenant
429RATE_LIMITEDChat window exceeded (Retry-After header)
500INTERNAL_ERROR, EMBEDDING_ERROR, …Upstream or server failure

Read /api/v1/health

GET/api/v1/health

Auth: None

Liveness probe. Use for uptime checks and load balancers.

curl -s https://tourragapi.vercel.app/api/v1/health # {"status":"ok"}

Write /api/v1/tenants

POST/api/v1/tenants

Auth: x-admin-key

Create a tenant (tourism company). The api_key is returned only in this response — store it securely.

Request body

{ "name": "Serengeti Trails", "system_prompt": "You are a helpful safari booking assistant..." }

Response 201

{ "id": "uuid", "name": "Serengeti Trails", "system_prompt": "...", "api_key": "hex-secret", "created_at": "..." }

Read /api/v1/tenants/:id

GET/api/v1/tenants/:id

Auth: x-admin-key

Fetch tenant metadata. Never returns api_key after creation.

curl -s https://tourragapi.vercel.app/api/v1/tenants/TENANT_UUID \ -H "x-admin-key: $ADMIN_API_KEY"

Write /api/v1/ingest

POST/api/v1/ingest

Auth: x-admin-key

Push pre-chunked knowledge base text. The API embeds each chunk and stores vectors in Postgres (pgvector). It does not scrape or split documents for you.

Request body

{ "tenant_id": "uuid", "chunks": [ { "content": "string (max 8000 chars)", "metadata": { "any": "json object" } } ] }

Response 201

{ "inserted": 2 }

Limits: max 50 chunks per request; each chunk max 8000 characters.

Write /api/v1/chat

POST/api/v1/chat

Auth: x-api-key (tenant)

RAG chat: embed message → retrieve top documents for that tenant → generate answer → save history.

Request body

{ "message": "How much is a 3-day Serengeti safari?", "session_id": "web-session-001" }

Response 200

{ "answer": "A 3-day Serengeti safari costs $890 per person.", "sources": [ { "id": "uuid", "content": "...", "metadata": {}, "similarity": 0.76 } ], "session_id": "web-session-001" }

Limits & behaviour

Ingest capacity (tokens / full website)

LimitValueNotes
Chunk size8,000 chars~1.5–2k tokens each (rule of thumb)
Chunks / request50Repeat calls to add more
Max per request~400k chars50 × 8,000 — still constrained by function timeout
DB hard capNone in app codePostgres/Supabase plan + embedding cost
~1,000 web pagesPossible after chunkingScrape → clean → chunk → many ingest batches. Prefer FAQs & packages first for sales demos.

Vectors are not “tokens stored forever” — each chunk is one 768-dim embedding. Chat only retrieves the top 4 nearest chunks, so quality of chunks matters more than raw page count.

Next steps

Talk to the builder

Need this on your tourism website?

Call or message Cleven for demos, custom knowledge bases, multi-tenant setup, or embedding the chat widget on your operator site.