Integration API

Every endpoint an integration key, an embed key, or no credential at all can reach — the set you build against.

dev · https://api.dev.oprag.ai

These are the endpoints you can call from your own product. 12 of them take an sk_live_ integration key, an origin-locked embed_live_ key, or no credential at all, and a further 10 belong to Extract. Nothing on this page needs a dashboard login.

Everything your key opens

Grouped below by what each endpoint acts on. Extract has its own section.
EndpointCredentialWhat it does
GET /v1/public/share/{slug}PublicBootstrap the hosted share page for a slug and mint a short-lived chat token.
POST /v1/chatIntegration or embed keyAsk a question against a project's documents and get a grounded answer with citations.
POST /v1/chat/streamIntegration or embed keyThe same question, answered as a Server-Sent Events stream of tokens.
POST /v1/chat/feedbackIntegration keyRecord a visitor's thumbs up or down on an assistant message.
POST /v1/projects/{projectId}/conversations/{conversationId}/escalateIntegration keyHand a public conversation to a human, over a webhook, an email, or both.
POST /v1/projects/{projectId}/leadsIntegration keyRecord a lead captured by the widget's contact form.
POST /v1/projects/{projectId}/ticketsIntegration keyCreate an escalation ticket from a conversation.
GET /widget.jsPublicEmbed widget bundle (301 to CDN when configured)
GET /v1/widget/{projectId}/configPublicPublic display configuration for a project's chat widget.
GET /healthPublicLiveness check
GET /configPublicCognito pool/client IDs, API URL, Hosted UI domain prefix, SPA OAuth callback, and enabled socialProviders (Google, GitHub). Used by the dashboard and MCP clients to bootstrap auth.
GET /dev/infoPublicDev testing credentials, MCP login steps, and the live API route catalog.

Chat

Ask questions against a project's documents, stream answers, and record feedback. The endpoints most integrations start and end with.

GET /v1/public/share/{slug}

Bootstrap the hosted share page for a slug and mint a short-lived chat token.

Auth Public — no credential

Before you call it

  • The project must be live, with shareEnabled and a shareSlug matching this path.
  • accessMode: "public" lets anyone bootstrap. accessMode: "private" first requires a dashboard JWT — Authorization: Bearer, or a Cognito access token — and membership of the project.
  • shareToken is a 15-minute HMAC JWT. Send it to POST /v1/chat as X-Oprag-Share-Token in place of an API key.

Path parameters

Name Type Required Description
slug string Required Public share slug from the project's share settings.

Query parameters

None.Reads the resource named in the path; there is nothing else to select.

Body parameters

None.GET requests carry no body.

Response

200 Success

JSON
{
  "projectId": "proj_abc123",
  "accessMode": "public",
  "displayName": "Support Bot",
  "welcomeMessage": "Hi! Ask me anything about our product.",
  "theme": {
    "primaryColor": "#2563eb",
    "position": "bottom-right",
    "mode": "auto"
  },
  "shareToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "shareTokenExpiresAt": "2026-08-11T16:26:00.000Z"
}

Status codes

Status Meaning
200 Success.
403 The share link is private and the caller is anonymous: { error: "This chat is private", accessMode: "private" }.
404 { error: "Share link not found" } — unknown slug, share turned off, or an archived project.
429 Rate limited. See rate limits.
503 SHARE_TOKEN_SECRET is not configured, so no token can be minted.

curl

Shell
curl -X GET 'https://api.dev.oprag.ai/v1/public/share/{slug}' \
  -H 'X-Oprag-Key: sk_live_...'
POST /v1/chat

Ask a question against a project's documents and get a grounded answer with citations.

Auth Integration keyEmbed keyShare token Embed keys require a browser `Origin`; share tokens use `X-Oprag-Share-Token`

Path parameters

None.

Query parameters

None.Everything it needs is in the request body.

Body parameters

Name Type Required Description
question string Required The visitor's question. Trimmed; an empty question is rejected with 400.
sessionId string Optional Groups turns into one conversation. Send back the value from the previous response to keep multi-turn context.
conversationId string Optional Server-assigned conversation identifier. Echo it back so the conversation stays one thread in the dashboard.
visitorId string Optional Stable identifier for the end user. Ties leads and escalations to the person who asked.

Request

