openapi: 3.0.3
info:
title: Brainfish Public Agents Sessions API
description: "The Brainfish API is organized around REST. Our API has predictable resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.\n\nUse the Brainfish API to programmatically manage your knowledge base, generate AI-powered answers, and integrate Brainfish capabilities into your applications.\n\n---\n\n## Just Getting Started?\n\nCheck out our [Help documentation](https://help.brainfi.sh) for guides and tutorials.\n\n---\n\n## Base URL\n\n```\nhttps://api.brainfi.sh\n```\n\nAll API requests must be made over HTTPS. Calls made over plain HTTP will fail.\n\n---\n\n## Authentication\n\nThe Brainfish API uses API tokens to authenticate requests. You can view and manage your API tokens in your [Brainfish Dashboard](https://app.brainfi.sh) under **Settings → API Tokens**.\n\nAPI tokens have the prefix `bf_api_`. Your API tokens carry many privileges, so be sure to keep them secure! Do not share your API tokens in publicly accessible areas such as GitHub, client-side code, and so forth.\n\nAll API requests must include authentication. Requests without authentication will fail.\n\n| Header | Description |\n|--------|-------------|\n| `Authorization` | Bearer token authentication: `Bearer bf_api_xxxxx` |\n| `agent-key` | Required for AI Agent endpoints only. Find this in your Agents page. |\n\n**Example: Authenticated Request**\n\n```bash\ncurl https://api.brainfi.sh/v1/auth/validate \\\n -X POST \\\n -H \"Authorization: Bearer bf_api_xxxxx\" \\\n -H \"Content-Type: application/json\"\n```\n\n---\n\n## Errors\n\nBrainfish uses conventional HTTP response codes to indicate the success or failure of an API request.\n\n| Code | Description |\n|------|-------------|\n| `2xx` | Success — The request was successful. |\n| `4xx` | Client Error — The request failed due to client-side issues (e.g., missing required parameter, invalid authentication, resource not found). |\n| `5xx` | Server Error — Something went wrong on Brainfish's servers (these are rare). |\n\n**Error Response Format**\n\n```json\n{\n \"error\": \"validation_failed\",\n \"message\": \"Request validation failed\",\n \"validationErrors\": [\n {\n \"field\": \"query\",\n \"message\": \"Query cannot be empty\",\n \"code\": \"invalid_string\"\n }\n ],\n \"timestamp\": \"2024-01-15T10:30:00Z\",\n \"requestId\": \"req-abc123\"\n}\n```\n\nThe `requestId` can be provided to Brainfish support when troubleshooting issues.\n\n---\n\n## Rate Limiting\n\nThe API implements rate limiting to ensure fair usage and system stability.\n\n| Endpoint Type | Limit |\n|---------------|-------|\n| Most endpoints | 25 requests per minute |\n| Token revocation | 10 requests per hour |\n\nWhen you exceed the rate limit, the API returns a `429 Too Many Requests` response with headers indicating when you can retry:\n\n- `X-RateLimit-Limit`: Maximum requests allowed in the window\n- `X-RateLimit-Remaining`: Remaining requests in current window\n- `X-RateLimit-Reset`: Unix timestamp when the rate limit resets\n\n---\n\n## Available Resources\n\n| Resource | Description |\n|----------|-------------|\n| **Authentication** | Validate and revoke API tokens |\n| **AI Agents** | Generate streaming AI-powered answers from your knowledge base |\n| **Analytics** | Query conversation thread analytics with filtering and pagination |\n| **Conversations** | Generate follow-up questions for conversations |\n| **Collections** | Organize documents into collections |\n| **Catalogs** | Create catalogs and sync content via API |\n| **Documents** | Create, read, update, and delete documents |\n\n---\n\n## Quick Start\n\n**1. Create an API token** in your Brainfish dashboard under Settings → API Tokens.\n\n**2. Validate your token** to ensure it's working:\n\n```bash\ncurl https://api.brainfi.sh/v1/auth/validate \\\n -X POST \\\n -H \"Authorization: Bearer bf_api_xxxxx\" \\\n -H \"Content-Type: application/json\"\n```\n\n**3. For AI endpoints**, get your agent key from the Agents page.\n\n**4. Generate an AI answer**:\n\n```bash\ncurl https://api.brainfi.sh/v1/agents/answer \\\n -X POST \\\n -H \"Authorization: Bearer bf_api_xxxxx\" \\\n -H \"agent-key: your-agent-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"query\": \"How do I reset my password?\"}'\n```\n\n---\n\n## Pagination\n\nList endpoints support pagination using `limit` and `offset` parameters:\n\n| Parameter | Description | Default |\n|-----------|-------------|---------|\n| `limit` | Maximum number of results to return (1-100) | 25 |\n| `offset` | Number of results to skip | 0 |\n\nPaginated responses include a `pagination` object:\n\n```json\n{\n \"data\": [...],\n \"pagination\": {\n \"offset\": 0,\n \"limit\": 25,\n \"total\": 42\n }\n}\n```\n"
version: 1.0.0
contact:
name: Brainfish API Support
email: support@brainfish.ai
url: https://help.brainfi.sh/articles/api-reference-7mjzVCAmeM
license:
name: Proprietary
servers:
- url: https://api.brainfi.sh
description: Production server
tags:
- name: Sessions
description: Chat session search, detail, timeline, and AI-powered insights. A "session" is a chat conversation keyed by conversationId.
paths:
/v1/sessions/search:
post:
summary: Search chat sessions
description: 'Search chat sessions (conversations) by query text, filters, and date range.
Returns one result per conversation, folded by conversationId.
A "session" in this context means a chat conversation (one or more user turns with the AI agent).
'
operationId: searchSessions
tags:
- Sessions
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
query:
type: string
description: Text to search for in user queries (case-insensitive partial match)
conversationId:
type: string
description: Filter by exact conversation ID
userId:
type: string
format: uuid
description: Filter by platform user ID
externalUserId:
type: string
description: Filter by external user ID
widgetIds:
type: array
items:
type: string
format: uuid
description: Filter by widget/agent IDs
source:
type: string
description: Filter by source (e.g. widget, api, help_center)
feedback:
type: string
enum:
- positive
- negative
nullable: true
description: Filter by feedback (null means no feedback given)
isAnswered:
type: boolean
description: Filter by whether the query was answered
fromDate:
type: string
format: date-time
description: Start date (ISO 8601)
toDate:
type: string
format: date-time
description: End date (ISO 8601)
limit:
type: integer
minimum: 1
maximum: 100
default: 20
offset:
type: integer
minimum: 0
default: 0
sortOrder:
type: string
enum:
- asc
- desc
default: desc
example:
query: refund
isAnswered: false
fromDate: '2026-04-01T00:00:00Z'
toDate: '2026-04-23T23:59:59Z'
limit: 20
responses:
'200':
description: Sessions matching the search criteria
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: string
conversationId:
type: string
nullable: true
lastQuery:
type: string
lastQueryAt:
type: string
format: date-time
turnCount:
type: integer
isAnswered:
type: boolean
feedback:
type: string
nullable: true
userId:
type: string
nullable: true
externalUserId:
type: string
nullable: true
source:
type: string
nullable: true
widgetId:
type: string
nullable: true
pagination:
type: object
properties:
offset:
type: integer
limit:
type: integer
total:
type: integer
timestamp:
type: string
format: date-time
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
/v1/sessions/{id}:
get:
summary: Get session detail
description: 'Fetch full conversation detail for a chat session: all turns (user query, AI answer, feedback)
plus analytics metadata (session start time, start URL, linked search query IDs).
Accepts a conversationId or searchQueryId.
'
operationId: getSession
tags:
- Sessions
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Conversation ID or search query ID
responses:
'200':
description: Session detail with turns and analytics metadata
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
conversationId:
type: string
teamId:
type: string
startedAt:
type: string
format: date-time
endedAt:
type: string
format: date-time
sessionId:
type: string
nullable: true
startedAtUrl:
type: string
nullable: true
searchQueryIds:
type: array
items:
type: string
turnCount:
type: integer
turns:
type: array
items:
type: object
properties:
id:
type: string
query:
type: string
rewrittenQuery:
type: string
nullable: true
suggestedAnswer:
type: string
nullable: true
isAnswered:
type: boolean
feedback:
type: string
nullable: true
createdAt:
type: string
format: date-time
timestamp:
type: string
format: date-time
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
/v1/sessions/{id}/timeline:
get:
summary: Get session event timeline
description: 'Fetch the chronological analytics event timeline for a conversation. Includes page views,
widget interactions, search events, and chat turns with their properties map.
The timeline is proxied from the analytic-service.
'
operationId: getSessionTimeline
tags:
- Sessions
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Conversation ID
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 1000
default: 200
- name: includeSessionContext
in: query
schema:
type: boolean
default: true
description: Include session-level events (screen views, widget open/close)
- name: fromDate
in: query
schema:
type: string
format: date-time
- name: toDate
in: query
schema:
type: string
format: date-time
- name: eventNames
in: query
schema:
type: string
description: Comma-separated event name(s) to filter by (e.g. "screen_view,Primary Field Search Submitted")
- name: country
in: query
schema:
type: string
description: Comma-separated country code(s) (e.g. "US,CA")
- name: city
in: query
schema:
type: string
description: Comma-separated city name(s)
- name: region
in: query
schema:
type: string
description: Comma-separated region/state name(s)
- name: os
in: query
schema:
type: string
description: Comma-separated OS name(s) (e.g. "Mac OS,Windows")
- name: browser
in: query
schema:
type: string
description: Comma-separated browser name(s) (e.g. "Chrome,Safari")
- name: device
in: query
schema:
type: string
description: Comma-separated device type(s) (e.g. "desktop,mobile")
- name: referrerType
in: query
schema:
type: string
description: Comma-separated referrer type(s) (e.g. "search,social,direct")
responses:
'200':
description: Chronological event timeline
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
type: object
properties:
id:
type: string
name:
type: string
createdAt:
type: string
userId:
type: string
sessionId:
type: string
widgetKey:
type: string
conversationId:
type: string
searchQueryId:
type: string
path:
type: string
origin:
type: string
properties:
type: object
additionalProperties:
type: string
timestamp:
type: string
format: date-time
'401':
$ref: '#/components/responses/Unauthorized'
'429':
$ref: '#/components/responses/TooManyRequests'
/v1/sessions/{id}/insights:
post:
summary: Generate session insights
description: 'Generate a structured LLM-powered diagnosis of a chat session: root cause analysis,
severity, evidence, and actionable recommendations. Results are cached server-side for 24 hours.
Use force=true to regenerate.
'
operationId: generateSessionInsights
tags:
- Sessions
security:
- BearerAuth: []
parameters:
- name: id
in: path
required: true
schema:
type: string
description: Conversation ID or search query ID
requestBody:
content:
application/json:
schema:
type: object
properties:
force:
type: boolean
default: false
description: Skip cache and regenerate insights
responses:
'200':
description: Structured session diagnosis
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
summary:
type: string
rootCause:
type: object
properties:
category:
type: string
enum:
- missing_content
- retrieval_miss
- hallucination
- ambiguous_query
- out_of_scope
- user_confusion
- other
explanation:
type: string
severity:
type: string
enum:
- low
- medium
- high
evidence:
type: array
items:
type: object
properties:
type:
type: string
ref:
type: string
quote:
type: string
recommendations:
type: array
items:
type: object
properties:
action:
type: string
rationale:
type: string
metrics:
type: object
properties:
turnCount:
type: integer
hadNegativeFeedback:
type: boolean
answerCoverage:
type: string
enum:
- full
- partial
- none
cached:
type: boolean
timestamp:
type: string
format: date-time
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'429':
$ref: '#/components/responses/TooManyRequests'
components:
schemas:
Error:
type: object
required:
- error
- message
properties:
error:
type: string
description: Error type or code
message:
type: string
description: Human-readable error message
details:
type: object
additionalProperties: true
description: Additional error details
timestamp:
type: string
format: date-time
description: Error timestamp
requestId:
type: string
description: Unique request identifier for debugging
responses:
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: not_found
message: Document not found
timestamp: '2024-01-15T10:30:00Z'
requestId: req-notfound123
TooManyRequests:
description: Rate limit exceeded
headers:
X-RateLimit-Limit:
schema:
type: integer
description: Request limit per time window
X-RateLimit-Remaining:
schema:
type: integer
description: Remaining requests in current window
X-RateLimit-Reset:
schema:
type: integer
description: Time when rate limit resets (Unix timestamp)
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error: rate_limit_exceeded
message: 'Too many requests. Rate limit: 25 requests per minute'
timestamp: '2024-01-15T10:30:00Z'
Unauthorized:
description: Authentication required or invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
missingToken:
summary: Missing authentication token
value:
error: authentication_required
message: 'Authentication required. Use Authorization: Bearer <token> header'
timestamp: '2024-01-15T10:30:00Z'
requestId: req-abc123
missingAgentKey:
summary: Missing agent key
value:
error: authentication_required
message: Agent key is required
timestamp: '2024-01-15T10:30:00Z'
requestId: req-def456
invalidCredentials:
summary: Invalid credentials
value:
error: authentication_required
message: Invalid or missing authentication credentials
timestamp: '2024-01-15T10:30:00Z'
requestId: req-ghi789
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: API Token
description: 'Bearer token authentication. Include your API token in the Authorization header.
Example: `Authorization: Bearer bf_api_xxxxx`
Create tokens in your Brainfish dashboard under Settings → API Tokens.
'
AccessToken:
type: apiKey
in: header
name: access-token
description: '**Deprecated**: Use Bearer authentication instead.
Legacy access token header for backward compatibility. Must start with `bf_api_`.
Create tokens in your Brainfish dashboard under Settings → API Tokens.
'
AgentKey:
type: apiKey
in: header
name: agent-key
description: 'Agent key identifier that specifies which AI agent/widget to use for the request.
Find agent keys in your Brainfish dashboard under Agents. Click on any agent key to copy it.
'