{"openapi":"3.1.0","info":{"title":"Kawl Now Management API","version":"0.3.0","description":"Manage one Kawl Now brand/workspace. Coding agents should connect `/api/mcp` with browser OAuth sign-in: setup:read/setup:write access is limited to the explicitly approved brand and Support, Sales or Both agents, lasts up to 24 hours with offline refresh and can be revoked in Developers. Setup access can read a redacted workspace, eligible knowledge, installation/status and import drafts or configure setup-safe fields; it cannot approve knowledge, enable calls, change phone numbers/billing, manage keys or read conversations. The canonical workflow is `/agent-setup.md`. Advanced workspace tokens created in Developers have full management access to their brand; give them only to trusted tools. Tokens cannot list/create/select another brand. New knowledge is always saved unapproved; the owner reviews and approves its exact revision separately before customer conversations may use it."},"security":[{"workspaceToken":[]}],"components":{"securitySchemes":{"setupOAuth":{"type":"oauth2","description":"Authorization Code with mandatory S256 PKCE and exact resource https://app.kawlnow.com/api/mcp. Setup grant is explicitly brand/agent scoped. Discovery: /.well-known/oauth-protected-resource/api/mcp.","flows":{"authorizationCode":{"authorizationUrl":"https://app.kawlnow.com/oauth/authorize","tokenUrl":"https://app.kawlnow.com/oauth/token","refreshUrl":"https://app.kawlnow.com/oauth/token","scopes":{"setup:read":"Read safe setup settings and selected-agent knowledge.","setup:write":"Configure setup-safe fields, merge origins, import draft knowledge and verify a published installation."}}}},"workspaceToken":{"type":"http","scheme":"bearer","description":"A token created in Developers for the selected brand/workspace."}},"schemas":{"SetupConfiguration":{"type":"object","additionalProperties":false,"required":["channel"],"properties":{"channel":{"enum":["support","sales"]},"settings":{"type":"object","additionalProperties":false,"properties":{"productName":{"type":"string","maxLength":80},"agentName":{"type":"string","maxLength":60},"greeting":{"type":"string","maxLength":500},"instructions":{"type":"string","maxLength":4000},"voice":{"enum":["marin","cedar"]},"widgetLabel":{"type":"string","maxLength":30},"accentColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"agentConfigured":{"type":"boolean"}}},"allowedOrigins":{"type":"array","maxItems":10,"items":{"type":"string","format":"uri"},"description":"Merge these exact public production HTTPS origins atomically with existing origins; never replace them. Localhost, IPs, credentials, paths and internal hosts are rejected."}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}},"AgentSettings":{"type":"object","additionalProperties":false,"description":"Send only the fields to change. Support and sales keep separate settings.","properties":{"productName":{"type":"string","minLength":1,"maxLength":80},"agentName":{"type":"string","minLength":1,"maxLength":60},"greeting":{"type":"string","maxLength":500},"instructions":{"type":"string","maxLength":4000},"voice":{"enum":["marin","cedar"]},"widgetLabel":{"type":"string","maxLength":30},"accentColor":{"type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"allowedOrigins":{"type":"array","maxItems":10,"items":{"type":"string","format":"uri"},"description":"Websites allowed to start calls, as HTTPS origins without a path, such as https://yourproduct.com."},"humanNumber":{"type":"string","maxLength":20,"description":"Human handover number in international format, such as +442071234567, or empty to remove it. Only the operator workspace can set a number."},"escalationEnabled":{"type":"boolean","description":"Offer “Talk to a human”. Customer workspaces must first verify a destination in the dashboard."},"enabled":{"type":"boolean","description":"Accept customer calls on this channel."},"agentConfigured":{"type":"boolean"}}},"Source":{"type":"object","properties":{"id":{"type":"string"},"workspace_id":{"type":"string"},"channel":{"type":"string","enum":["support","sales","both"],"description":"Knowledge audience: Support only, Sales only, or Both agents."},"title":{"type":"string"},"kind":{"enum":["document","github","website"]},"content":{"type":"string"},"repo":{"type":["string","null"]},"path":{"type":["string","null"]},"approved":{"enum":[0,1],"description":"1 when the source is approved for customer conversations."},"content_revision":{"type":"integer","minimum":1,"description":"Review version. Supply this as reviewedRevision when approving or changing the audience. Content refreshes and audience changes increment it."},"updated_at":{"type":"string","format":"date-time"}}},"Conversation":{"type":"object","properties":{"id":{"type":"string"},"channel":{"enum":["support","sales"]},"topic":{"type":"string"},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"seconds":{"type":"number"},"finalized":{"enum":[0,1]},"transcript":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string"},"text":{"type":"string"}}}},"summary":{"type":["string","null"]},"feedback":{"type":["string","null"]}}}}},"paths":{"/api/manage/setup":{"get":{"summary":"Read this brand and agent’s setup checklist","security":[{"workspaceToken":[]},{"setupOAuth":["setup:read"]}],"parameters":[{"name":"channel","in":"query","schema":{"enum":["support","sales"]}}],"description":"Saved agent, approved eligible knowledge, allowed origins, latest published markup check, finalized private browser-test evidence and call enablement are separate facts. Does not start calls or establish human audio acceptance.","responses":{"200":{"description":"Setup status and next action"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Agent is outside the approved connection","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/setup/configure":{"post":{"summary":"Configure setup-safe fields and merge production origins","security":[{"workspaceToken":[]},{"setupOAuth":["setup:read","setup:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupConfiguration"}}}},"responses":{"200":{"description":"Saved safe settings and refreshed setup status"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient setup or agent access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Concurrent update; refresh before retrying","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/setup/verify":{"post":{"summary":"Verify a published website installation","security":[{"workspaceToken":[]},{"setupOAuth":["setup:read","setup:write"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["url","channel"],"properties":{"url":{"type":"string","format":"uri","description":"Public HTTPS HTML page without query parameters or account-action paths."},"channel":{"enum":["support","sales"]}}}}}},"description":"Bounded public-only DNS-pinned fetch and static HTML/policy inspection. Status verified means published markup checks passed, never browser initialization, microphone audio or human handover. Dynamic scripts may be inconclusive. Saves only the latest diagnostic per brand/channel; shares website scan budgets.","responses":{"200":{"description":"Checks, remediation, explicit static-only limits and setup status"},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient setup or agent access","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Account or service website-check limit reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/insights":{"get":{"summary":"Read automatic conversation insights","description":"Recurring questions, issues and themes with validated caller excerpts. Analyses up to the latest 30 finalized non-test calls in the last 30 days; updates automatically. Counts describe the sample, not all calls.","parameters":[{"name":"channel","in":"query","schema":{"type":"string","enum":["support","sales"],"default":"support"}}],"responses":{"200":{"description":"Current report, evidence and coverage, or an empty/pending state","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/knowledge-gaps":{"get":{"summary":"Find potential knowledge gaps","description":"Compares recurring caller questions and suggested Support or Sales topics with current approved knowledge, including Both sources. Reports matching drafts awaiting review and sources tagged for the other agent. Call counts and evidence come from the bounded Insights sample, not all calls. Text matching does not prove an unanswered call or complete coverage. Read-only; no new provider request, generated answer or automatic approval. Setup-only OAuth connections cannot access caller evidence.","parameters":[{"name":"channel","in":"query","schema":{"type":"string","enum":["support","sales"],"default":"support"}}],"responses":{"200":{"description":"Potential gaps, current source diagnostics and sampled call coverage","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Full management access required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/workspace":{"get":{"summary":"Read the workspace","description":"Returns this brand’s workspace ID, support and sales settings, account-wide shared free conversations used, brand knowledge source details with approval status, the brand’s 100 most recent conversations, token prefixes, and connection, notification and usage status.","responses":{"200":{"description":"The workspace","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/settings":{"patch":{"summary":"Update the support agent and widget","description":"Changes the support channel’s agent, widget, allowed websites and call settings.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSettings"}}}},"responses":{"200":{"description":"The saved settings for this channel","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer handover requires a phone number verified in the dashboard","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another change was saved at the same time; try again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/sales-settings":{"patch":{"summary":"Update the sales agent and widget","description":"Changes the sales channel’s agent, widget, allowed websites and call settings. Sales settings are separate from support settings.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSettings"}}}},"responses":{"200":{"description":"The saved settings for this channel","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Customer handover requires a phone number verified in the dashboard","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Another change was saved at the same time; try again","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/sources":{"post":{"summary":"Add knowledge for review","description":"Saves a document for Support only, Sales only, or Both agents as unapproved knowledge. New sources are always unapproved, and any `approved` value in the request is ignored. Review the source, then approve it with `PATCH /api/manage/sources/{id}`. A brand can hold up to 500 sources within the shared account byte allowance.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","content"],"properties":{"channel":{"type":"string","enum":["support","sales","both"],"default":"support"},"title":{"type":"string","minLength":1,"maxLength":140},"content":{"type":"string","minLength":1,"maxLength":50000}}}}}},"responses":{"201":{"description":"The new source, saved unapproved","content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/sources/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"Source ID","schema":{"type":"string"}}],"get":{"summary":"Read a source for review","description":"Returns the source, including its full text.","responses":{"200":{"description":"The source","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Source"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Source not found in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Change a source approval or knowledge audience","description":"Send one operation at a time. To approve, read the full source first and pass its content_revision as reviewedRevision; unapproving needs no revision. To change the audience, send channel and the exact reviewedRevision. An audience change preserves the source ID, text and approval, increments the revision, and immediately makes approved text available to that audience. A content refresh removes approval, even for unchanged text. Stale reviews return 409; approval and audience cannot change in the same request.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":false,"required":["approved"],"properties":{"approved":{"type":"boolean"},"reviewedRevision":{"type":"integer","minimum":1,"maximum":2147483647}},"anyOf":[{"properties":{"approved":{"const":false}}},{"required":["reviewedRevision"]}]},{"type":"object","additionalProperties":false,"required":["channel","reviewedRevision"],"properties":{"channel":{"type":"string","enum":["support","sales","both"]},"reviewedRevision":{"type":"integer","minimum":1,"maximum":2147483647}}}]}}}},"responses":{"200":{"description":"Approval saved, or the updated source audience metadata","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["ok"],"properties":{"ok":{"const":true}}},{"type":"object","required":["id","channel","content_revision","approved"],"properties":{"id":{"type":"string"},"channel":{"type":"string","enum":["support","sales","both"]},"content_revision":{"type":"integer","minimum":1},"approved":{"enum":[0,1]}}}]}}}},"400":{"description":"Send approved or channel separately; approving or changing the audience requires a positive reviewedRevision","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Source not found in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Source changed since review, or the GitHub document/website URL already exists for that audience; read the current source before retrying","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Account knowledge-write budget reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a source","responses":{"200":{"description":"Done","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/github":{"post":{"summary":"Import or refresh one GitHub file for Support, Sales, or Both","description":"Imports or refreshes one eligible repository text or source-code file as complete unapproved knowledge for Support only, Sales only, or Both agents. Use github/scan and github/import to choose multiple files at a pinned commit. Regular files are checked through immutable Git trees and verified blobs; code is never executed. Long text is split without truncation. Review every source before exact-revision approval. A bound sourceId preserves its audience when omitted; concurrent group changes return 409. A private repository needs the server’s GitHub token and must be on this brand’s server-side allowlist.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["repo"],"properties":{"repo":{"type":"string","description":"owner/repository or its GitHub URL"},"path":{"type":"string","default":"README.md","description":"Relative path of the document"},"sourceId":{"type":"string","description":"Existing source ID for a bound refresh; must match this brand, repository, path and any explicit audience."},"channel":{"type":"string","enum":["support","sales","both"],"default":"support"}}}}}},"responses":{"201":{"description":"The imported source, saved unapproved","content":{"application/json":{"schema":{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Repository or document not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The source audience or identity changed during refresh; reload it before retrying","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"GitHub could not sync the document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/documents":{"post":{"summary":"Upload multiple PDF knowledge documents","description":"Upload one to 25 text PDFs, each at most 2 MiB and 100 pages, with a 50 MiB total file limit. Extracted text must fit 50,000 characters per source. All sources are saved atomically, unapproved, for Support only, Sales only, or Both agents. No original PDF is retained. Scanned, encrypted, oversized and malformed files are rejected without partial saves.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["files"],"properties":{"files":{"type":"array","minItems":1,"maxItems":25,"items":{"type":"string","format":"binary"}},"channel":{"type":"string","enum":["support","sales","both"],"default":"support"}}}}}},"responses":{"201":{"description":"Unapproved document sources saved","content":{"application/json":{"schema":{"type":"object","properties":{"sources":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"}}}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Editor or owner access and trusted Origin required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"PDF upload is too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Parser or account capacity reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"PDF extraction is unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/website":{"post":{"summary":"Scan a public website into knowledge drafts","description":"Scans up to 250 public HTML pages using HTTPS connections pinned to validated public addresses, respecting robots and sensitive-path exclusions. Saves complete unapproved sources for Support only, Sales only, or Both agents, with URL provenance and full-text chunks. Use website/scan then website/import to choose pages before saving. Supply sourceId to refresh only its whole page group; refreshing removes approval. Account byte and write allowances and the 500-source brand capacity apply atomically.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"channel":{"type":"string","enum":["support","sales","both"],"default":"support"},"sourceId":{"type":"string"}}}}}},"responses":{"201":{"description":"Knowledge drafts saved for review","content":{"application/json":{"schema":{"type":"object","properties":{"sources":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"url":{"type":"string"}}}},"pagesScanned":{"type":"integer"},"skippedPages":{"type":"array","items":{"type":"object"}},"truncated":{"type":"boolean"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Scan capacity or account limits reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The website could not be read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Scan capacity is temporarily unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/website/scan":{"post":{"summary":"Preview up to 250 website pages before import","description":"Discovers readable public HTML without saving knowledge. Returns metadata and a server-held, brand/audience-bound preview that expires after 15 minutes. Scan limits and skipped pages are reported; long pages retain their full readable text.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri"},"channel":{"type":"string","enum":["support","sales","both"],"default":"support"}}}}}},"responses":{"200":{"description":"Website page preview","content":{"application/json":{"schema":{"type":"object","properties":{"scanId":{"type":"string"},"pages":{"type":"array","maxItems":250,"items":{"type":"object"}},"expiresAt":{"type":"string"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Audience or account access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Scan capacity reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/website/import":{"post":{"summary":"Import all or selected pages from a website preview","description":"Imports only server-held text for selected preview URLs. Complete page groups save atomically as unapproved sources. Browser text is never trusted. A changed source group, expired preview or account capacity failure saves nothing.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scanId","pageUrls"],"properties":{"scanId":{"type":"string"},"pageUrls":{"type":"array","minItems":1,"maxItems":250,"items":{"type":"string","format":"uri"}}}}}}},"responses":{"201":{"description":"Complete drafts saved for review","content":{"application/json":{"schema":{"type":"object","properties":{"sources":{"type":"array","items":{"type":"object"}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Audience or account access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Preview missing or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Account capacity or reviewed revisions changed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/github/scan":{"post":{"summary":"Scan a repository and preview eligible files","description":"Lists up to 500 eligible text or source-code files at a pinned default-branch commit. The brand/audience-bound preview expires after 15 minutes. Symlinks, submodules, generated/binary files and recognized credential files are excluded. Private access is checked server-side.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["repo"],"properties":{"repo":{"type":"string"},"channel":{"type":"string","enum":["support","sales","both"],"default":"support"}}}}}},"responses":{"200":{"description":"Repository file preview","content":{"application/json":{"schema":{"type":"object","properties":{"scanId":{"type":"string"},"files":{"type":"array","maxItems":500,"items":{"type":"object"}}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Audience or account access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Repository not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Repository scan capacity reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/github/import":{"post":{"summary":"Import selected repository files for review","description":"Reads up to 100 selected files from a server-held preview, at most 1 MB per file and 20 MB selected bytes. Git blob hashes, sizes and text are verified. Complete contents save atomically as unapproved chunks within brand/account capacity; private access and source group revisions are rechecked. No repository code runs.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scanId","paths"],"properties":{"scanId":{"type":"string"},"channel":{"type":"string","enum":["support","sales","both"],"default":"support"},"paths":{"type":"array","minItems":1,"maxItems":100,"items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Selected files saved as drafts","content":{"application/json":{"schema":{"type":"object","properties":{"imported":{"type":"integer"},"sources":{"type":"integer"},"approved":{"const":false}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Audience or account access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Preview missing or expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Source group changed during import","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Import capacity reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/conversations/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"Conversation ID","schema":{"type":"string"}}],"get":{"summary":"Read a conversation","description":"Returns one conversation with its transcript.","responses":{"200":{"description":"The conversation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Conversation"}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Conversation not found in this workspace","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/keys":{"post":{"summary":"Create a workspace token","description":"Returns a new token once. Only its hash is stored. A notification email is sent when email notifications are set up.","responses":{"201":{"description":"The new token","content":{"application/json":{"schema":{"type":"object","required":["id","token"],"properties":{"id":{"type":"string"},"token":{"type":"string"}}}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/keys/{id}":{"parameters":[{"name":"id","in":"path","required":true,"description":"Token ID","schema":{"type":"string"}}],"delete":{"summary":"Revoke a workspace token","description":"The token stops working at once.","responses":{"200":{"description":"Done","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/manage/notifications/test":{"post":{"summary":"Send a test notification email","description":"Queues one test email to the workspace’s notification address, at most once a minute.","responses":{"202":{"description":"Queued","content":{"application/json":{"schema":{"type":"object","properties":{"queued":{"const":true}}}}}},"401":{"description":"Missing, invalid or revoked workspace token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"No notification address is set up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Wait a minute before sending another test","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Email is not set up on this server","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}