JSON
{
  "question": "What is your refund policy?",
  "sessionId": "sess_abc123",
  "conversationId": "conv_abc123",
  "visitorId": "visitor_abc123"
}

Responses

200 Answer

The usual branch. type is answer and sources carries the passages it was grounded in.

JSON
{
  "type": "answer",
  "answer": "You can cancel any time from Account → Billing. Refunds are available within 30 days of purchase.",
  "sessionId": "sess_abc123",
  "conversationId": "conv_abc123",
  "visitorId": "visitor_abc123",
  "assistantMessageId": "msg_abc123",
  "sources": [
    {
      "documentTitle": "Billing FAQ",
      "excerpt": "Refunds are available within 30 days of purchase...",
      "location": "billing-faq.pdf",
      "pageNumber": 2,
      "score": 0.89
    }
  ],
  "suggestedFollowUps": ["How long do refunds take?", "Can I pause my plan instead?"]
}

200 Lead capture prompt

Returned when smart lead capture is enabled and the documents cannot answer. There is no answer field on this branch — branch on type before reading it.

JSON
{
  "type": "lead_capture_prompt",
  "promptMessage": "I could not find that in the docs. Leave your email and someone will follow up.",
  "fields": ["name", "email"],
  "conversationId": "conv_abc123",
  "visitorId": "visitor_abc123",
  "sessionId": "sess_abc123"
}

200 Test key fixture

What an sk_test_ or embed_test_ key returns. It omits type — a legacy-shaped payload that clients treat as the answer branch.

JSON
{
  "answer": "This is a test response from oprag. Your integration is working correctly. Replace this with a live key to get real answers from your documents.",
  "sources": [],
  "conversationId": "conv_abc123",
  "sessionId": "sess_abc123"
}

Status codes

Status Meaning
200 Success.
400 The request body failed validation.
401 Missing, revoked, or wrong-environment key.
403 Origin or IP not allowed for this project.
429 Rate limited. See rate limits.

curl

Shell
curl -X POST 'https://api.dev.oprag.ai/v1/chat' \
  -H 'X-Oprag-Key: sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"question": "What is your refund policy?","sessionId": "sess_abc123","conversationId": "conv_abc123","visitorId": "visitor_abc123"}'

SDK equivalent `oprag.chat.ask()`

POST /v1/chat/stream

The same question, answered as a Server-Sent Events stream of tokens.

Auth Integration keyEmbed keyShare token Same auth as `POST /v1/chat`

Path parameters

None.

Query parameters

None.Everything it needs is in the request body.

Body parameters

Name Type Required Description
question string Required The visitor's question. Trimmed; an empty question is rejected with 400.
sessionId string Optional Groups turns into one conversation. Send back the value from the previous response to keep multi-turn context.
conversationId string Optional Server-assigned conversation identifier. Echo it back so the conversation stays one thread in the dashboard.
visitorId string Optional Stable identifier for the end user. Ties leads and escalations to the person who asked.

Request

JSON
{
  "question": "What is your refund policy?",
  "sessionId": "sess_abc123",
  "conversationId": "conv_abc123",
  "visitorId": "visitor_abc123"
}

Response

Status codes

Status Meaning
200 Success.
400 The request body failed validation.
401 Missing, revoked, or wrong-environment key.
403 Origin or IP not allowed for this project.
429 Rate limited. See rate limits.

curl

Shell
curl -X POST 'https://api.dev.oprag.ai/v1/chat/stream' \
  -H 'X-Oprag-Key: sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"question": "What is your refund policy?","sessionId": "sess_abc123","conversationId": "conv_abc123","visitorId": "visitor_abc123"}'

SDK equivalent `oprag.chat.stream()`

POST /v1/chat/feedback

Record a visitor's thumbs up or down on an assistant message.

Auth Integration key

Before you call it

  • messageId is the assistantMessageId from the answer being rated.
  • visitorId becomes required once the conversation already has one.
  • Respects the widget's feedbackEnabled setting, which defaults to on, and is rate limited per IP.

Path parameters

None.

Query parameters

None.Everything it needs is in the request body.

Body parameters

Name Type Required Description
conversationId string Required Conversation this relates to.
messageId string Required The assistantMessageId from the answer being rated.
rating "up" | "down" Required up or down.
visitorId string Optional Stable identifier for the end user.

Request

