API Reference

Build with the oprag API

Ship a document-backed chatbot with one API key. Use the public chat endpoint from your app or backend, and manage projects, documents, and keys from the dashboard API.

REST / JSON AWS Bedrock RAG prod · https://api.oprag.ai

Overview

The oprag API powers document-backed AI chatbots for your product. Upload knowledge in the dashboard, test responses with cited sources, then deploy to receive an API key for production use.

There are two surfaces: a public chat API authenticated with project API keys (sk_live_...), and a dashboard API authenticated with Cognito JWTs for managing companies, projects, documents, deployments, and keys.

Retrieval is multi-tenant: each project's documents are isolated by tenant_id and project_id in the shared Bedrock knowledge base per environment.

Base URLs

All requests use HTTPS. Pick the host for your environment:

Development https://api.dev.oprag.ai
Staging https://api.stg.oprag.ai
Production https://api.oprag.ai

This page is deployed to prod. Example requests below use https://api.oprag.ai.

Authentication

Dashboard routes

Routes under /v1/companies/* and /v1/projects/* require a Cognito JWT from the oprag dashboard:

Authorization: Bearer <Cognito JWT>

Users must have custom:tenant_id (your companyId) set after company creation. Only owners can invite another user with role: "owner". Inviting a user who already belongs to another company returns 409 Conflict.

Public chat

POST /v1/chat accepts your project API key in either header:

X-Oprag-Key: sk_live_...
# or
Authorization: Bearer sk_live_...

API keys are issued when you deploy a project from the dashboard.

Roles

Dashboard routes enforce company membership roles. Public POST /v1/chat uses API keys only.

RoleAccess
member Projects (read/update), documents (upload, sync, delete), dashboard test chat
admin Everything members can do, plus deploy, API keys, integration info, archive project
owner Same as admin; only owners can invite another user with role: "owner"

Public Chat API

Ask questions against your project's indexed documents. Answers include cited source filenames.

POST /v1/chat

Auth: X-Oprag-Key or Authorization: Bearer sk_live_...

Request body

{
  "question": "What is your refund policy?",
  "sessionId": "optional-session-id"
}
FieldTypeRequiredDescription
question string Yes The user's question. Must be non-empty after trimming and within the project question max length (default 1 000 characters).
sessionId string No Pass a prior sessionId to continue a multi-turn conversation.

Response

{
  "answer": "You can cancel any time from Account → Billing...",
  "sessionId": "sess_abc123",
  "citations": [],
  "sources": ["a1b2c3d4-billing-faq.pdf", "e5f6g7h8-terms.md"]
}
FieldTypeDescription
answer string Generated answer grounded in your documents.
sessionId string Session identifier for follow-up questions.
citations object[] Raw Bedrock citation objects. Most integrations only need sources.
sources string[] S3 object basenames cited in the answer (format: {uuid}-{originalFilename}).

Example

curl -X POST 'https://api.oprag.ai/v1/chat' \
  -H 'X-Oprag-Key: sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"question":"What is your refund policy?","sessionId":"optional-session-id"}'

CORS & allowed origins

API Gateway allows browser CORS from any origin at the edge. Lambda enforces per-project allowedOrigins on POST /v1/chat:

  • Empty list — server-to-server calls without an Origin header are allowed; browser embeds are denied (403).
  • Non-empty list — browser requests must send an Origin that exactly matches an entry (scheme and host; trailing slashes matter). Server-to-server calls without Origin are still allowed.

Set allowedOrigins on project create or update before embedding the chat widget on customer sites.

Getting an API key

  1. Upload documents to your project in the dashboard and sync (or deploy — deploy also ingests pending uploads).
  2. Deploy via POST /v1/projects/{id}/deploy (admin role). Issues a new sk_live_* key, revokes prior active keys, and auto-ingests uploaded documents.
  3. Use the key in your integration. Keys work as soon as deploy completes — you do not need to wait for live status if documents are still indexing.

Manage keys from the dashboard or API:

  • GET /v1/projects/{id}/keys — list keys (prefix only, never the full secret)
  • POST /v1/projects/{id}/keys/rotate — rotate (requires an existing active key)
  • DELETE /v1/projects/{id}/keys/{keyId} — revoke a key
  • GET /v1/projects/{id}/integration — endpoint URL and curl example

API routes

Full route reference. Dashboard routes require Authorization: Bearer <Cognito JWT>; POST /v1/chat and GET /health are public. RAG-dependent routes return 503 when the knowledge base is not enabled in an environment. Route list is defined in site/src/data/api-docs.ts — keep in sync with backend/src/index.ts.

Method Path Auth Description
GET /health Public Liveness check
POST /v1/chat API key Public project chatbot — question max length enforced per project (default 1 000 chars)
POST /v1/companies JWT Create company (signup)
GET /v1/companies/me JWT Current company
GET /v1/companies/users JWT List team members
POST /v1/companies/users/invite JWT Invite user
POST /v1/projects JWT · member Create project (settings and allowed origins require admin)
GET /v1/projects JWT · member List projects
GET /v1/projects/{id} JWT · member Get project
PATCH /v1/projects/{id} JWT · admin Update project name, description, CORS origins, system prompt, model, question cap, retrieval and indexing settings
DELETE /v1/projects/{id} JWT · admin Archive project
POST /v1/projects/{id}/documents/upload-url JWT · member Presigned upload URLs
POST /v1/projects/{id}/documents/{docId}/confirm JWT · member Confirm S3 upload
GET /v1/projects/{id}/documents/{docId}/preview-url JWT · member Presigned preview URL (5 min TTL, works without RAG)
GET /v1/projects/{id}/documents JWT · member List documents
DELETE /v1/projects/{id}/documents/{docId} JWT · member Delete document (S3 + KB)
POST /v1/projects/{id}/documents/sync JWT · member Ingest uploaded documents (202 Accepted)
POST /v1/projects/{id}/chat JWT · member Dashboard test chat — question max length enforced per project (default 1 000 chars)
GET /v1/projects/{id}/test-prompts JWT · member List suggested and saved prompt tests
POST /v1/projects/{id}/test-prompts JWT · admin Create saved prompt test; prompt max length enforced per project
POST /v1/projects/{id}/test-runs JWT · member Run saved or ad hoc prompt tests using project chat settings
POST /v1/projects/{id}/deploy JWT · admin Deploy, auto-ingest docs, issue API key
GET /v1/projects/{id}/keys JWT · admin List API keys (prefix only)
POST /v1/projects/{id}/keys/rotate JWT · admin Rotate API key
DELETE /v1/projects/{id}/keys/{keyId} JWT · admin Revoke key
GET /v1/projects/{id}/integration JWT · admin Integration info (endpoint, curl)

Document upload flow

Dashboard routes for ingesting files into your project knowledge base (member role):

  1. Request upload URLsPOST /v1/projects/{id}/documents/upload-url
  2. Upload to S3PUT the file to uploadUrl and metadataBody (verbatim JSON string) to metadataUploadUrl (15-minute TTL).
  3. Confirm uploadPOST /v1/projects/{id}/documents/{docId}/confirm — verifies S3 objects, marks uploaded, returns the document record.
  4. Sync to knowledge basePOST /v1/projects/{id}/documents/sync — returns 202 Accepted; ingestion runs asynchronously (wait 1–5 minutes before chatting).

Upload-url request

{
  "filename": "billing-faq.pdf",
  "contentType": "application/pdf"
}
FieldRequiredDescription
filenameYesOriginal filename (used in S3 key suffix)
contentTypeNoDefaults to application/octet-stream

Upload-url response

{
  "documentId": "doc_abc123",
  "uploadUrl": "https://...",
  "metadataUploadUrl": "https://...",
  "metadataBody": "{\"metadataAttributes\":{\"tenant_id\":\"...\",\"project_id\":\"...\"}}",
  "key": "documents/{companyId}/{projectId}/{uuid}-billing-faq.pdf",
  "metadataKey": "documents/.../billing-faq.pdf.metadata.json",
  "bucket": "ashutech-dev-oprag-docs-...",
  "expiresInSeconds": 900,
  "instructions": "1) PUT file to uploadUrl. 2) PUT metadataBody to metadataUploadUrl. 3) POST confirm. 4) POST sync."
}

PUT metadataBody as the raw body to metadataUploadUrl — do not JSON.stringify it again. S3 keys use {uuid}-{filename}.

Sync response (202 Accepted)

{
  "documentCount": 2,
  "statuses": ["STARTING"],
  "companyId": "...",
  "projectId": "...",
  "message": "Project-scoped ingestion started. Wait 1–5 minutes before chatting."
}

documentCount reflects uploaded/indexed documents only — not abandoned presigns. POST .../deploy also confirms pending uploads and ingests documents, so a separate sync before deploy is optional. Searchability may lag a few minutes after sync or deploy.

Error responses

Errors return JSON with an error string and the appropriate HTTP status:

{
  "error": "question is required"
}
StatusMeaningCommon causes
400 Bad Request Invalid JSON; missing question or filename; question exceeds the project max length; no documents ready for sync; deploy before rotate; S3 objects missing on confirm
401 Unauthorized Missing or invalid JWT / API key
403 Forbidden Origin not allowed for public chat; insufficient project role
404 Not Found Project, document, key not found; unknown route (No route for METHOD path)
409 Conflict User already belongs to another company; user already a company member; user already has a company (signup)
502 Bad Gateway Chat request failed upstream (Bedrock or retrieval error)
503 Service Unavailable RAG / knowledge base not enabled in this environment

Health

GET /health

Auth: none (public)

Liveness probe — no authentication required. Use for uptime monitoring and deploy smoke tests.

curl 'https://api.oprag.ai/health'

Response

{
  "status": "ok",
  "service": "oprag-api",
  "timestamp": "2026-06-09T12:00:00.000Z"
}

Ready to ship?

Get started free