{"openapi":"3.1.0","info":{"title":"CanWeChat public API","version":"1.0.0","summary":"Public widget endpoints and outbound webhook event shapes","description":"Integration surface for websites and backends: the public widget loader/API and signed outbound webhooks. Dashboard/session routes under /api/v1 (except /widget/**) are internal to canwechat.dev and are not a partner API.","contact":{"name":"CanWeChat","url":"https://canwechat.dev/contact"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://canwechat.dev","description":"Production"}],"tags":[{"name":"Widget","description":"Public visitor-facing widget endpoints"},{"name":"Webhooks","description":"Outbound signed events to your backend"}],"paths":{"/api/widget.js":{"get":{"tags":["Widget"],"summary":"Widget loader script","description":"Minified IIFE. Load with async and data-site (preferred). data-site-key is accepted as a legacy alias.","responses":{"200":{"description":"JavaScript bundle","content":{"application/javascript":{}}}}}},"/api/v1/widget/config":{"get":{"tags":["Widget"],"summary":"Public widget config","parameters":[{"name":"site","in":"query","required":true,"schema":{"type":"string","example":"pk_live_..."}}],"responses":{"200":{"description":"Widget settings for the site key"}}}},"/api/v1/widget/session":{"post":{"tags":["Widget"],"summary":"Create or resume a visitor session","responses":{"200":{"description":"Visitor session + optional conversation"}}},"patch":{"tags":["Widget"],"summary":"Identify visitor (name/email/user id)","description":"Prefer the JS API CanWeChat.identify from the host page.","responses":{"200":{"description":"Updated session"}}}},"/api/v1/widget/session/page":{"post":{"tags":["Widget"],"summary":"Record current page for the visitor session","responses":{"200":{"description":"Page recorded"}}}},"/api/v1/widget/conversations":{"post":{"tags":["Widget"],"summary":"Start a conversation","responses":{"200":{"description":"Conversation created"}}}},"/api/v1/widget/conversations/{conversationId}/messages":{"post":{"tags":["Widget"],"summary":"Visitor sends a message","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Message created"}}}},"/api/v1/widget/conversations/{conversationId}/read":{"post":{"tags":["Widget"],"summary":"Mark agent replies as read for the visitor","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Read receipt recorded"}}}},"/api/v1/widget/conversations/{conversationId}/socket":{"get":{"tags":["Widget"],"summary":"Visitor realtime WebSocket","parameters":[{"name":"conversationId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"101":{"description":"Switching protocols"}}}}},"components":{"schemas":{"EnvelopeSuccess":{"type":"object","properties":{"ok":{"const":true},"data":{}},"required":["ok","data"]},"EnvelopeError":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"WebhookEvent":{"type":"object","description":"Outbound webhook body from the dashboard webhook relay. Verify HMAC-SHA256 of `${timestamp}.${rawBody}` with the relay secret. Configure the URL in the CanWeChat dashboard — there is no public REST API to manage the relay.","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["message.created","conversation.closed","conversation.reopened"]},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object"}}}}},"externalDocs":{"description":"Widget JS API, webhooks, and AI agent install guide","url":"https://canwechat.dev/docs"}}