JSON
{
  "conversationId": "conv_xyz789",
  "messageId": "msg_abc123",
  "rating": "up",
  "visitorId": "visitor_001"
}

Response

200 Success

JSON
{
  "ok": true,
  "messageId": "msg_abc123",
  "rating": "up",
  "ratedAt": "2026-08-11T18:00:00.000Z"
}

Status codes

Status Meaning
200 Success.
400 The request body failed validation.
401 Missing, revoked, or wrong-environment key.
403 Origin or IP not allowed for this project.
429 Rate limited. See rate limits.

curl

Shell
curl -X POST 'https://api.dev.oprag.ai/v1/chat/feedback' \
  -H 'X-Oprag-Key: sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"conversationId": "conv_xyz789","messageId": "msg_abc123","rating": "up","visitorId": "visitor_001"}'

Conversations

Read conversation history, review it, export it, and escalate a thread to a human.

POST /v1/projects/{projectId}/conversations/{conversationId}/escalate

Hand a public conversation to a human, over a webhook, an email, or both.

Auth Integration key

Before you call it

  • The project needs escalationWebhookUrl or escalationEmail in its settings; without one there is nowhere to escalate to.
  • On the Growth plan and above the escalation is also stored as a native ticket, and emits ticket.created.
  • When a webhook is configured, oprag POSTs the transcript to it over HTTPS with an X-Oprag-Signature: sha256=… header, including ticketId when one was created.
  • Email escalation needs SES_FROM_EMAIL configured.

Path parameters

Name Type Required Description
projectId string Required Project the request applies to. Must belong to the calling workspace.
conversationId string Required Conversation within the project.

Query parameters

None.Everything it needs is in the request body.

Body parameters

Name Type Required Description
visitorId string Required The visitor asking for a human. Required.
subject string Optional Short summary line.
requesterEmail string Optional Email to reply to.
requesterName string Optional Name of the person asking.
message string Optional Body text.

Request

JSON
{ "visitorId": "visitor_001", "message": "Need billing help" }

Response

200 Success

JSON
{ "escalated": true, "ticketId": "tkt_abc123" }

Status codes

Status Meaning
200 Escalated. The body is { escalated: true, ticketId? }.
400 The request body failed validation.
401 Missing, revoked, or wrong-environment key.
403 Origin or IP not allowed for this project.
404 No such resource in this workspace.
409 This conversation has already been escalated.
429 Rate limited. See rate limits.
500 A webhook URL is configured but its signing secret is missing.

curl

Shell
curl -X POST 'https://api.dev.oprag.ai/v1/projects/{projectId}/conversations/{conversationId}/escalate' \
  -H 'X-Oprag-Key: sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{ "visitorId": "visitor_001", "message": "Need billing help" }'

SDK equivalent `oprag.conversations.escalate()`

Leads & tickets

Capture leads from chat, export them, and manage the tickets escalation creates.

POST /v1/projects/{projectId}/leads

Record a lead captured by the widget's contact form.

Auth Integration key

Before you call it

  • The project needs leadCaptureEnabled, and the body needs visitorId plus at least one of name or email.
  • Built-in lead fields are unlimited on every plan — there is no monthly cap.
  • customFields needs the Growth plan or above with leadFormFields configured on the project.

Path parameters

Name Type Required Description
projectId string Required Project the request applies to. Must belong to the calling workspace.

Query parameters

None.Everything it needs is in the request body.

Body parameters

Name Type Required Description
visitorId string Required Stable identifier for the end user.
name string Optional Display name.
email string Optional Email address.
conversationId string Optional Conversation this relates to.
sourceQuestion string Optional The question that triggered capture, for context in the dashboard.
customFields object Optional Values for any custom lead form fields configured on the project.

Request

JSON
{
  "visitorId": "visitor_001",
  "name": "Jane Doe",
  "email": "jane@example.com",
  "conversationId": "conv_xyz789",
  "customFields": {
    "company_size": "50-200",
    "plan_tier": "Growth"
  }
}

Response

200 Success

JSON
{ "leadId": "lead_abc123" }

Status codes

Status Meaning
201 Created. The body is { leadId }.
400 The request body failed validation.
401 Missing, revoked, or wrong-environment key.
402 customFields were sent on the Free plan.
403 Origin or IP not allowed for this project.
404 No such resource in this workspace.
429 More than 10 submissions from one visitor within an hour.

curl

