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 stg · https://api.stg.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 stg. Example requests below use https://api.stg.oprag.ai.

Authentication

Dashboard routes

All routes under /v1/* except POST /v1/chat and GET /v1/widget/{id}/config require a Cognito JWT from the oprag dashboard. This includes workspace summaries (/v1/dashboard/*, /v1/activity, /v1/analytics/*, /v1/billing/*, /v1/conversations/*, /v1/keys), companies, and projects:

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 Read projects and workspace summaries, upload/sync/delete documents, dashboard test chat, conversation inbox, test runs
admin Everything members can do, plus project settings, deploy, API keys, team management, widget config updates, 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",
  "conversationId": "optional-conversation-id",
  "visitorId": "optional-visitor-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.
conversationId string No Resume a persisted conversation from a prior response.
visitorId string No Stable visitor identifier for public embed analytics and conversation grouping.

Response

{
  "answer": "You can cancel any time from Account → Billing...",
  "sessionId": "sess_abc123",
  "conversationId": "conv_abc123",
  "visitorId": "visitor_abc123",
  "sources": [
    {
      "title": "a1b2c3d4-billing-faq.pdf",
      "excerpt": "Refunds are available within 30 days of purchase...",
      "pageNumber": 2
    }
  ]
}
FieldTypeDescription
answer string Generated answer grounded in your documents.
sessionId string Session identifier for follow-up questions.
conversationId string Persisted conversation id when chat history is stored.
visitorId string Echoed visitor id when provided in the request.
sources object[] Cited sources with optional title, excerpt, and pageNumber. Omitted when no citations are returned.

Example

curl -X POST 'https://api.stg.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","conversationId":"optional-conversation-id","visitorId":"optional-visitor-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 — create an additional live or test key
  • POST /v1/projects/{id}/keys/rotate — rotate live key (requires an existing active key)
  • DELETE /v1/projects/{id}/keys/{keyId} — revoke a key
  • GET /v1/projects/{id}/integration — endpoint URL and curl example
  • GET /v1/keys — list all keys across projects (workspace-level)

API routes

Full route reference. Dashboard routes require Authorization: Bearer <Cognito JWT>; POST /v1/chat, GET /health, GET /config, GET /widget.js, and GET /v1/widget/{id}/config 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
GET /config Public Cognito pool/client IDs and API URL (MCP and tooling)
GET /widget.js Public Embed widget bundle (301 to CDN when configured)
GET /v1/widget/{id}/config Public Widget display config (project must be live or indexing, widget enabled)
POST /v1/chat API key Public project chatbot — question max length enforced per project (default 1 000 chars)
GET /v1/dashboard/summary JWT · member Dashboard KPIs and project rollups
GET /v1/activity JWT · member Recent workspace activity feed
GET /v1/analytics/summary JWT · member Usage analytics (optional projectId, from, to query params)
GET /v1/billing/summary JWT · member Plan limits and usage
GET /v1/conversations JWT · member Workspace conversation inbox
GET /v1/conversations/{conversationId} JWT · member Workspace conversation detail and messages
PATCH /v1/conversations/{conversationId} JWT · member Update review status, rating, and notes
GET /v1/keys JWT · member All API keys across projects
POST /v1/companies JWT Create company (signup)
GET /v1/companies/me JWT · member Current company
PATCH /v1/companies/me JWT · admin Update company name
GET /v1/companies/users JWT · member List team members
POST /v1/companies/users/invite JWT · admin Invite user
POST /v1/companies/users/{userId}/resend-invite JWT · admin Resend invite email
PATCH /v1/companies/users/{userId} JWT · admin Change member role
DELETE /v1/companies/users/{userId} JWT · admin Remove member
GET /v1/companies/settings JWT · member Workspace defaults (origins, prompts, retention)
PATCH /v1/companies/settings JWT · admin Update workspace defaults
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
GET /v1/projects/{id}/overview JWT · member Project dashboard summary and setup progress
GET /v1/projects/{id}/deploy-readiness JWT · member Pre-deploy checklist and blockers
GET /v1/projects/{id}/widget-config JWT · member Widget settings (dashboard)
PATCH /v1/projects/{id}/widget-config JWT · admin Update widget display name, welcome message, and theme
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}/documents/upload-url JWT · member Presigned upload URL (single file)
POST /v1/projects/{id}/documents/bulk-upload-url JWT · member Presigned upload URLs (batch)
POST /v1/projects/{id}/documents/{docId}/confirm JWT · member Confirm S3 upload
POST /v1/projects/{id}/documents/{docId}/replace-url JWT · member Replace document (versioned)
GET /v1/projects/{id}/documents/{docId}/versions JWT · member List document version history
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}/conversations JWT · member List project conversations
GET /v1/projects/{id}/conversations/{conversationId} JWT · member Project conversation detail and messages
POST /v1/projects/{id}/deploy JWT · admin Deploy, auto-ingest docs, issue API key
GET /v1/projects/{id}/integration JWT · admin Integration info (endpoint, curl)
GET /v1/projects/{id}/keys JWT · admin List API keys (prefix only)
POST /v1/projects/{id}/keys JWT · admin Create additional API key (live or test environment)
POST /v1/projects/{id}/keys/rotate JWT · admin Rotate live API key
DELETE /v1/projects/{id}/keys/{keyId} JWT · admin Revoke key

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 (single file) or POST .../documents/bulk-upload-url (batch)
  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).

To replace an existing file, use POST .../documents/{docId}/replace-url, then confirm and sync as usual. Version history is available at GET .../documents/{docId}/versions.

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.stg.oprag.ai/health'

Response

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

Ready to ship?

Get started free