{"openapi":"3.0.3","info":{"title":"Conferbot External API","version":"1.0.0","description":"Customer-facing REST API for managing chatbots, reading responses and analytics, managing webhooks, and checking API usage."},"servers":[{"url":"https://api-v2.conferbot.com/api/v1","description":"Detected from request"}],"tags":[{"name":"External API","description":"Customer-facing API endpoints authenticated with x-api-key."}],"paths":{"/external/v1/chatbots":{"get":{"tags":["External API"],"summary":"List workspace chatbots","operationId":"listChatbots","security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"List of chatbots","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChatbotSummary"}}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["External API"],"summary":"Create a chatbot","operationId":"createChatbot","security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Chatbot created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ChatbotCreated"}}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan chatbot limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/chatbots/{id}":{"get":{"tags":["External API"],"summary":"Get chatbot details","operationId":"getChatbot","security":[{"apiKeyAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ChatbotId"}],"responses":{"200":{"description":"Chatbot details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Chatbot"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["External API"],"summary":"Update a chatbot","operationId":"updateChatbot","security":[{"apiKeyAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ChatbotId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string"},"disabled":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Chatbot updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ChatbotUpdated"}}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["External API"],"summary":"Delete a chatbot","operationId":"deleteChatbot","security":[{"apiKeyAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ChatbotId"}],"responses":{"200":{"description":"Chatbot deleted","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/chatbots/{id}/duplicate":{"post":{"tags":["External API"],"summary":"Duplicate a chatbot","operationId":"duplicateChatbot","security":[{"apiKeyAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ChatbotId"}],"responses":{"201":{"description":"Chatbot duplicated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ChatbotCreated"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Plan chatbot limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/chatbots/{id}/responses":{"get":{"tags":["External API"],"summary":"List chatbot responses","operationId":"listResponses","security":[{"apiKeyAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ChatbotId"},{"in":"query","name":"page","schema":{"type":"integer","default":1,"minimum":1}},{"in":"query","name":"limit","schema":{"type":"integer","default":20,"minimum":1,"maximum":100}},{"in":"query","name":"startDate","schema":{"type":"string","format":"date"}},{"in":"query","name":"endDate","schema":{"type":"string","format":"date"}}],"responses":{"200":{"description":"Paginated responses","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ChatbotResponse"}},"total":{"type":"integer"},"page":{"type":"integer"},"totalPages":{"type":"integer"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/chatbots/{id}/responses/{responseId}":{"get":{"tags":["External API"],"summary":"Get a single response","operationId":"getResponse","security":[{"apiKeyAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ChatbotId"},{"in":"path","name":"responseId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Response details","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ChatbotResponse"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot or response not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/chatbots/{id}/analytics":{"get":{"tags":["External API"],"summary":"Get chatbot analytics","operationId":"getChatbotAnalytics","security":[{"apiKeyAuth":[]}],"parameters":[{"$ref":"#/components/parameters/ChatbotId"},{"in":"query","name":"days","schema":{"type":"integer","default":30,"minimum":1,"maximum":365},"description":"Lookback window in days. Server clamps to [1, 365]; out-of-range values return 400."}],"responses":{"200":{"description":"Analytics data with daily counts","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ChatbotAnalytics"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/webhooks":{"get":{"tags":["External API"],"summary":"List webhooks","operationId":"listWebhooks","security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"List of webhooks","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["External API"],"summary":"Create a webhook","operationId":"createWebhook","security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["chatbotId","url","events"],"properties":{"chatbotId":{"type":"string"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["response.created","response.updated","conversation.started","conversation.completed"]}},"description":{"type":"string"}}}}}},"responses":{"201":{"description":"Webhook created with signing secret","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookWithSecret"},"message":{"type":"string"}}}}}},"400":{"description":"Missing required fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Webhook limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Chatbot not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/webhooks/{id}":{"patch":{"tags":["External API"],"summary":"Update a webhook","description":"Partial update. Only the fields you send are changed. The signing secret is preserved.","operationId":"updateWebhook","security":[{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Webhook ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["response.created","response.updated","conversation.started","conversation.completed"]}},"description":{"type":"string"},"status":{"type":"string","enum":["active","paused"]}}}}}},"responses":{"200":{"description":"Webhook updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"description":"Invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Duplicate (chatbot, url)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["External API"],"summary":"Delete a webhook","operationId":"deleteWebhook","security":[{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Webhook ID"}],"responses":{"200":{"description":"Webhook deleted","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Webhook not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/usage":{"get":{"tags":["External API"],"summary":"Get API usage stats","operationId":"getApiUsage","security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"API usage statistics","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ApiUsage"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/account":{"get":{"tags":["External API"],"summary":"Get account profile","operationId":"getAccountProfile","security":[{"apiKeyAuth":[]}],"responses":{"200":{"description":"Account profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AccountProfile"}}}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["External API"],"summary":"Update account profile","description":"Partial update. Only the fields you send are changed.","operationId":"updateAccountProfile","security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountProfileUpdate"}}}},"responses":{"200":{"description":"Updated account profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AccountProfile"}}}}}},"400":{"description":"No valid fields or invalid input","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Account not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/account/email/request-change":{"post":{"tags":["External API"],"summary":"Request email change (step 1 of 3)","description":"Starts an email change by sending a 6-digit OTP to the account's CURRENT email address. The OTP expires in 10 minutes.\n\nAn API key authenticates a workspace, not the mailbox owner, so it is not sufficient on its own to move the account to a new address. Completing a change requires access to the current inbox: call `/external/v1/account/email/verify-identity` with this code, then `/external/v1/account/email/confirm-change` with the code sent to the new address.\n\nRequires the `account:write` scope. Rate limited to 5 requests per hour per API key.","operationId":"requestAccountEmailChange","security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["newEmail"],"properties":{"newEmail":{"type":"string","format":"email"}}}}}},"responses":{"200":{"description":"OTP sent to the current email address","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"nextStep":{"type":"string"}}}}}}}},"400":{"description":"Invalid email or email already taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"API key missing the account:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit, usage limit, or email change throttle exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/account/email/verify-identity":{"post":{"tags":["External API"],"summary":"Verify identity and send OTP to the new address (step 2 of 3)","description":"Confirms the code sent to the account's CURRENT email address, then sends a second code to the new address. Both codes are required to complete a change, so possession of the API key alone can never move the account.\n\nRequires the `account:write` scope. Rate limited to 5 requests per hour per API key.","operationId":"verifyAccountEmailIdentity","security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["newEmail","otp"],"properties":{"newEmail":{"type":"string","format":"email","description":"Must match the address given in step 1"},"otp":{"type":"string","description":"6-digit code sent to the current email address"}}}}}},"responses":{"200":{"description":"Identity verified; OTP sent to the new address","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"nextStep":{"type":"string"}}}}}}}},"400":{"description":"Invalid or expired code","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"API key missing the account:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit, usage limit, or email change throttle exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/external/v1/account/email/confirm-change":{"post":{"tags":["External API"],"summary":"Confirm email change (step 3 of 3)","description":"Verifies the OTP sent to the new address and updates the account email. Requires a completed identity verification from step 2 — the new-address code alone is never sufficient. The old email is notified.\n\nRequires the `account:write` scope. Rate limited to 5 requests per hour per API key.","operationId":"confirmAccountEmailChange","security":[{"apiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["newEmail","otp"],"properties":{"newEmail":{"type":"string","format":"email"},"otp":{"type":"string","description":"6-digit verification code"}}}}}},"responses":{"200":{"description":"Email updated","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","additionalProperties":true}}}}}},"400":{"description":"Invalid OTP or email already taken","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit or usage limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Workspace API key. Keys may carry scopes limiting what they can reach — a request for an endpoint outside the key's scopes returns 403 naming the scope required. Keys created before scopes existed carry no scopes and are unrestricted. Available scopes: chatbots:read, chatbots:write, responses:read, analytics:read, webhooks:read, webhooks:write, usage:read, account:read, account:write."}},"parameters":{"ChatbotId":{"in":"path","name":"id","required":true,"schema":{"type":"string"},"description":"Chatbot ID"}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}}},"ChatbotSummary":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"disabled":{"type":"boolean"},"responseCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"Chatbot":{"allOf":[{"$ref":"#/components/schemas/ChatbotSummary"},{"type":"object","properties":{"description":{"type":"string"}}}]},"ChatbotCreated":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}}},"ChatbotUpdated":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"disabled":{"type":"boolean"},"updatedAt":{"type":"string","format":"date-time"}}},"ChatbotResponse":{"type":"object","additionalProperties":true,"properties":{"_id":{"type":"string"},"chatSessionId":{"type":"string"},"visitorId":{"type":"string"},"chatDate":{"type":"string","format":"date-time"},"record":{"type":"array","items":{"type":"object"}},"answerVariables":{"type":"object","additionalProperties":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ChatbotAnalytics":{"type":"object","properties":{"totalResponses":{"type":"integer"},"recentResponses":{"type":"integer"},"period":{"type":"string"},"dailyCounts":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date"},"count":{"type":"integer"}}}}}},"Webhook":{"type":"object","properties":{"id":{"type":"string"},"chatbot":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"name":{"type":"string","nullable":true}}},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["response.created","response.updated","conversation.started","conversation.completed"]}},"status":{"type":"string","enum":["active","paused","failed"]},"description":{"type":"string"},"failureCount":{"type":"integer"},"lastDeliveryAt":{"type":"string","format":"date-time","nullable":true},"lastFailureAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WebhookWithSecret":{"allOf":[{"$ref":"#/components/schemas/Webhook"},{"type":"object","properties":{"secret":{"type":"string","description":"HMAC-SHA256 signing key. Returned exactly once on create — save it."}}}]},"AccountProfile":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string","nullable":true},"dateOfBirth":{"type":"string","format":"date","nullable":true},"address":{"type":"string","nullable":true},"timezone":{"type":"string","nullable":true,"description":"IANA timezone, e.g. Asia/Dubai"}}},"AccountProfileUpdate":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"dateOfBirth":{"type":"string","format":"date"},"address":{"type":"string"},"timezone":{"type":"string","description":"IANA timezone, e.g. America/New_York"}}},"ApiUsage":{"type":"object","properties":{"month":{"type":"string","example":"2026-05"},"plan":{"type":"string","example":"Business"},"used":{"type":"integer"},"limit":{"type":"integer"},"remaining":{"type":"integer"}}}}}}