Shell
curl -X POST 'https://api.dev.oprag.ai/v1/projects/{projectId}/leads' \
  -H 'X-Oprag-Key: sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"visitorId": "visitor_001","name": "Jane Doe","email": "jane@example.com","conversationId": "conv_xyz789","customFields": {"company_size": "50-200","plan_tier": "Growth"}}'

SDK equivalent `oprag.leads.create()`

POST /v1/projects/{projectId}/tickets

Create an escalation ticket from a conversation.

Auth Integration key

Before you call it

  • Delivery is the same as escalate — webhook, email, or both.

Path parameters

Name Type Required Description
projectId string Required Project the request applies to. Must belong to the calling workspace.

Query parameters

None.Everything it needs is in the request body.

Body parameters

Name Type Required Description
conversationId string Required Conversation the ticket is raised from.
visitorId string Optional Stable identifier for the end user.
subject string Optional Short summary line.
requesterEmail string Optional Email to reply to.
requesterName string Optional Name of the person asking.
message string Optional Body text.

Request

JSON
{
  "conversationId": "conv_abc123",
  "visitorId": "visitor_001",
  "subject": "Billing question"
}

Response

200 Success

JSON
{ "ticketId": "tkt_abc123", "escalated": true }

Status codes

Status Meaning
200 Free plan — the escalation was delivered but no ticket is stored: { escalated: true }.
201 Growth and above — a native ticket was stored: { ticketId, escalated: true }.
400 The request body failed validation.
401 Missing, revoked, or wrong-environment key.
403 Origin or IP not allowed for this project.
404 No such resource in this workspace.
429 Rate limited. See rate limits.

curl

Shell
curl -X POST 'https://api.dev.oprag.ai/v1/projects/{projectId}/tickets' \
  -H 'X-Oprag-Key: sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{"conversationId": "conv_abc123","visitorId": "visitor_001","subject": "Billing question"}'

Channels

Where chat is exposed: the embeddable widget, its public configuration, and WhatsApp.

GET /widget.js

Embed widget bundle (301 to CDN when configured)

Auth Public — no credential

Path parameters

None.

Query parameters

None.Serves a fixed document and takes no input at all.

Body parameters

None.GET requests carry no body.

Response

Status codes

Status Meaning
200 Success.
429 Rate limited. See rate limits.

curl

Shell
curl -X GET 'https://api.dev.oprag.ai/widget.js' \
  -H 'X-Oprag-Key: sk_live_...'
GET /v1/widget/{projectId}/config

Public display configuration for a project's chat widget.

Auth Public — no credential

Before you call it

  • Only served while the project is live or indexing and its widget is enabled.
  • Returns displayName, welcomeMessage, and theme (primaryColor, position, and an optional mode).
  • theme.mode is auto, light, or dark. auto follows the visitor's prefers-color-scheme.
  • quickPrompts and the lead-capture fields appear only when those features are on, and escalationEnabled only when the project has an escalation webhook or email.

Path parameters

Name Type Required Description
projectId string Required Project the request applies to. Must belong to the calling workspace.

Query parameters

None.Reads the resource named in the path; there is nothing else to select.

Body parameters

None.GET requests carry no body.

Response

Status codes

Status Meaning
200 Success.
404 No such resource in this workspace.
429 Rate limited. See rate limits.

curl

Shell
curl -X GET 'https://api.dev.oprag.ai/v1/widget/{projectId}/config' \
  -H 'X-Oprag-Key: sk_live_...'

SDK equivalent `mountWidget()` reads this

Platform

Health, client bootstrap configuration, and environment information.

GET /health

Liveness check

Auth Public — no credential

Path parameters

None.

Query parameters

None.Serves a fixed document and takes no input at all.

Body parameters

None.GET requests carry no body.

Response

200 Success

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

Status codes

Status Meaning
200 Success.
429 Rate limited. See rate limits.

curl

Shell
curl -X GET 'https://api.dev.oprag.ai/health' \
  -H 'X-Oprag-Key: sk_live_...'
GET /config

Cognito pool/client IDs, API URL, Hosted UI domain prefix, SPA OAuth callback, and enabled socialProviders (Google, GitHub). Used by the dashboard and MCP clients to bootstrap auth.

Auth Public — no credential

Path parameters

None.

Query parameters

None.Serves a fixed document and takes no input at all.

Body parameters

