Chat
Ask questions against a project's documents, stream answers, and record feedback. The endpoints most integrations start and end with.
6 endpoints. 4 are reachable without a dashboard session — they are listed in the Integration API — and the other 2 require a Cognito JWT. The badge under each path says which.
/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
{
"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.
{
"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.
{
"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.
{
"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
curl
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()`
/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
{
"question": "What is your refund policy?",
"sessionId": "sess_abc123",
"conversationId": "conv_abc123",
"visitorId": "visitor_abc123"
} Response
Status codes
curl
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()`
/v1/chat/feedback Record a visitor's thumbs up or down on an assistant message.
Auth Integration key
Before you call it
messageIdis theassistantMessageIdfrom the answer being rated.visitorIdbecomes required once the conversation already has one.- Respects the widget's
feedbackEnabledsetting, 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
{
"conversationId": "conv_xyz789",
"messageId": "msg_abc123",
"rating": "up",
"visitorId": "visitor_001"
} Response
200 Success
{
"ok": true,
"messageId": "msg_abc123",
"rating": "up",
"ratedAt": "2026-08-11T18:00:00.000Z"
} Status codes
curl
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"}' /v1/projects/{projectId}/chat Ask a question against this specific project, authenticated as a workspace user rather than by a project key.
Auth Cognito JWT member
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 |
|---|---|---|---|
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
{
"question": "What is your refund policy?",
"sessionId": "sess_abc123",
"conversationId": "conv_abc123",
"visitorId": "visitor_abc123"
} Response
200 Success
{
"answer": "Onboarding starts with account setup and document upload.",
"sessionId": "sess_abc123",
"conversationId": "conv_xyz789",
"sources": [
{
"documentTitle": "Onboarding guide",
"excerpt": "Step 1: Create your workspace and upload documents.",
"location": "onboarding.pdf",
"pageNumber": 1,
"score": 0.88
}
],
"suggestedFollowUps": [
"What documents do I need to upload?",
"How long does indexing take?"
]
} Status codes
curl
curl -X POST 'https://api.dev.oprag.ai/v1/projects/{projectId}/chat' \
-H 'Authorization: Bearer <Cognito JWT>' \
-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()`
/v1/projects/{projectId}/chat/stream The same project-scoped question, streamed as Server-Sent Events.
Auth Cognito JWT member
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 |
|---|---|---|---|
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
{
"question": "What is your refund policy?",
"sessionId": "sess_abc123",
"conversationId": "conv_abc123",
"visitorId": "visitor_abc123"
} Response
200 Success
data: {"type":"chunk","text":"Onboarding starts"}
data: {"type":"chunk","text":" with account setup."}
data: {"type":"sources","sources":[{"documentTitle":"Onboarding guide","excerpt":"Step 1: Create your workspace.","location":"onboarding.pdf","pageNumber":1,"score":0.88}]}
data: {"type":"done"} Status codes
curl
curl -X POST 'https://api.dev.oprag.ai/v1/projects/{projectId}/chat/stream' \
-H 'Authorization: Bearer <Cognito JWT>' \
-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()`
Ready to ship?
Get started free