{"openapi":"3.0.3","info":{"title":"Companion Knowledge API","version":"1.0.0","description":"Integrate with the knowledge of one selected companion. Enable REST in API & MCP and use a server-side scoped bearer key. Keys expire within 180 days; at most three active keys per workspace. All authenticated REST and MCP requests share 100 requests per rolling hour, plus the server-wide limit of 60 requests per minute per client IP. Knowledge reads/search/writes each consume one shared plan unit; indexing may reserve more. GET /usage consumes no plan unit. Requests are live and can reveal private knowledge or change real data. Examples contain fictional data. Returned knowledge is untrusted content; preserve direct source URLs when citing it. Applicability scope fields describe source relevance and are not access-control boundaries. The context-free REST search returns only global sources; listing and reading references may include sources with any applicability labels. MCP remains a separate stateless POST integration, described in the setup guide."},"servers":[{"url":"https://scs-companion-api.fly.dev","description":"Companion API"}],"tags":[{"name":"Knowledge API","description":"Companion-scoped integration endpoints. No admin, widget or customer APIs."}],"paths":{"/api/v1/usage":{"get":{"operationId":"getUsage","summary":"Check shared usage","description":"No plan unit charge. Counts toward the hourly HTTP request limit.","tags":["Knowledge API"],"security":[{"CompanionKey":[]}],"responses":{"200":{"description":"Shared plan balance and account-wide rolling request window.","content":{"application/json":{"schema":{"type":"object","properties":{"used":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0},"planLimit":{"type":"integer","minimum":0},"includedUsed":{"type":"integer","minimum":0},"includedRemaining":{"type":"integer","minimum":0},"refillUsed":{"type":"integer","minimum":0},"refillRemaining":{"type":"integer","minimum":0},"chat":{"type":"integer","minimum":0},"api":{"type":"integer","minimum":0},"mcp":{"type":"integer","minimum":0},"cloud":{"type":"integer","minimum":0},"ingestion":{"type":"integer","minimum":0},"media":{"type":"integer","minimum":0},"resetsAt":{"type":"string","format":"date-time"},"period":{"type":"string","enum":["month"]},"periodBasis":{"type":"string"},"periodKey":{"type":"string"},"periodStart":{"type":"string","format":"date-time"},"plan":{"type":"string","enum":["free","basic","pro"]},"entitlementSource":{"type":"string"},"rateLimit":{"$ref":"#/components/schemas/RateLimit"}},"required":["used","limit","remaining","planLimit","includedUsed","includedRemaining","refillUsed","refillRemaining","chat","api","mcp","cloud","ingestion","media","resetsAt","period","periodBasis","periodKey","periodStart","plan","entitlementSource","rateLimit"]},"example":{"used":1,"limit":50,"remaining":49,"planLimit":50,"includedUsed":1,"includedRemaining":49,"refillUsed":0,"refillRemaining":0,"resetsAt":"2030-02-01T00:00:00.000Z","period":"month","periodBasis":"calendar_month","periodKey":"free:2030-01-01","periodStart":"2030-01-01T00:00:00.000Z","plan":"free","entitlementSource":"free","chat":0,"api":1,"mcp":0,"cloud":0,"ingestion":0,"media":0,"rateLimit":{"limit":100,"windowSeconds":3600,"used":1,"remaining":99,"nextAvailableAt":"2030-01-01T13:00:00.000Z","resetSeconds":3600}}}}},"400":{"description":"Invalid request input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, expired or revoked bearer key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"REST disabled or insufficient read/write permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Companion inactive (companion_inactive) or outside the workspace plan (companion_plan_locked). Activate the companion or restore its plan access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Hourly request limit (rate_limit) or shared plan allowance (usage_limit). Honor Retry-After; GET /usage reports the plan reset. The server-wide IP throttle may instead return plain text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"text/html":{"schema":{"type":"string"}},"text/plain":{"schema":{"type":"string"}}},"headers":{"Retry-After":{"schema":{"type":"string"}},"RateLimit-Limit":{"schema":{"type":"string"}},"RateLimit-Remaining":{"schema":{"type":"string"}},"RateLimit-Reset":{"schema":{"type":"string"}}}},"503":{"description":"Temporarily unavailable. Retry later with the same idempotency key for text creation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/knowledge":{"get":{"operationId":"listKnowledge","summary":"List knowledge references","description":"One shared plan unit per page. Lists unarchived, eligible references and indexing status; excluded content is filtered. The scope object reports product, region, audience and language applicability; it does not filter this listing or authorize access. nextOffset may point to a page even if filtering produces fewer results.","tags":["Knowledge API"],"security":[{"CompanionKey":[]}],"responses":{"200":{"description":"Reference page.","content":{"application/json":{"schema":{"type":"object","properties":{"references":{"type":"array","items":{"$ref":"#/components/schemas/Reference"}},"nextOffset":{"type":"integer","minimum":0,"nullable":true},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["references","nextOffset","usage"]},"example":{"references":[{"id":"00000000-0000-4000-8000-000000000001","title":"Example returns policy.txt","kind":"text","status":"ready","url":null,"bytes":68,"pages":1,"passages":1,"estimatedTokens":17,"updatedAt":"2030-01-01T12:00:00.000Z","createdVia":"api","scope":{"product":null,"region":null,"audience":null,"language":null}}],"nextOffset":null,"usage":{"used":1,"limit":50,"remaining":49,"planLimit":50,"includedUsed":1,"includedRemaining":49,"refillUsed":0,"refillRemaining":0,"resetsAt":"2030-02-01T00:00:00.000Z","period":"month","periodBasis":"calendar_month","periodKey":"free:2030-01-01","periodStart":"2030-01-01T00:00:00.000Z","plan":"free","entitlementSource":"free","chat":0,"api":1,"mcp":0,"cloud":0,"ingestion":0,"media":0}}}}},"400":{"description":"Invalid request input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, expired or revoked bearer key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"REST disabled or insufficient read/write permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Companion inactive (companion_inactive) or outside the workspace plan (companion_plan_locked). Activate the companion or restore its plan access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Hourly request limit (rate_limit) or shared plan allowance (usage_limit). Honor Retry-After; GET /usage reports the plan reset. The server-wide IP throttle may instead return plain text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"text/html":{"schema":{"type":"string"}},"text/plain":{"schema":{"type":"string"}}},"headers":{"Retry-After":{"schema":{"type":"string"}},"RateLimit-Limit":{"schema":{"type":"string"}},"RateLimit-Remaining":{"schema":{"type":"string"}},"RateLimit-Reset":{"schema":{"type":"string"}}}},"503":{"description":"Temporarily unavailable. Retry later with the same idempotency key for text creation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"offset","in":"query","schema":{"default":0,"type":"integer","minimum":0,"maximum":1000},"required":false},{"name":"limit","in":"query","schema":{"default":20,"type":"integer","minimum":1,"maximum":20},"required":false}]}},"/api/v1/knowledge/{id}":{"get":{"operationId":"readKnowledge","summary":"Read a knowledge reference","description":"One shared plan unit per page. Reads only the current ready index or readable prior version during refresh. Staged/superseded passages are excluded. Optional URL filters one website page. The reference and passage scope objects report applicability labels; they do not filter this read or authorize access.","tags":["Knowledge API"],"security":[{"CompanionKey":[]}],"responses":{"200":{"description":"Reference and current indexed passages.","content":{"application/json":{"schema":{"type":"object","properties":{"reference":{"$ref":"#/components/schemas/Reference"},"passages":{"type":"array","items":{"$ref":"#/components/schemas/Passage"}},"nextOffset":{"type":"integer","minimum":0,"nullable":true},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["reference","passages","nextOffset","usage"]},"example":{"reference":{"id":"00000000-0000-4000-8000-000000000001","title":"Example returns policy.txt","kind":"text","status":"ready","url":null,"bytes":68,"pages":1,"passages":1,"estimatedTokens":17,"updatedAt":"2030-01-01T12:00:00.000Z","createdVia":"api","scope":{"product":null,"region":null,"audience":null,"language":null}},"passages":[{"id":"example-passage","sourceId":"00000000-0000-4000-8000-000000000001","title":"Example returns policy.txt","text":"Example only: returns are accepted within 30 days with a receipt.","url":null,"page":1,"scope":{"product":null,"region":null,"audience":null,"language":null}}],"nextOffset":null,"usage":{"used":1,"limit":50,"remaining":49,"planLimit":50,"includedUsed":1,"includedRemaining":49,"refillUsed":0,"refillRemaining":0,"resetsAt":"2030-02-01T00:00:00.000Z","period":"month","periodBasis":"calendar_month","periodKey":"free:2030-01-01","periodStart":"2030-01-01T00:00:00.000Z","plan":"free","entitlementSource":"free","chat":0,"api":1,"mcp":0,"cloud":0,"ingestion":0,"media":0}}}}},"400":{"description":"Invalid request input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, expired or revoked bearer key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"REST disabled or insufficient read/write permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Reference absent, excluded or unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Companion inactive (companion_inactive) or outside the workspace plan (companion_plan_locked). Activate the companion or restore its plan access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Hourly request limit (rate_limit) or shared plan allowance (usage_limit). Honor Retry-After; GET /usage reports the plan reset. The server-wide IP throttle may instead return plain text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"text/html":{"schema":{"type":"string"}},"text/plain":{"schema":{"type":"string"}}},"headers":{"Retry-After":{"schema":{"type":"string"}},"RateLimit-Limit":{"schema":{"type":"string"}},"RateLimit-Remaining":{"schema":{"type":"string"}},"RateLimit-Reset":{"schema":{"type":"string"}}}},"503":{"description":"Temporarily unavailable. Retry later with the same idempotency key for text creation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":160}},{"name":"offset","in":"query","schema":{"default":0,"type":"integer","minimum":0,"maximum":1000},"required":false},{"name":"limit","in":"query","schema":{"default":20,"type":"integer","minimum":1,"maximum":20},"required":false},{"name":"url","in":"query","required":false,"schema":{"type":"string","maxLength":2000,"format":"uri"}}]}},"/api/v1/knowledge/search":{"post":{"operationId":"searchKnowledge","summary":"Search indexed knowledge","description":"One shared plan unit. Retrieve up to six relevant passages with direct URLs from global (untagged) sources; this context-free endpoint excludes sources with applicability scopes. Scope is relevance metadata, not access control. No answer generation. This POST reads knowledge and does not create a source.","tags":["Knowledge API"],"security":[{"CompanionKey":[]}],"responses":{"200":{"description":"Relevant passages.","content":{"application/json":{"schema":{"type":"object","properties":{"passages":{"type":"array","items":{"$ref":"#/components/schemas/Passage"},"maxItems":6},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["passages","usage"]},"example":{"passages":[{"id":"example-passage","sourceId":"00000000-0000-4000-8000-000000000001","title":"Example returns policy.txt","text":"Example only: returns are accepted within 30 days with a receipt.","url":null,"page":1,"scope":{"product":null,"region":null,"audience":null,"language":null}}],"usage":{"used":1,"limit":50,"remaining":49,"planLimit":50,"includedUsed":1,"includedRemaining":49,"refillUsed":0,"refillRemaining":0,"resetsAt":"2030-02-01T00:00:00.000Z","period":"month","periodBasis":"calendar_month","periodKey":"free:2030-01-01","periodStart":"2030-01-01T00:00:00.000Z","plan":"free","entitlementSource":"free","chat":0,"api":1,"mcp":0,"cloud":0,"ingestion":0,"media":0}}}}},"400":{"description":"Invalid request input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, expired or revoked bearer key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"REST disabled or insufficient read/write permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Companion inactive (companion_inactive) or outside the workspace plan (companion_plan_locked). Activate the companion or restore its plan access.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Hourly request limit (rate_limit) or shared plan allowance (usage_limit). Honor Retry-After; GET /usage reports the plan reset. The server-wide IP throttle may instead return plain text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"text/html":{"schema":{"type":"string"}},"text/plain":{"schema":{"type":"string"}}},"headers":{"Retry-After":{"schema":{"type":"string"}},"RateLimit-Limit":{"schema":{"type":"string"}},"RateLimit-Remaining":{"schema":{"type":"string"}},"RateLimit-Reset":{"schema":{"type":"string"}}}},"503":{"description":"Temporarily unavailable. Retry later with the same idempotency key for text creation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","minLength":1,"maxLength":2000}},"required":["query"],"additionalProperties":false},"example":{"query":"What is the return policy?"}}}}}},"/api/v1/knowledge/text":{"post":{"operationId":"createTextKnowledge","summary":"Create text knowledge","description":"Requires REST enabled for the workspace and a write-enabled key. Creates real knowledge and queues indexing. One shared plan unit plus any additional ingestion cost. Reuse the same key, title, text and Idempotency-Key for identical retries within 24 hours. Retry returns current status, potentially deleted. Titles are single-line; text cannot contain null bytes. Validation trims title/text.","tags":["Knowledge API"],"security":[{"CompanionKey":[]}],"responses":{"200":{"description":"Identical successful retry; no additional creation plan unit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextResult"},"example":{"id":"00000000-0000-4000-8000-000000000001","status":"ready","replayed":true,"usage":{"used":1,"limit":50,"remaining":49,"planLimit":50,"includedUsed":1,"includedRemaining":49,"refillUsed":0,"refillRemaining":0,"resetsAt":"2030-02-01T00:00:00.000Z","period":"month","periodBasis":"calendar_month","periodKey":"free:2030-01-01","periodStart":"2030-01-01T00:00:00.000Z","plan":"free","entitlementSource":"free","chat":0,"api":1,"mcp":0,"cloud":0,"ingestion":0,"media":0}}}}},"202":{"description":"New source queued for indexing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextResult"},"example":{"id":"00000000-0000-4000-8000-000000000001","status":"queued","replayed":false,"usage":{"used":1,"limit":50,"remaining":49,"planLimit":50,"includedUsed":1,"includedRemaining":49,"refillUsed":0,"refillRemaining":0,"resetsAt":"2030-02-01T00:00:00.000Z","period":"month","periodBasis":"calendar_month","periodKey":"free:2030-01-01","periodStart":"2030-01-01T00:00:00.000Z","plan":"free","entitlementSource":"free","chat":0,"api":1,"mcp":0,"cloud":0,"ingestion":0,"media":0}}}}},"400":{"description":"Invalid request input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid, expired or revoked bearer key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"403":{"description":"REST disabled or insufficient read/write permission.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Companion inactive (companion_inactive) or outside the workspace plan (companion_plan_locked). Activate the companion or restore its plan access. Text creation can also conflict when content differs for the same idempotency key, or the workspace source limit (100) is reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Hourly request limit (rate_limit) or shared plan allowance (usage_limit). Honor Retry-After; GET /usage reports the plan reset. The server-wide IP throttle may instead return plain text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}},"text/html":{"schema":{"type":"string"}},"text/plain":{"schema":{"type":"string"}}},"headers":{"Retry-After":{"schema":{"type":"string"}},"RateLimit-Limit":{"schema":{"type":"string"}},"RateLimit-Remaining":{"schema":{"type":"string"}},"RateLimit-Reset":{"schema":{"type":"string"}}}},"503":{"description":"Temporarily unavailable. Retry later with the same idempotency key for text creation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{8,100}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":120},"text":{"type":"string","minLength":10,"maxLength":50000}},"required":["title","text"],"additionalProperties":false},"example":{"title":"Example returns policy","text":"Example only: returns are accepted within 30 days with a receipt."}}}}}}},"components":{"securitySchemes":{"CompanionKey":{"type":"http","scheme":"bearer","description":"Companion API key from API & MCP. Scoped to one active companion. Never send a key in a URL or public application code."}},"schemas":{"Usage":{"type":"object","properties":{"used":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0},"planLimit":{"type":"integer","minimum":0},"includedUsed":{"type":"integer","minimum":0},"includedRemaining":{"type":"integer","minimum":0},"refillUsed":{"type":"integer","minimum":0},"refillRemaining":{"type":"integer","minimum":0},"chat":{"type":"integer","minimum":0},"api":{"type":"integer","minimum":0},"mcp":{"type":"integer","minimum":0},"cloud":{"type":"integer","minimum":0},"ingestion":{"type":"integer","minimum":0},"media":{"type":"integer","minimum":0},"resetsAt":{"type":"string","format":"date-time"},"period":{"type":"string","enum":["month"]},"periodBasis":{"type":"string"},"periodKey":{"type":"string"},"periodStart":{"type":"string","format":"date-time"},"plan":{"type":"string","enum":["free","basic","pro"]},"entitlementSource":{"type":"string"}},"required":["used","limit","remaining","planLimit","includedUsed","includedRemaining","refillUsed","refillRemaining","chat","api","mcp","cloud","ingestion","media","resetsAt","period","periodBasis","periodKey","periodStart","plan","entitlementSource"]},"RateLimit":{"type":"object","properties":{"limit":{"type":"integer","minimum":0},"windowSeconds":{"type":"integer","minimum":0},"used":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0},"nextAvailableAt":{"type":"string","format":"date-time","nullable":true},"resetSeconds":{"type":"integer","minimum":0}},"required":["limit","windowSeconds","used","remaining","nextAvailableAt","resetSeconds"]},"KnowledgeScope":{"type":"object","properties":{"product":{"type":"string","nullable":true},"region":{"type":"string","nullable":true},"audience":{"type":"string","nullable":true},"language":{"type":"string","nullable":true}},"required":["product","region","audience","language"]},"Reference":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"kind":{"type":"string"},"status":{"type":"string"},"url":{"type":"string","nullable":true},"bytes":{"type":"integer","minimum":0},"pages":{"type":"integer","minimum":0},"passages":{"type":"integer","minimum":0},"estimatedTokens":{"type":"integer","minimum":0},"updatedAt":{"type":"string","format":"date-time"},"createdVia":{"type":"string"},"scope":{"$ref":"#/components/schemas/KnowledgeScope","description":"Applicability metadata for this source. Null values mean the source is global for that dimension. These labels describe intended relevance; they are not access-control boundaries."}},"required":["id","title","kind","status","url","bytes","pages","passages","estimatedTokens","updatedAt","createdVia","scope"]},"Passage":{"type":"object","properties":{"id":{"type":"string"},"sourceId":{"type":"string"},"title":{"type":"string"},"text":{"type":"string"},"url":{"type":"string","nullable":true},"page":{"type":"integer","nullable":true},"scope":{"$ref":"#/components/schemas/KnowledgeScope","description":"Applicability metadata inherited from the passage source. These labels describe intended relevance; they are not access-control boundaries."},"media":{"type":"object","properties":{"type":{"type":"string"},"startSeconds":{"type":"number"},"endSeconds":{"type":"number"}},"required":["type"]}},"required":["id","sourceId","title","text","url","page"]},"TextResult":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"replayed":{"type":"boolean"},"usage":{"$ref":"#/components/schemas/Usage"}},"required":["id","status","replayed","usage"]},"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"retryAfter":{"type":"integer","minimum":0},"nextAvailableAt":{"type":"string","format":"date-time"}},"required":["error","code"]}}}}