{"openapi":"3.0.0","info":{"title":"Bonterra API","version":"1.0.0","description":"API for Fundraising Coach, conversations, analytics, and feedback"},"servers":[{"url":"/api/v1","description":"API v1"}],"paths":{"/api/v1/agent/chat":{"post":{"summary":"Stream chat with an AI agent","description":"Initiates a streaming chat conversation with a specified AI agent. Creates a new conversation or continues an existing one.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message","agentId","siteId"],"properties":{"message":{"type":"string","description":"The user message to send to the agent"},"agentId":{"type":"string","description":"The ID of the agent to chat with"},"siteId":{"type":"string","description":"The site ID for the conversation"},"threadId":{"type":"string","description":"Optional thread ID for continuing an existing conversation"},"userId":{"type":"string","description":"Optional user ID for the conversation"}}}}}},"parameters":[{"name":"X-Bonterra-User-Id","in":"header","description":"DEPRECATED: User ID for authentication and conversation ownership. Use JWT authentication instead.","required":false,"deprecated":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Streaming response from the agent","headers":{"X-Thread-Id":{"description":"Thread ID for new conversations","schema":{"type":"string"}}},"content":{"text/plain":{"schema":{"type":"string","description":"Streaming text response from the agent"}}}},"400":{"description":"Bad request - missing required parameters or unknown agent","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}}},"/api/v1/agent/suggest":{"post":{"summary":"Get suggestions from an AI agent","description":"Generates conversation suggestions from a specified AI agent, either initial suggestions or contextual suggestions based on conversation history.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentId","siteId"],"properties":{"agentId":{"type":"string","description":"The ID of the agent to get suggestions from"},"siteId":{"type":"string","description":"The site ID for the suggestions"},"threadId":{"type":"string","description":"Optional thread ID for contextual suggestions based on conversation history"},"userId":{"type":"string","description":"Optional user ID for the suggestions"}}}}}},"parameters":[{"name":"X-Bonterra-User-Id","in":"header","description":"DEPRECATED: User ID for authentication. Use JWT authentication instead.","required":false,"deprecated":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response with suggestions","content":{"application/json":{"schema":{"type":"object","properties":{"suggestions":{"type":"array","items":{"type":"string"},"description":"Array of suggested conversation starters or follow-up questions"}}}}}},"400":{"description":"Bad request - missing required parameters or unknown agent","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}}},"/api/v1/conversations":{"get":{"summary":"List conversations or get a specific conversation","description":"Retrieves conversations based on filters. Can fetch a specific conversation by threadId or list conversations filtered by siteId, agentId, and/or userId.","parameters":[{"name":"threadId","in":"query","description":"Specific conversation thread ID to retrieve","required":false,"schema":{"type":"string"}},{"name":"siteId","in":"query","description":"Filter conversations by site ID","required":false,"schema":{"type":"string"}},{"name":"agentId","in":"query","description":"Filter conversations by agent ID","required":false,"schema":{"type":"string"}},{"name":"limit","in":"query","description":"Maximum number of conversations to return (default: 10)","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":10}},{"name":"nextToken","in":"query","description":"Pagination token for retrieving the next page of results","required":false,"schema":{"type":"string"}},{"name":"X-Bonterra-User-Id","in":"header","description":"DEPRECATED: User ID for authentication and filtering conversations by user. Use JWT authentication instead.","deprecated":true,"required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"Single conversation response (when threadId is provided)","properties":{"threadId":{"type":"string"},"agentId":{"type":"string"},"siteId":{"type":"string"},"userId":{"type":"string"},"created":{"type":"string","format":"date-time"},"updated":{"type":"string","format":"date-time"},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}}}}}},{"type":"object","description":"List of conversations response","properties":{"conversations":{"type":"array","items":{"type":"object","properties":{"threadId":{"type":"string"},"agentId":{"type":"string"},"siteId":{"type":"string"},"userId":{"type":"string"},"created":{"type":"string","format":"date-time"},"updated":{"type":"string","format":"date-time"}}}},"nextToken":{"type":"string","description":"Token for retrieving the next page of results"}}}]}}}},"400":{"description":"Bad request - missing required filters","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"404":{"description":"Conversation not found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"details":{"type":"string"}}}}}}}}},"/api/v1/analytics":{"post":{"summary":"Log analytics events","description":"Records analytics events from frontend or backend sources. Supports both modern and legacy event formats.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","description":"Modern event format","required":["eventName","siteId","source","eventData"],"properties":{"eventName":{"type":"string","description":"Name of the analytics event"},"siteId":{"type":"string","nullable":true,"description":"Site ID associated with the event"},"source":{"type":"string","enum":["frontend","backend","agent"],"description":"Source of the event"},"eventData":{"type":"object","description":"Event-specific data"},"threadId":{"type":"string","description":"Optional thread ID for conversation-related events"}}},{"type":"object","description":"Legacy event format","required":["event","properties"],"properties":{"event":{"type":"string","description":"Name of the analytics event"},"sessionId":{"type":"string","description":"Session/thread ID"},"properties":{"type":"object","description":"Event properties"},"metadata":{"type":"object","description":"Additional metadata"}}}]}}}},"responses":{"200":{"description":"Event logged successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"description":"Bad request - invalid event format","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}},"get":{"summary":"Analytics endpoint health check","description":"Simple health check for the analytics endpoint","responses":{"200":{"description":"Analytics endpoint is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["analytics-endpoint-ok"]}}}}}}}}},"/api/v1/auth/token":{"post":{"summary":"Exchange user context for JWT token","description":"Customer backend endpoint to exchange user context for a signed JWT token. This enables direct widget access to Bongentic APIs with proper authentication and tenant isolation.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_context"],"properties":{"user_context":{"type":"object","required":["user_id","entity_id","site_id","roles"],"properties":{"user_id":{"type":"string","description":"Unique user identifier","example":"user-123"},"entity_id":{"type":"string","description":"Organization/tenant identifier","example":"org-456"},"site_id":{"type":"string","description":"Product identifier","enum":["npohub","everyaction","nfg"],"example":"npohub"},"roles":{"type":"array","items":{"type":"string","enum":["user","admin","bonterra-staff"]},"minItems":1,"description":"User roles for authorization","example":["admin"]},"optional_claims":{"type":"object","description":"Product-specific optional claims","properties":{"admin_id":{"type":"integer","description":"NFG admin identifier","example":789},"department":{"type":"string","description":"User department","example":"marketing"}}}}}}}}}},"parameters":[{"name":"X-Token-Exchange-Secret","in":"header","description":"Token exchange secret for customer backend authentication","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"JWT token created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"access_token":{"type":"string","description":"Signed JWT token for API access","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."},"expires_in":{"type":"integer","description":"Token expiration time in seconds","example":900},"token_type":{"type":"string","description":"Token type","example":"Bearer"}}}}}},"400":{"description":"Bad request - Invalid user context","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Missing required fields: user_id, entity_id, site_id"}}}}}},"403":{"description":"Forbidden - Invalid API secret","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Invalid or missing API secret"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","example":"Internal server error"}}}}}}}}},"/api/v1/health":{"get":{"summary":"Check the health status of the API","description":"Simple health check endpoint","responses":{"200":{"description":"API is healthy","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]}}}}}}}}},"/api/v1/chat-feedback":{"post":{"summary":"Submit user feedback on agent messages","description":"Records user feedback (positive/negative) for specific messages in a conversation","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["messageIndex","feedbackType"],"properties":{"messageIndex":{"type":"integer","description":"Index of the message being rated"},"feedbackType":{"type":"string","enum":["positive","negative"],"description":"Type of feedback"},"feedbackText":{"type":"string","description":"Optional additional feedback text"},"messageContent":{"type":"string","description":"Optional content of the message being rated"},"siteId":{"type":"string","description":"The site ID"},"threadId":{"type":"string","description":"Optional thread ID"}}}}}},"responses":{"200":{"description":"Feedback received successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}}},"/api/v1/report-error":{"post":{"summary":"Report errors from the frontend","description":"Records error reports from the frontend for monitoring and debugging","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["errorMessage"],"properties":{"errorMessage":{"type":"string","description":"Error message"},"siteId":{"type":"string","description":"The site ID"},"threadId":{"type":"string","description":"Optional thread ID"},"failedMessageIndex":{"type":"integer","description":"Optional index of the message that failed"}}}}}},"responses":{"200":{"description":"Error report received successfully","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}},"500":{"description":"Server error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}}}},"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"details":{"type":"string"}}},"Message":{"type":"object","properties":{"role":{"type":"string","enum":["user","assistant","system"]},"content":{"type":"string"}}},"Conversation":{"type":"object","properties":{"threadId":{"type":"string"},"agentId":{"type":"string"},"siteId":{"type":"string"},"userId":{"type":"string"},"created":{"type":"string","format":"date-time"},"updated":{"type":"string","format":"date-time"},"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}}}}}}