None.GET requests carry no body.

Response

200 Success

JSON
{
  "cognitoUserPoolId": "us-east-1_example",
  "cognitoClientId": "exampleclientid",
  "apiUrl": "https://api.dev.oprag.ai",
  "cognitoRegion": "us-east-1",
  "cognitoDomain": "ashutech-dev-oprag",
  "oauthRedirectUri": "https://app.dev.oprag.ai/auth/callback",
  "socialProviders": ["Google", "GitHub"]
}

Status codes

Status Meaning
200 Success.
429 Rate limited. See rate limits.

curl

Shell
curl -X GET 'https://api.dev.oprag.ai/config' \
  -H 'X-Oprag-Key: sk_live_...'
GET /dev/info

Dev testing credentials, MCP login steps, and the live API route catalog.

Auth Public — no credential

Before you call it

  • Returns 404 in staging and production — it exists to bootstrap local and dev testing only.
  • The response carries mcp.authModes, mcp.notes, mcp.testProject, the full loginSteps array, and apis.routes — the live catalog of every main-backend route.
  • The dev QA password is never returned.

Path parameters

None.

Query parameters

None.Serves a fixed document and takes no input at all.

Body parameters

None.GET requests carry no body.

Response

200 Success

JSON
{
  "environment": "dev",
  "apiUrl": "https://api.dev.oprag.ai",
  "docsUrl": "https://dev.oprag.ai/docs/",
  "dashboardUrl": "https://app.dev.oprag.ai",
  "mcp": {
    "credentials": {
      "apiUrl": "https://api.dev.oprag.ai",
      "cognitoUserPoolId": "us-east-1_example",
      "cognitoClientId": "exampleclientid",
      "email": "dev-qa@oprag.ai"
    },
    "testAccount": { "email": "dev-qa@oprag.ai", "companyName": "Dev QA" },
    "testProject": { "purposeId": "mcp-qa", "name": "Uolo Product Assistant" },
    "authModes": [
      { "mode": "credentials", "priority": 1, "env": ["OPRAG_API_URL", "OPRAG_COGNITO_EMAIL", "OPRAG_COGNITO_PASSWORD"] },
      { "mode": "jwt", "priority": 2, "env": ["OPRAG_API_URL", "OPRAG_JWT_TOKEN"] },
      { "mode": "api-key-only", "priority": 3, "env": ["OPRAG_API_URL", "OPRAG_API_KEY"], "description": "health_check and public_chat only" }
    ],
    "loginSteps": [
      { "step": 1, "title": "Install and build the MCP server", "commands": ["cd mcp", "npm install", "npm run build"] },
      { "step": 2, "title": "Configure credentials", "commands": ["cp mcp/.env.example mcp/.env"] }
    ],
    "notes": ["Password self-signup is disabled; use provisioned dev QA or invite."],
    "envExample": { "OPRAG_API_URL": "https://api.dev.oprag.ai", "OPRAG_COGNITO_EMAIL": "dev-qa@oprag.ai" }
  },
  "apis": {
    "count": 74,
    "routes": [{ "method": "GET", "path": "/health", "auth": "Public", "group": "health" }]
  }
}

Status codes

Status Meaning
200 Success.
429 Rate limited. See rate limits.

curl

Shell
curl -X GET 'https://api.dev.oprag.ai/dev/info' \
  -H 'X-Oprag-Key: sk_live_...'

Extract

Structured extraction takes the same integration key and is documented in its own section: Extract — 10 endpoints, covering uploads, jobs, and schemas.

Endpoints that call you

A third party calls us and signs the request — Stripe, Meta, Slack. You configure the URL in their console; you never call it yourself.

EndpointSigned byFull documentation
POST /v1/billing/webhookUpdates the workspace's plan and billing status from Stripe's checkout and subscription events.Workspace
GET /v1/webhooks/whatsappAnswers Meta's hub subscription challenge when the webhook is registered.Channels
POST /v1/webhooks/whatsappReceives inbound WhatsApp messages from Meta and answers them through the project's chat pipeline.Channels
POST /v1/slack/eventsSlack Events API callback (url_verification, app_mention, DM)Integrations

Endpoints Cognito calls

Exists for Cognito to call during federated sign-in. Not a route you integrate against. They are documented on OAuth & sign-in, which explains where the authorize step actually happens.

Ready to ship?

Get started free