{"openapi":"3.1.0","info":{"title":"WuKongIM Product HTTP Runtime API","version":"3.0.0-beta-snapshot","description":"The 43 core Product HTTP JSON operations, plus the plugin-defined ANY route in x-wukongim-extension-routes. Routes have no built-in authentication."},"servers":[{"url":"http://127.0.0.1:5001","description":"Local single-node cluster example"}],"tags":[{"name":"Users","description":"User device metadata, presence, and system identities."},{"name":"Routing","description":"Configured client Gateway addresses."},{"name":"Messages","description":"Message recovery, events, and command-message compatibility."},{"name":"Message Sending","description":"Trusted-backend message submission."},{"name":"Channels","description":"Channel metadata and member-list administration."},{"name":"Conversations","description":"Conversation synchronization and per-user state."}],"x-wukongim-scope":"complete-source-aligned-product-http-runtime","x-wukongim-extension-routes":[{"method":"ANY","path":"/plugins/:plugin_no/*path","description":"Plugin-defined HTTP payloads forwarded through the bounded Route hook; no built-in authentication. Inherits maintenance mode. See the plugin integration guide.","guide":"/en/guide/integration/plugins","max_body_bytes":10485760,"timeout_config":"plugin.timeout"}],"security":[],"paths":{"/route":{"get":{"operationId":"getQuickstartGatewayRoute","summary":"Resolve Gateway addresses","description":"Default external routes complete wildcard listener hosts from Host; explicit addresses win. See [address rules](/en/server/configuration/reference).","tags":["Routing"],"security":[],"x-wukongim-trust":"trusted-backend-only","parameters":[{"$ref":"#/components/parameters/NodeIDSnake"},{"$ref":"#/components/parameters/NodeIDCamel"},{"$ref":"#/components/parameters/NodeIDUpperCamel"},{"$ref":"#/components/parameters/Intranet"}],"responses":{"200":{"$ref":"#/components/responses/RouteOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body http://127.0.0.1:5001/route"}]}},"/route/batch":{"post":{"operationId":"getGatewayRoutesBatch","summary":"Resolve one address group for UIDs","description":"Echoes an unbounded UID array in one address group; retained for compatibility. Address completion follows GET /route.","tags":["Routing"],"deprecated":true,"security":[],"x-wukongim-trust":"trusted-backend-only","parameters":[{"$ref":"#/components/parameters/NodeIDSnake"},{"$ref":"#/components/parameters/NodeIDCamel"},{"$ref":"#/components/parameters/NodeIDUpperCamel"},{"$ref":"#/components/parameters/Intranet"}],"requestBody":{"$ref":"#/components/requestBodies/RouteBatch"},"responses":{"200":{"$ref":"#/components/responses/RouteBatchOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}}}},"/user/token":{"post":{"operationId":"setQuickstartUserToken","summary":"Create or update a device token","description":"Upserts one UID/device token; default Gateway authentication requires later CONNECT credentials for the same UID and device category to match it.","tags":["Users"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/UpdateToken"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/user/token \\\n  --header 'content-type: application/json' \\\n  --data '{\"uid\":\"alice\",\"token\":\"server-generated-development-secret\",\"device_flag\":1,\"device_level\":0}'"}],"x-wukongim-semantics":{"scope":"The token is persisted cluster-wide; for a Master device, the handling node starts closing old sessions after about 10 seconds.","success":"A 200 response means the token write completed, not that old sessions are already closed."}}},"/user/device_quit":{"post":{"operationId":"quitUserDevice","summary":"Clear a user device token","description":"Clears one stored device token and schedules owner-local Session closure; device_flag -1 selects APP, Web, and PC.","tags":["Users"],"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/DeviceQuit"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"The handling node performs session closure after about 2 seconds; device_flag=-1 processes APP, Web, and PC sequentially.","atomicity":"Multi-device sign-out is not transactional; earlier device classes may be signed out before a later one fails.","success":"A missing target device still returns 200."}}},"/user/onlinestatus":{"post":{"operationId":"listUserOnlineStatus","summary":"List active user routes","description":"Returns one row per active authority route; an empty UID array returns the legacy status object instead of an array.","tags":["Users"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/OnlineStatus"},"responses":{"200":{"$ref":"#/components/responses/OnlineStatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}}}},"/user/systemuids_add":{"post":{"operationId":"addSystemUIDs","summary":"Add system UIDs","description":"Persists system identities and adds them to the current process cache.","tags":["Users"],"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/SystemUIDs"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"The UID set is persisted first, then only the handling process permission cache is updated. This request does not refresh other nodes.","recovery":"Refresh the local cache on every server node, or roll the nodes, so effective permission state matches the persisted set."}}},"/user/systemuids_remove":{"post":{"operationId":"removeSystemUIDs","summary":"Remove system UIDs","description":"Removes persisted system identities and current-process cache entries.","tags":["Users"],"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/SystemUIDs"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"UIDs are removed from durable state first, then only from the handling process permission cache.","recovery":"Refresh the local cache on every server node, or roll the nodes."}}},"/user/systemuids":{"get":{"operationId":"listSystemUIDs","summary":"List all system UIDs","description":"Aggregates the complete persisted system UID set into one unbounded response.","tags":["Users"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","responses":{"200":{"$ref":"#/components/responses/SystemUIDListOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Returns the durable system-UID set; it does not prove that every node currently has the same in-memory permission cache."}}},"/user/systemuids_add_to_cache":{"post":{"operationId":"addSystemUIDsToLocalCache","summary":"Add node-local system UID cache entries","description":"Mutates only the current process cache and does not persist or replicate the change.","tags":["Users"],"deprecated":true,"security":[],"x-wukongim-trust":"node-local-operator-only","requestBody":{"$ref":"#/components/requestBodies/SystemUIDs"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Changes only the handling process in-memory cache; it is neither persisted nor broadcast to other nodes."}}},"/user/systemuids_remove_from_cache":{"post":{"operationId":"removeSystemUIDsFromLocalCache","summary":"Remove node-local system UID cache entries","description":"Mutates only the current process cache and does not change durable system identities.","tags":["Users"],"deprecated":true,"security":[],"x-wukongim-trust":"node-local-operator-only","requestBody":{"$ref":"#/components/requestBodies/SystemUIDs"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Changes only the handling process in-memory cache; it is neither persisted nor broadcast to other nodes."}}},"/channel":{"post":{"operationId":"upsertChannel","summary":"Create or update Channel metadata","description":"Upserts all metadata flags and optionally resets subscribers; disband is terminal.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelUpsert"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2,\"reset\":1,\"subscribers\":[\"alice\",\"bob\"]}'"}],"x-wukongim-semantics":{"scope":"Channel metadata and membership are written to cluster storage; large is recomputed from the current member count after membership changes.","atomicity":"Metadata update, old-member removal, chunked member insertion, and large refresh are separate stages, not one transaction.","recovery":"After a timeout or 400/5xx, replay the desired business state and verify membership through the protected Manager query."}}},"/channel/info":{"post":{"operationId":"updateChannelInfo","summary":"Replace Channel metadata","description":"Passes the zero-valued full record to UpdateInfo when fields are omitted; retained for compatibility.","tags":["Channels"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/ChannelInfo"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}}}},"/channel/delete":{"post":{"operationId":"disbandChannel","summary":"Terminally disband a Channel","description":"Sets the durable disband flag without deleting Channel identity; request-key validation is weak.","tags":["Channels"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/WeakChannelKey"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}}}},"/channel/subscriber_add":{"post":{"operationId":"addChannelSubscribers","summary":"Add or replace durable subscribers","description":"Adds non-blank subscribers; channel_type 0 becomes group type 2 and reset=1 replaces the snapshot.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelSubscriberAdd"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/subscriber_add \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2,\"reset\":0,\"temp_subscriber\":0,\"subscribers\":[\"carol\"]}'"}],"x-wukongim-semantics":{"scope":"A missing target Channel is created implicitly; an omitted or zero channel_type is treated as group type 2.","atomicity":"Reset removal, chunked insertion, and large refresh are separate stages and may partially complete."}}},"/channel/subscriber_remove":{"post":{"operationId":"removeChannelSubscribers","summary":"Remove durable subscribers","description":"Removes non-blank subscribers; unlike subscriber_add, channel_type 0 is not normalized.","tags":["Channels"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/ChannelSubscriberRemove"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Removes existing members without implicitly creating the Channel; channel_type=0 is passed through unchanged.","atomicity":"Member removal and large refresh are separate stages and may partially complete."}}},"/channel/subscriber_remove_all":{"post":{"operationId":"removeAllChannelSubscribers","summary":"Remove all durable subscribers","description":"Clears ordinary subscribers through bounded internal pages; person Channels are rejected.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/NonPersonChannelKey"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/subscriber_remove_all \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2}'"}],"x-wukongim-semantics":{"scope":"Clears ordinary subscribers and then refreshes large; person Channels are not supported.","atomicity":"Removal and large refresh are not one transaction."}}},"/tmpchannel/subscriber_set":{"post":{"operationId":"setTemporaryChannelSubscribers","summary":"Replace temporary Channel subscribers","description":"Replaces the derived Type-8 temporary subscriber list; UID elements are not validated by the entry adapter.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/TemporarySubscribers"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/tmpchannel/subscriber_set \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"ephemeral-42\",\"uids\":[\"alice\",\"bob\"]}'"}],"x-wukongim-semantics":{"scope":"Temporary subscribers use full-replacement semantics.","atomicity":"The service removes all members before chunked insertion; failure may leave only part of the new set."}}},"/channel/blacklist_add":{"post":{"operationId":"addChannelDenylistMembers","summary":"Add Channel denylist members","description":"Adds the supplied UID strings to the derived Channel denylist.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelMembers"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/blacklist_add \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2,\"uids\":[\"blocked-user\"]}'"}],"x-wukongim-semantics":{"scope":"The entry does not verify that the parent Channel exists; derived denylist state can be created first and become effective if the parent Channel appears later."}}},"/channel/blacklist_set":{"post":{"operationId":"setChannelDenylistMembers","summary":"Replace Channel denylist members","description":"Removes the old list before adding the supplied values; only channel_id is validated at entry.","tags":["Channels"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/ChannelMemberSet"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"The denylist uses full-replacement semantics.","atomicity":"The list is removed and then inserted; the two stages are not transactional."}}},"/channel/blacklist_remove":{"post":{"operationId":"removeChannelDenylistMembers","summary":"Remove Channel denylist members","description":"Removes the supplied UID strings from the derived Channel denylist.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelMembers"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/blacklist_remove \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2,\"uids\":[\"blocked-user\"]}'"}]}},"/channel/blacklist_remove_all":{"post":{"operationId":"removeAllChannelDenylistMembers","summary":"Remove all Channel denylist members","description":"Clears the derived denylist through bounded internal traversal.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelKey"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/blacklist_remove_all \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2}'"}]}},"/channel/whitelist_add":{"post":{"operationId":"addChannelAllowlistMembers","summary":"Add Channel allowlist members","description":"Adds non-blank UIDs to the derived Channel allowlist.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelAllowlistMembers"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/whitelist_add \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2,\"uids\":[\"moderator\"]}'"}],"x-wukongim-semantics":{"scope":"The entry does not verify that the parent Channel exists; derived allowlist state can be created first and become effective if the parent Channel appears later."}}},"/channel/whitelist_set":{"post":{"operationId":"setChannelAllowlistMembers","summary":"Replace Channel allowlist members","description":"Removes the old list before adding supplied values; only channel_id is validated at entry.","tags":["Channels"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","requestBody":{"$ref":"#/components/requestBodies/ChannelMemberSet"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"The allowlist uses full-replacement semantics.","atomicity":"The list is removed and then inserted; the two stages are not transactional."}}},"/channel/whitelist_remove":{"post":{"operationId":"removeChannelAllowlistMembers","summary":"Remove Channel allowlist members","description":"Removes non-blank UIDs from the derived Channel allowlist.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelAllowlistMembers"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/whitelist_remove \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2,\"uids\":[\"moderator\"]}'"}]}},"/channel/whitelist_remove_all":{"post":{"operationId":"removeAllChannelAllowlistMembers","summary":"Remove all Channel allowlist members","description":"Clears the derived allowlist through bounded internal traversal.","tags":["Channels"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelKey"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend or operator boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/whitelist_remove_all \\\n  --header 'content-type: application/json' \\\n  --data '{\"channel_id\":\"team-42\",\"channel_type\":2}'"}]}},"/channel/whitelist":{"get":{"operationId":"listChannelAllowlistMembers","summary":"List all Channel allowlist members","description":"Returns an unbounded full list; missing or invalid channel_type is silently treated as 0.","tags":["Channels"],"deprecated":true,"security":[],"x-wukongim-trust":"operator-only","parameters":[{"$ref":"#/components/parameters/ChannelIDQuery"},{"$ref":"#/components/parameters/ChannelTypeQuery"}],"responses":{"200":{"$ref":"#/components/responses/ChannelMemberListOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}}}},"/message/send":{"post":{"operationId":"sendChannelMessage","summary":"Submit a message","description":"Accepts the complete compatibility parser, including legacy aliases, transient flags, and request-scoped subscribers; inspect reason on HTTP 200.","tags":["Message Sending"],"security":[],"x-wukongim-trust":"trusted-backend-only","parameters":[{"$ref":"#/components/parameters/TraceID"}],"requestBody":{"$ref":"#/components/requestBodies/SendMessage"},"responses":{"200":{"$ref":"#/components/responses/SendCompleted"},"400":{"$ref":"#/components/responses/SendBadRequest"},"404":{"$ref":"#/components/responses/SendNotFound"},"408":{"$ref":"#/components/responses/SendTimedOut"},"500":{"$ref":"#/components/responses/SendInternalError"},"503":{"$ref":"#/components/responses/SendUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/message/send \\\n  --header 'content-type: application/json' \\\n  --data '{\"from_uid\":\"system\",\"channel_id\":\"alice\",\"channel_type\":1,\"client_msg_no\":\"order-20260828-0001\",\"payload\":\"eyJ0eXBlIjoib3JkZXJfdXBkYXRlIn0=\"}'"}],"x-wukongim-semantics":{"scope":"Messages are submitted by a trusted backend; optional X-WK-Trace-ID must be 32 hexadecimal characters or the server ignores it and generates a new value.","success":"Even with HTTP 200, inspect reason; only a success Reason Code means the message was accepted."}}},"/message/event":{"post":{"operationId":"appendMessageEvent","summary":"Append a message event","description":"Validates and applies one message-scoped event projection; non-null headers are unsupported.","tags":["Messages"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/AppendMessageEvent"},"responses":{"200":{"$ref":"#/components/responses/MessageEventOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"visibility is stored as event metadata; ordinary message synchronization does not use it as an access-control filter; eventsync filters by include_private without checking caller permissions."}}},"/message/eventsync":{"post":{"operationId":"syncMessageEvents","summary":"Synchronize current message event projections","description":"Reads current durable event projections after a sequence cursor, with filtering after a bounded read; not a replayable event log.","tags":["Messages"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/MessageEventSync"},"responses":{"200":{"$ref":"#/components/responses/MessageEventSyncOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Reads current durable lane projections, not complete event history. This entry checks neither caller identity nor membership; include_private is caller-controlled and requires a trusted backend.","success":"Reads limit+1 raw projections before filtering private/restricted entries. A filtered empty page or more=0 does not prove there are no visible projections farther ahead. next_msg_event_seq advances only for returned items."}}},"/message/sync":{"post":{"operationId":"syncCommandMessages","summary":"Synchronize command messages","description":"Returns the latest durable CMD generation; message_seq is accepted but ignored.","tags":["Messages"],"deprecated":true,"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/MessageSync"},"responses":{"200":{"$ref":"#/components/responses/LegacyMessageListOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Messages come from durable storage, but the latest acknowledgement generation is kept only in the handling process memory, by default for about 5 minutes and at most 4,096 UIDs.","success":"limit bounds returned messages, not the total cost of enumerating command Channels and scanning messages.","recovery":"Keep sync and syncack node-affine; run sync again after process restart, expiry, or eviction."}}},"/message/syncack":{"post":{"operationId":"ackCommandMessages","summary":"Acknowledge the latest command sync","description":"Requires a positive last_message_seq but acknowledges the server's latest recorded generation, not that supplied value.","tags":["Messages"],"deprecated":true,"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/MessageSyncAck"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Acknowledgement consumes only the generation recorded by the latest sync in this process; last_message_seq is only validated as positive and is not used for acknowledgement.","success":"If no local generation exists, the endpoint still returns 200 and acknowledges nothing."}}},"/message/cmd/bind":{"post":{"operationId":"bindCommandChannel","summary":"Bind command-channel discovery","description":"Starts bounded recipient discovery after one committed command tail.","tags":["Messages"],"deprecated":true,"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/MessageCMDBinding"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"atomicity":"Choose uid plus source, uids plus source, or subscribers only. At most 1000 raw recipients and a 256 KiB body; subscribers must match SEND order.","success":"Retry preserves live start and ack positions. Cross-Slot failure can be partial; retry the complete batch successfully before SEND.","scope":"Persists discovery binding between a user and a command Channel; later /message/sync acknowledgement still depends on the current-process generation record."}}},"/message/cmd/unbind":{"post":{"operationId":"unbindCommandChannel","summary":"Unbind command-channel discovery","description":"Tombstones bounded recipient discovery without deleting command messages.","tags":["Messages"],"deprecated":true,"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/MessageCMDBinding"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-wukongim-semantics":{"scope":"Uses the same three exclusive forms and 1000-entry/256 KiB bounds as bind; temporary scope order must match SEND.","success":"Cross-Slot failure can be partial; retry the complete batch. Unbinding does not delete messages."}}},"/channel/messagesync":{"post":{"operationId":"syncQuickstartChannelMessages","summary":"Synchronize one Channel's committed messages","description":"Checks membership visibility and returns an ascending page; limit is 100 by default and capped at 10000.","tags":["Messages"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelMessageSync"},"responses":{"200":{"description":"One committed-message page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageSyncResponse"}}},"headers":{"X-WK-Content-Epoch":{"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Successful-restore generation. Invalidate cached comparisons when it increases; discard delayed older generations."}}},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"description":"Temporary read failure or restore maintenance; retry the same query with bounded backoff.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/MaintenanceError"},{"$ref":"#/components/schemas/MessageUpdateError"}]}}}}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/channel/messagesync \\\n  --header 'content-type: application/json' \\\n  --data '{\"login_uid\":\"bob\",\"channel_id\":\"alice\",\"channel_type\":1,\"start_message_seq\":0,\"end_message_seq\":0,\"limit\":100,\"pull_mode\":1,\"include_event_meta\":0,\"event_summary_mode\":\"\"}'"}],"x-wukongim-semantics":{"recovery":"Page reads include latest edits; retry the original query on 503 unavailable. Reset cached version comparisons after a content epoch increase.","scope":"The login_uid must have an ordinary membership before reading; join_seq and deleted_to_seq establish the lowest visible sequence. Returned messages are always ordered by ascending message_seq.","success":"pull_mode=1 reads [start_message_seq, end_message_seq); other values read older messages in (end_message_seq, start_message_seq]. A zero boundary selects the open end."}}},"/channel/messagesyncbatch":{"post":{"operationId":"syncChannelMessagesBatch","summary":"Synchronize up to 200 Channels","description":"Validates all memberships before one aligned batch read; item failures are embedded in the HTTP-200 response.","tags":["Messages"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ChannelMessageSyncBatch"},"responses":{"200":{"description":"Aligned batch result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageSyncBatchResponse"}}},"headers":{"X-WK-Content-Epoch":{"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Successful-restore generation. Invalidate cached comparisons when it increases; discard delayed older generations."}}},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"description":"Content epoch unavailable, restore transition, or restore maintenance; existing per-item batch errors are unchanged.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/MaintenanceError"},{"$ref":"#/components/schemas/MessageUpdateError"}]}}}}},"x-wukongim-semantics":{"scope":"Each items entry runs independently; response order matches request order.","success":"Even with HTTP 200, inspect each item error; one failed item does not make the whole batch non-2xx."}}},"/conversation/list":{"post":{"operationId":"listConversations","summary":"Synchronize a Conversation page","description":"Reads Leader-persisted messages without runtime activation. Failed SENDs may appear. Any read error fails the page; retry the original cursor.","tags":["Conversations"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ConversationList"},"responses":{"200":{"description":"Canonical Conversation page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListResponse"}}},"headers":{"X-WK-Content-Epoch":{"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Successful-restore generation. Invalidate cached comparisons when it increases; discard delayed older generations."}}},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"500":{"description":"Channel or storage read failed; no partial page or cursor is returned.","content":{"application/json":{"schema":{"type":"object","properties":{"msg":{"type":"string"},"status":{"type":"integer"}}}}}},"503":{"description":"Temporary read failure or restore maintenance; retry the same query with bounded backoff.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/MaintenanceError"},{"$ref":"#/components/schemas/MessageUpdateError"}]}}}}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/conversation/list \\\n  --header 'content-type: application/json' \\\n  --data '{\"uid\":\"alice\",\"cursor\":\"\",\"limit\":50,\"completed_coverage\":0}'"}],"x-wukongim-semantics":{"recovery":"Previews include the latest tail edit; preserve the cursor on 503 unavailable. Content edits do not change conversation order or unread.","scope":"limit bounds membership rows scanned, not the number of returned conversations; tombstones go to deletes. Previews use Leader-persisted data without runtime activation. Any read failure fails the whole page; retry the original request and cursor.","success":"Only done=true completes a full pass and permits saving coverage; reset_required=true requires rebuilding the local Conversation directory."}}},"/conversation/sync":{"post":{"operationId":"syncConversationsLegacy","summary":"Synchronize legacy Conversations","description":"Read persisted heads and recents without Channel activation. Failed SENDs may appear; any read error fails the request. Legacy fields and cursors are preserved.","tags":["Conversations"],"deprecated":true,"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ConversationSyncLegacy"},"responses":{"200":{"description":"Bare legacy Conversation array","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationSyncLegacyItem"}}}},"headers":{"X-WK-Content-Epoch":{"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Successful-restore generation. Invalidate cached comparisons when it increases; discard delayed older generations."}}},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"description":"Temporary read failure or restore maintenance; retry the same query with bounded backoff.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/MaintenanceError"},{"$ref":"#/components/schemas/MessageUpdateError"}]}}}}},"x-wukongim-semantics":{"scope":"Recents contain the latest edits; an edited tail is returned again even when last_msg_seqs is caught up. Merge by message ID and version.","success":"The legacy array, conversation version, unread, ordering, only_unread and msg_count=0 behavior are preserved.","recovery":"Transient reads return 503 unavailable; preserve the request and cache and retry with backoff. Reset message version comparisons when the content epoch increases."}}},"/conversations/clearUnread":{"post":{"operationId":"clearConversationUnread","summary":"Clear Conversation unread","description":"Advances read_seq to the current committed head; unknown legacy fields such as message_seq are ignored.","tags":["Conversations"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ConversationMutation"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/conversations/clearUnread \\\n  --header 'content-type: application/json' \\\n  --data '{\"uid\":\"alice\",\"channel_id\":\"team-42\",\"channel_type\":2}'"}]}},"/conversations/setUnread":{"post":{"operationId":"setConversationUnread","summary":"Set maximum Conversation unread","description":"Monotonically advances read_seq so no more than unread messages remain.","tags":["Conversations"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ConversationSetUnread"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/conversations/setUnread \\\n  --header 'content-type: application/json' \\\n  --data '{\"uid\":\"alice\",\"channel_id\":\"team-42\",\"channel_type\":2,\"unread\":3}'"}]}},"/conversations/delete":{"post":{"operationId":"hideConversation","summary":"Hide Conversation through the current head","description":"Advances deleted_to_seq to the current committed head without deleting Channel membership.","tags":["Conversations"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ConversationMutation"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/conversations/delete \\\n  --header 'content-type: application/json' \\\n  --data '{\"uid\":\"alice\",\"channel_id\":\"team-42\",\"channel_type\":2}'"}]}},"/conversations/activate":{"post":{"operationId":"activateConversation","summary":"Activate a Conversation","description":"Records an explicit open, switch, or resume action for ordering; message paths do not activate it.","tags":["Conversations"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/ConversationMutation"},"responses":{"200":{"$ref":"#/components/responses/StatusOK"},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"$ref":"#/components/responses/MaintenanceUnavailable"}},"x-codeSamples":[{"lang":"bash","label":"Trusted backend (cURL)","source":"# Run only from the trusted backend boundary.\ncurl --fail-with-body \\\n  --request POST \\\n  --url http://127.0.0.1:5001/conversations/activate \\\n  --header 'content-type: application/json' \\\n  --data '{\"uid\":\"alice\",\"channel_id\":\"team-42\",\"channel_type\":2}'"}]}},"/messages":{"post":{"operationId":"lookupMessages","summary":"Look up exact committed messages","description":"Looks up exact committed messages within membership visibility; selector, result and scan limits fail without partial results.","tags":["Messages"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/MessageLookup"},"responses":{"200":{"description":"One committed-message page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageSyncResponse"}}},"headers":{"X-WK-Content-Epoch":{"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Successful-restore generation. Invalidate cached comparisons when it increases; discard delayed older generations."}}},"400":{"$ref":"#/components/responses/CompatibilityBadRequest"},"503":{"description":"Temporary read failure or restore maintenance; retry the same query with bounded backoff.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/MaintenanceError"},{"$ref":"#/components/schemas/MessageUpdateError"}]}}}}},"x-wukongim-semantics":{"atomicity":"Content includes latest edits; temporary reads fail as 503 unavailable without partial messages.","scope":"Reads exact message indexes within current membership visibility, without a recent-history scan fallback.","success":"Selectors form a union ordered and deduplicated by sequence; exhaustion or any failed read returns no partial result.","recovery":"Every node must support the indexed-read RPC; older nodes reject it explicitly."}}},"/message/update":{"post":{"operationId":"updateMessage","summary":"Replace a message payload","description":"Replaces an ordinary retained payload with version and restore-epoch checks. CMD, stream and nonpersistent messages cannot be edited.","tags":["Messages"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/UpdateMessage"},"responses":{"200":{"description":"Success","headers":{"X-WK-Content-Epoch":{"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Successful-restore generation. Invalidate cached comparisons when it increases; discard delayed older generations."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMessageResponse"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"403":{"description":"channel_not_accessible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"404":{"description":"message_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"409":{"description":"version_conflict, content_epoch_conflict, idempotency_conflict, reset_required or stale_meta","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"422":{"description":"message_not_updatable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"429":{"description":"resource_exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"503":{"description":"Temporary dependency failure or restore maintenance","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/MaintenanceError"},{"$ref":"#/components/schemas/MessageUpdateError"}]}}}}},"x-wukongim-semantics":{"scope":"The backend owns editing permissions and time windows; message ID, sequence, original timestamp, unread and ordering stay unchanged.","success":"200 means the edit and idempotency result were quorum committed and applied by the Slot; it does not wait for devices.","recovery":"Retry uncertain outcomes with identical request_id, version, content epoch and payload. After a version or epoch conflict, reload and make a new editing decision."}}},"/channel/messageupdates":{"post":{"operationId":"syncMessageUpdates","summary":"Pull edits for one channel","description":"Bootstrap with an empty cursor before loading history. Drain more pages and merge versions with the cursor atomically; this feed returns latest states.","tags":["Messages"],"security":[],"x-wukongim-trust":"trusted-backend-only","requestBody":{"$ref":"#/components/requestBodies/MessageUpdates"},"responses":{"200":{"description":"Success","headers":{"X-WK-Content-Epoch":{"schema":{"type":"string","pattern":"^[0-9]+$"},"description":"Successful-restore generation. Invalidate cached comparisons when it increases; discard delayed older generations."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdatesResponse"}}}},"400":{"description":"invalid_request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"403":{"description":"channel_not_accessible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"404":{"description":"message_not_found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"409":{"description":"version_conflict, content_epoch_conflict, idempotency_conflict, reset_required or stale_meta","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"422":{"description":"message_not_updatable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"429":{"description":"resource_exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdateError"}}}},"503":{"description":"Temporary dependency failure or restore maintenance","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/MaintenanceError"},{"$ref":"#/components/schemas/MessageUpdateError"}]}}}}},"x-wukongim-semantics":{"scope":"Synchronize the currently viewed channel on entry, reconnect or resume; this endpoint does not discover updates for all conversations.","success":"Obtain a baseline before loading visible history; continue while more=true even when updates is empty. Merge messages and cursor transactionally; an older message edit must not replace a newer tail preview.","recovery":"On reset_required=true, reload visible history from the new baseline; on 503, preserve the cursor and retry with backoff. Discard delayed responses from older content epochs."}}}},"components":{"parameters":{"NodeIDSnake":{"name":"node_id","in":"query","required":false,"description":"Preferred node selector; when supplied it must identify a configured node with an ID greater than 0.","schema":{"type":"integer","format":"uint64","minimum":1}},"NodeIDCamel":{"name":"nodeId","in":"query","required":false,"deprecated":true,"description":"Legacy nodeId alias, read only when node_id is absent.","schema":{"type":"integer","format":"uint64","minimum":1}},"NodeIDUpperCamel":{"name":"nodeID","in":"query","required":false,"deprecated":true,"description":"Legacy nodeID alias, read only when both node_id and nodeId are absent.","schema":{"type":"integer","format":"uint64","minimum":1}},"Intranet":{"name":"intranet","in":"query","required":false,"description":"Address-scope selector; any parseable non-zero integer selects intranet addresses, while invalid text behaves as 0 and selects public addresses.","schema":{"type":"integer","default":0}},"ChannelIDQuery":{"name":"channel_id","in":"query","required":false,"description":"Channel ID whose allowlist is read; this legacy endpoint does not validate the query parameter.","schema":{"type":"string","default":""}},"ChannelTypeQuery":{"name":"channel_type","in":"query","required":false,"description":"Channel type whose allowlist is read; parsed as uint8, with missing, invalid, or out-of-range text silently treated as 0.","schema":{"type":"integer","minimum":0,"maximum":255,"default":0}},"TraceID":{"name":"X-WK-Trace-ID","in":"header","required":false,"description":"Optional 32-character hexadecimal trace ID; an invalid value is ignored and replaced with a generated ID.","schema":{"type":"string","pattern":"^[0-9a-fA-F]{32}$"}}},"requestBodies":{"RouteBatch":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteBatchRequest"}}},"description":"JSON array of UIDs whose route group is requested."},"UpdateToken":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTokenRequest"}}},"description":"User, device, and token metadata to store."},"DeviceQuit":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceQuitRequest"}}},"description":"User and device category to sign out."},"OnlineStatus":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnlineStatusRequest"}}},"description":"JSON array of UIDs whose active routes are queried."},"SystemUIDs":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemUIDsRequest"}}},"description":"UID set used by the current system-identity mutation."},"ChannelInfo":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelInfoRequest"}}},"description":"Channel metadata to replace in full; every field preserves legacy zero-value behavior."},"ChannelUpsert":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelUpsertRequest"}}},"description":"Channel metadata to create or update plus an optional subscriber snapshot."},"WeakChannelKey":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WeakChannelKeyRequest"}}},"description":"Legacy, weakly validated Channel key."},"ChannelSubscriberAdd":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelSubscriberAddRequest"}}},"description":"Ordinary subscribers to add or replace."},"ChannelSubscriberRemove":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelSubscriberRemoveRequest"}}},"description":"Ordinary subscribers to remove."},"NonPersonChannelKey":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NonPersonChannelKeyRequest"}}},"description":"Non-person Channel key whose subscribers are cleared."},"TemporarySubscribers":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemporarySubscriberSetRequest"}}},"description":"Temporary Channel ID and replacement UID set."},"ChannelMembers":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMemberMutationRequest"}}},"description":"Denylist members to add or remove."},"ChannelMemberSet":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMemberSetRequest"}}},"description":"Complete allowlist or denylist snapshot to write."},"ChannelAllowlistMembers":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelAllowlistMutationRequest"}}},"description":"Allowlist members to add or remove."},"ChannelKey":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelKeyRequest"}}},"description":"Channel key whose derived member list is cleared."},"SendMessage":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageRequest"}}},"description":"Message and delivery options submitted by the trusted backend."},"MessageEventSync":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageEventSyncRequest"}}},"description":"Message event identity, sequence cursor, and filters to read."},"AppendMessageEvent":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendMessageEventRequest"}}},"description":"Event to project onto one message."},"MessageSync":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageSyncRequest"}}},"description":"User and page limit for command-message synchronization."},"MessageSyncAck":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageSyncAckRequest"}}},"description":"User acknowledging the latest command-message generation."},"MessageCMDBinding":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageCMDBindingRequest"}}},"description":"Persistent discovery binding between a user and command Channel."},"ChannelMessageSync":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageSyncRequest"}}},"description":"Committed-message read criteria for one Channel."},"ChannelMessageSyncBatch":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageSyncBatchRequest"}}},"description":"One user and message-read criteria for up to 200 Channels."},"ConversationList":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListRequest"}}},"description":"Conversation-directory pagination and deletion-coverage inputs."},"ConversationMutation":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationMutationRequest"}}},"description":"User Conversation key to clear, hide, or activate."},"ConversationSetUnread":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationSetUnreadRequest"}}},"description":"User Conversation key and maximum unread count to retain."},"ConversationSyncLegacy":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationSyncLegacyRequest"}}},"description":"Cursor, filter, and pagination inputs for legacy Conversation sync."},"MessageLookup":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageLookupRequest"}}}},"UpdateMessage":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateMessageRequest"},"example":{"login_uid":"alice","channel_id":"bob","channel_type":1,"message_id":"12345","expected_version":"0","expected_content_epoch":"0","request_id":"5893e137-1994-4377-b4ed-1f0c9e8fe4bd","payload":"bmV3"}}},"description":"Replaces an ordinary retained payload with version and restore-epoch checks. CMD, stream and nonpersistent messages cannot be edited."},"MessageUpdates":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageUpdatesRequest"},"example":{"login_uid":"bob","channel_id":"alice","channel_type":1,"update_cursor":"","limit":100}}},"description":"Bootstrap with an empty cursor before loading history. Drain more pages and merge versions with the cursor atomically; this feed returns latest states."}},"responses":{"StatusOK":{"description":"Mutation accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusEnvelope"}}}},"CompatibilityBadRequest":{"description":"Input, validation, dependency, or downstream error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompatibilityError"}}}},"MaintenanceUnavailable":{"description":"Controller restore maintenance is active","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaintenanceError"}}}},"RouteOK":{"description":"Selected Gateway addresses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"RouteBatchOK":{"description":"One selected address group","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteBatchResponse"}}}},"OnlineStatusOK":{"description":"Active routes or the empty-request status object","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnlineStatusResponse"}}}},"SystemUIDListOK":{"description":"Complete system UID list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemUIDListResponse"}}}},"ChannelMemberListOK":{"description":"Complete legacy allowlist member array","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMemberListResponse"}}}},"SendCompleted":{"description":"Transport completed; inspect reason","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendMessageResponse"}}}},"SendBadRequest":{"description":"Invalid request or payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendError"}}}},"SendNotFound":{"description":"Channel not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendError"}}}},"SendTimedOut":{"description":"Request cancelled or timed out","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendError"}}}},"SendInternalError":{"description":"Unmapped send failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendError"}}}},"SendUnavailable":{"description":"Retry-required routing failure or restore maintenance","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/RetryRequiredError"},{"$ref":"#/components/schemas/MaintenanceError"}]}}}},"MessageEventSyncOK":{"description":"Current durable event projections","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageEventSyncResponse"}}}},"MessageEventOK":{"description":"Applied event projection","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendMessageEventResponse"}}}},"LegacyMessageListOK":{"description":"Bare legacy message array","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LegacyMessage"}}}}},"ChannelMessageSyncOK":{"description":"One committed-message page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageSyncResponse"}}}},"ChannelMessageSyncBatchOK":{"description":"Aligned batch result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelMessageSyncBatchResponse"}}}},"ConversationListOK":{"description":"Canonical Conversation page","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationListResponse"}}}},"ConversationSyncLegacyOK":{"description":"Bare legacy Conversation array","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ConversationSyncLegacyItem"}}}}}},"schemas":{"StatusEnvelope":{"type":"object","additionalProperties":false,"required":["status"],"properties":{"status":{"type":"integer","const":200,"description":"Application-level status fixed at 200."}},"description":"Legacy mutation-success response."},"CompatibilityError":{"type":"object","additionalProperties":false,"required":["msg","status"],"properties":{"msg":{"type":"string","description":"Human-readable error text with no stability guarantee; do not branch on it."},"status":{"type":"integer","const":400,"description":"Application-level status fixed at 400."}},"description":"HTTP 400 error body shared by multiple legacy entries."},"MaintenanceError":{"type":"object","additionalProperties":false,"required":["error","message"],"properties":{"error":{"type":"string","const":"maintenance","description":"Stable maintenance error category."},"message":{"type":"string","const":"restore maintenance is active","description":"Current restore-maintenance message."}},"description":"503 error body returned while cluster restore maintenance is active."},"RouteResponse":{"type":"object","additionalProperties":false,"required":["tcp_addr","ws_addr","wss_addr"],"properties":{"tcp_addr":{"type":"string","description":"WKProto TCP ingress address."},"ws_addr":{"type":"string","description":"Non-TLS WebSocket ingress address."},"wss_addr":{"type":"string","description":"TLS WebSocket ingress address."}},"description":"Client ingress addresses for the selected Gateway."},"RouteBatchRequest":{"type":["array","null"],"description":"Array of UID strings; JSON null is also accepted as an empty array, and the current entry does not bound its size.","items":{"type":"string"}},"RouteBatchItem":{"type":"object","additionalProperties":false,"required":["tcp_addr","ws_addr","wss_addr"],"properties":{"tcp_addr":{"type":"string","description":"WKProto TCP ingress address."},"ws_addr":{"type":"string","description":"Non-TLS WebSocket ingress address."},"wss_addr":{"type":"string","description":"TLS WebSocket ingress address."},"uids":{"type":"array","items":{"type":"string"},"description":"UIDs assigned to this address set; compatibility responses may omit it."}},"description":"A group of UIDs sharing one Gateway address set."},"RouteBatchResponse":{"type":"array","items":{"$ref":"#/components/schemas/RouteBatchItem"}},"UpdateTokenRequest":{"type":"object","additionalProperties":true,"required":["uid","token"],"properties":{"uid":{"type":"string","minLength":1,"description":"User ID whose device token is created or updated; it must not contain @, #, or &."},"token":{"type":"string","minLength":1,"description":"Opaque token persisted for this user and device category; the default Gateway requires later CONNECT credentials to match it exactly."},"device_flag":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Device category; 0=APP, 1=Web, 2=PC, and 99=system, defaulting to 0 when omitted."},"device_level":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Same-category device conflict level; 0=Slave and 1=Master, defaulting to 0 when omitted."}},"description":"Device-token update parameters."},"DeviceQuitRequest":{"type":"object","additionalProperties":true,"properties":{"uid":{"type":"string","default":"","description":"User ID whose device is signed out; the entry itself does not reject an empty value."},"device_flag":{"type":"integer","default":0,"description":"Device category to sign out; -1 selects APP, Web, and PC together, while other integers are converted to uint8 by the use case."}},"description":"Device sign-out parameters with legacy weak validation."},"OnlineStatusRequest":{"type":["array","null"],"description":"Array of UID strings; JSON null or an empty array returns the legacy status object, and the current entry does not bound its size.","items":{"type":"string"}},"UserOnlineStatus":{"type":"object","additionalProperties":false,"required":["uid","device_flag","online"],"properties":{"uid":{"type":"string","description":"Unique identifier of the target user."},"device_flag":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Online device category."},"online":{"type":"integer","const":1,"description":"Fixed at 1 to indicate that this route is online."}},"description":"One active authoritative device route for a user."},"OnlineStatusResponse":{"oneOf":[{"$ref":"#/components/schemas/StatusEnvelope"},{"type":"array","items":{"$ref":"#/components/schemas/UserOnlineStatus"}}]},"SystemUIDsRequest":{"type":"object","additionalProperties":true,"properties":{"uids":{"type":["array","null"],"description":"System UIDs to add or remove; the field may be omitted, empty, or null, and elements are not validated at entry.","items":{"type":"string"}}},"description":"System-identity mutation parameters."},"SystemUIDListResponse":{"type":["array","null"],"items":{"type":"string"}},"CompatibilityFlag":{"type":"integer","default":0,"description":"Legacy integer boolean; exactly 1 means true and every other integer means false."},"ChannelInfoRequest":{"type":"object","additionalProperties":true,"properties":{"channel_id":{"type":"string","default":"","description":"Channel ID to update; omission produces an empty string and the entry does not validate it."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Channel type to update; omission produces 0 and the entry does not validate it."},"large":{"type":"integer","default":0,"description":"Large-group compatibility flag; exactly 1 enables it and every other integer disables it."},"ban":{"type":"integer","default":0,"description":"Channel-ban compatibility flag; exactly 1 enables it and every other integer disables it."},"disband":{"type":"integer","default":0,"description":"Terminal-disband compatibility flag; exactly 1 enables it and every other integer disables it."},"send_ban":{"type":"integer","default":0,"description":"Send-ban compatibility flag; exactly 1 enables it and every other integer disables it."},"allow_stranger":{"type":"integer","default":0,"description":"Allow-stranger compatibility flag; exactly 1 enables it and every other integer disables it."}},"description":"Legacy Channel metadata with no required fields and full zero-value replacement semantics."},"ChannelUpsertRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type"],"properties":{"channel_id":{"type":"string","minLength":1,"pattern":"^(?!.*[#@])(?=.*\\S).+$","description":"Non-blank Channel ID to create or update; it must not contain # or @."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"large":{"type":"integer","default":0,"description":"Large-group compatibility flag; exactly 1 enables it and every other integer disables it."},"ban":{"type":"integer","default":0,"description":"Channel-ban compatibility flag; exactly 1 enables it and every other integer disables it."},"disband":{"type":"integer","default":0,"description":"Terminal-disband compatibility flag; exactly 1 enables it and every other integer disables it."},"send_ban":{"type":"integer","default":0,"description":"Send-ban compatibility flag; exactly 1 enables it and every other integer disables it."},"allow_stranger":{"type":"integer","default":0,"description":"Allow-stranger compatibility flag; exactly 1 enables it and every other integer disables it."},"reset":{"type":"integer","default":0,"description":"Subscriber-snapshot replacement compatibility flag; exactly 1 enables it and every other integer disables it."},"subscribers":{"type":["array","null"],"description":"Ordinary subscriber UIDs to add; it may be omitted, empty, or null, a person Channel rejects a non-empty list, and elements are not validated at entry.","items":{"type":"string"}}},"allOf":[{"if":{"required":["channel_type"],"properties":{"channel_type":{"const":1}}},"then":{"properties":{"subscribers":{"not":{"type":"array","minItems":1}}}}}],"description":"Full Channel metadata update plus optional subscriber replacement parameters."},"WeakChannelKeyRequest":{"type":"object","additionalProperties":true,"properties":{"channel_id":{"type":"string","default":"","description":"Channel ID to disband; omission produces an empty string and the entry does not validate it."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Channel type to disband; 1 is rejected while every other value, including 0, is passed to the use case."}},"description":"Compatibility Channel key with deliberately weak validation."},"ChannelSubscriberAddRequest":{"type":"object","additionalProperties":true,"required":["channel_id","subscribers"],"properties":{"channel_id":{"type":"string","minLength":1,"pattern":"^(?!.*[#@])(?=.*\\S).+$","description":"Target non-blank Channel ID; it must not contain # or @."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":2,"not":{"const":1},"description":"Target Channel type; omission or 0 becomes group type 2, while type 1 is rejected."},"reset":{"type":"integer","default":0,"description":"Subscriber-snapshot replacement compatibility flag; exactly 1 enables it and every other integer disables it."},"temp_subscriber":{"type":"integer","not":{"const":1},"description":"Deprecated temporary-subscriber flag; value 1 is rejected and every other value is ignored."},"subscribers":{"type":"array","minItems":1,"items":{"type":"string","minLength":1,"pattern":"\\S"},"description":"One or more non-blank subscriber UIDs to add."}},"description":"Ordinary-subscriber add or replacement parameters."},"ChannelSubscriberRemoveRequest":{"type":"object","additionalProperties":true,"required":["channel_id","subscribers"],"properties":{"channel_id":{"type":"string","minLength":1,"pattern":"^(?!.*[#@])(?=.*\\S).+$","description":"Target non-blank Channel ID; it must not contain # or @."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"not":{"const":1},"description":"Target Channel type; type 1 is rejected, while omission or 0 is passed through without normalization."},"reset":{"type":"integer","default":0,"description":"Integer flag accepted for compatibility but not used by the removal operation."},"temp_subscriber":{"type":"integer","description":"Legacy temporary-subscriber flag accepted and ignored for compatibility."},"subscribers":{"type":"array","minItems":1,"items":{"type":"string","minLength":1,"pattern":"\\S"},"description":"One or more non-blank subscriber UIDs to remove."}},"description":"Ordinary-subscriber removal parameters."},"NonPersonChannelKeyRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type"],"properties":{"channel_id":{"type":"string","minLength":1,"description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":2,"maximum":255,"description":"Non-person Channel type, so the accepted range is 2–255."}},"description":"Non-person Channel key."},"TemporarySubscriberSetRequest":{"type":"object","additionalProperties":true,"required":["channel_id","uids"],"properties":{"channel_id":{"type":"string","minLength":1,"pattern":"^[^#@]+$","description":"Temporary Channel ID; it must not be empty or contain # or @."},"uids":{"type":"array","minItems":1,"items":{"type":"string"},"description":"Replacement temporary-subscriber UIDs; at least one is required and entry does not validate element content."}},"description":"Complete temporary-subscriber snapshot."},"ChannelMemberMutationRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type","uids"],"properties":{"channel_id":{"type":"string","minLength":1,"description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"uids":{"type":"array","minItems":1,"items":{"type":"string"},"description":"One or more UIDs to add or remove; entry does not validate element content."}},"description":"Denylist add or remove parameters."},"ChannelMemberSetRequest":{"type":"object","additionalProperties":true,"required":["channel_id"],"properties":{"channel_id":{"type":"string","minLength":1,"pattern":"\\S","description":"Target non-blank Channel ID."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Target Channel type; it may be omitted or 0 and is not rejected at entry."},"uids":{"type":["array","null"],"items":{"type":"string"},"description":"Complete replacement UID set; it may be omitted, empty, or null, and elements are not validated at entry."}},"description":"Complete allowlist or denylist replacement parameters with legacy weak validation."},"ChannelAllowlistMutationRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type","uids"],"properties":{"channel_id":{"type":"string","minLength":1,"pattern":"^[^#@]+$","description":"Target Channel ID; it must not be empty or contain # or @."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"uids":{"type":"array","minItems":1,"items":{"type":"string","minLength":1,"pattern":"\\S"},"description":"One or more non-blank UIDs to add or remove."}},"description":"Allowlist add or remove parameters."},"ChannelKeyRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type"],"properties":{"channel_id":{"type":"string","minLength":1,"description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."}},"description":"Channel key with basic validation."},"ChannelMember":{"type":"object","additionalProperties":false,"required":["id","uid"],"properties":{"id":{"type":"integer","format":"uint64","minimum":0,"description":"Internal member-record ID; do not use it as the UID."},"uid":{"type":"string","description":"Unique identifier of the target user."}},"description":"Member in the legacy allowlist response."},"ChannelMemberListResponse":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMember"}},"SendMessageHeaderRequest":{"type":"object","additionalProperties":true,"properties":{"red_dot":{"type":"integer","default":0,"description":"Non-zero preserves the message red-dot flag; omitted means 0. There is no top-level red_dot alias."},"no_persist":{"type":"integer","default":0,"description":"A non-zero value makes the message non-durable."},"sync_once":{"type":"integer","default":0,"description":"A non-zero value treats the message as a one-shot command message."}},"description":"Compatibility flags for the message fixed header; same-named top-level no_persist and sync_once fields are ORed with the header values."},"SendMessageRequest":{"type":"object","additionalProperties":true,"required":["payload"],"allOf":[{"if":{"required":["subscribers"],"properties":{"subscribers":{"type":"array","minItems":1}}},"then":{"properties":{"channel_id":{"maxLength":0}},"anyOf":[{"required":["sync_once"],"properties":{"sync_once":{"not":{"const":0}}}},{"required":["header"],"properties":{"header":{"type":"object","required":["sync_once"],"properties":{"sync_once":{"not":{"const":0}}}}}}]},"else":{"required":["channel_id","channel_type"],"properties":{"channel_id":{"minLength":1},"channel_type":{"minimum":1}}}}],"properties":{"from_uid":{"type":"string","description":"Message sender UID; when empty, sender_uid is consulted, and when both are empty the system account configured by message.system_uid is used."},"sender_uid":{"type":"string","deprecated":true,"description":"Deprecated sender-UID alias used only when from_uid is empty; when both are empty, the configured system account is used."},"device_id":{"type":"string","description":"Caller-supplied sending-device identifier; it may be empty."},"channel_id":{"type":"string","description":"Target Channel ID; required for an ordinary send and required to be empty for a request-scoped subscribers send."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Target Channel type; it must be greater than 0 for an ordinary send and is 0 for a request-scoped subscribers send."},"client_msg_no":{"type":"string","description":"Optional client idempotency key; omitted or blank values generate a unique number returned in the response. Reuse an explicit key when retrying the same message."},"setting":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"WKProto Setting bitset; combine SDK constants instead of writing unknown bits by hand."},"topic":{"type":"string","description":"Optional Topic; it has protocol meaning only when the matching Setting bit and client capability are present."},"expire":{"type":"integer","format":"uint32","minimum":0,"description":"Caller-supplied message expiration in seconds; 0 means no expiration is set."},"payload":{"type":"string","minLength":1,"contentEncoding":"base64","description":"Base64-encoded message payload; decoding failure returns 400."},"subscribers":{"type":["array","null"],"description":"Request-scoped delivery UIDs; when non-empty, channel_id must be empty and sync_once must be enabled; the field may be omitted, empty, or null.","items":{"type":"string"}},"header":{"oneOf":[{"$ref":"#/components/schemas/SendMessageHeaderRequest"},{"type":"null"}],"description":"Optional compatibility header flags; it may be an object, null, or omitted."},"no_persist":{"type":"integer","default":0,"description":"Top-level compatibility flag; non-zero means non-durable and is ORed with header.no_persist."},"sync_once":{"type":"integer","default":0,"description":"Top-level compatibility flag; non-zero means a one-shot command message and is ORed with header.sync_once."}},"description":"Complete compatibility message-send parameters."},"SendMessageResponse":{"type":"object","additionalProperties":false,"required":["message_id","message_seq","reason","client_msg_no"],"properties":{"message_id":{"type":"integer","format":"int64","description":"Server message ID; JavaScript must parse it without losing int64 precision."},"message_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Sequence of this message within the target Channel; JavaScript must parse it without losing uint64 precision."},"reason":{"type":"integer","format":"uint8","enum":[1,2,3,4,5,9,11,13,15,18,19,24,25],"description":"WKProto Reason Code; HTTP 200 does not replace this success check."},"client_msg_no":{"type":"string","description":"Client message number submitted with this send; generated by the server when omitted."}},"description":"Completed message-send transport response; reason still requires inspection."},"SendError":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"string","description":"Human-readable diagnostic text; do not match the full text."}},"description":"HTTP error body for message sending."},"RetryRequiredError":{"type":"object","additionalProperties":false,"required":["error"],"properties":{"error":{"type":"string","const":"retry required","description":"Fixed at retry required."}},"description":"Send error requiring re-routing before retry."},"MessageEventSyncRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type","client_msg_no"],"properties":{"channel_id":{"type":"string","pattern":"\\S","description":"Non-blank Channel ID; a person channel with non-blank from_uid is normalized using both UIDs."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Channel type in the range 1–255."},"from_uid":{"type":"string","description":"Optional sender UID used only for person-channel normalization, not an authenticated identity."},"client_msg_no":{"type":"string","pattern":"\\S","description":"Non-blank client message number of the parent message."},"event_key":{"type":"string","description":"Optional event-lane filter; empty reads all lanes."},"from_msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"default":0,"description":"Exclusive sequence boundary; read only current projections after this value, default 0."},"limit":{"type":"integer","minimum":0,"default":0,"description":"Omit or use 0 for 200; negative values are rejected and values above 2000 are capped at 2000."},"include_private":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Exactly 1 includes private/restricted projections; other uint8 values filter them. This switch is not an authorization check."}},"description":"Read parameters for current durable message event projections; membership is not checked."},"SyncedMessageEvent":{"type":"object","additionalProperties":false,"required":["msg_event_seq","event_id","event_key","event_type","visibility","occurred_at"],"properties":{"msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Latest event sequence of the projection."},"event_id":{"type":"string","description":"Latest event ID."},"event_key":{"type":"string","description":"Event lane key."},"event_type":{"type":"string","description":"Latest event type; a blank original value returns stream.snapshot."},"visibility":{"type":"string","description":"Visibility string stored with the projection."},"occurred_at":{"type":"integer","format":"int64","description":"Original event time value stored with the projection."},"payload":{"description":"Snapshot JSON value; non-JSON bytes become a string, and a missing snapshot uses an object with status/end_reason and optional error."}},"description":"Current projection of one event lane, not every historical event."},"MessageEventSyncData":{"type":"object","additionalProperties":false,"required":["client_msg_no","from_msg_event_seq","next_msg_event_seq","more","events","filtered_by_event_key"],"properties":{"client_msg_no":{"type":"string","description":"Requested client message number."},"from_msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Echoed request starting cursor."},"next_msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Sequence of the last returned projection; unchanged from the input cursor when no items are returned."},"more":{"type":"integer","enum":[0,1],"description":"1 when another returnable item exists in the bounded raw page; filtering can make it 0 even when visible projections exist farther ahead."},"events":{"type":"array","maxItems":2000,"items":{"$ref":"#/components/schemas/SyncedMessageEvent"},"description":"Current projections ordered by event sequence, at most 2000 items."},"filtered_by_event_key":{"type":"string","description":"Echoed event_key; empty means no lane filter."}},"description":"Projection read result and continuation cursor."},"MessageEventSyncResponse":{"type":"object","additionalProperties":false,"required":["status","data"],"properties":{"status":{"type":"integer","const":200,"description":"Application status fixed at 200."},"data":{"$ref":"#/components/schemas/MessageEventSyncData","description":"Current projections and cursors."}},"description":"Successful message-event read response."},"AppendMessageEventRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type","client_msg_no","event_id","event_type"],"properties":{"channel_id":{"type":"string","minLength":1,"pattern":"\\S","description":"Target non-blank Channel ID; person and Agent Channels are normalized by the use case."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"from_uid":{"type":"string","description":"Event actor UID; person or unencoded Agent Channel normalization may require it."},"message_id":{"type":"integer","format":"int64","description":"Optional server message ID; positive values become uint64, while 0 or negative values are omitted from the event command."},"client_msg_no":{"type":"string","minLength":1,"pattern":"\\S","description":"Non-blank client message number of the message receiving the event."},"event_id":{"type":"string","minLength":1,"pattern":"\\S","description":"Non-blank unique identifier of this event."},"event_type":{"type":"string","minLength":1,"pattern":"^\\s*[sS][tT][rR][eE][aA][mM]\\.(?:[oO][pP][eE][nN]|[dD][eE][lL][tT][aA]|[cC][lL][oO][sS][eE]|[eE][rR][rR][oO][rR]|[cC][aA][nN][cC][eE][lL]|[sS][nN][aA][pP][sS][hH][oO][tT]|[fF][iI][nN][iI][sS][hH])\\s*$","examples":["stream.open","stream.delta","stream.close","stream.error","stream.cancel","stream.snapshot","stream.finish"],"description":"Event type; surrounding whitespace is removed and the value is lowercased."},"event_key":{"type":"string","description":"Event lane key; empty selects the default lane and stream.finish forces the finish lane."},"visibility":{"type":"string","description":"Caller-supplied event metadata stored after trimming; ordinary message synchronization does not use it as an access-control filter. eventsync filters by include_private without checking caller permissions."},"occurred_at":{"type":"integer","format":"int64","description":"Caller-supplied integer event time; the entry does not interpret its unit."},"payload":{"description":"Arbitrary JSON event payload passed to event storage as raw JSON bytes."},"headers":{"type":"null","deprecated":true,"description":"Reserved field; it must be omitted or null, and every non-null JSON value is rejected."}},"description":"Message-event projection parameters."},"AppendMessageEventData":{"type":"object","additionalProperties":false,"required":["client_msg_no","event_key","event_id","msg_event_seq","stream_status","channel_id","channel_type","from_uid"],"properties":{"client_msg_no":{"type":"string","description":"Client message number of the target message."},"event_key":{"type":"string","description":"Normalized event lane key."},"event_id":{"type":"string","description":"Accepted unique event identifier."},"msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Increasing sequence within this message event stream."},"stream_status":{"type":"string","enum":["open","closed","error","cancelled"],"description":"Stream status after projection."},"channel_id":{"type":"string","description":"Normalized Channel ID."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Normalized Channel type."},"from_uid":{"type":"string","description":"Normalized event actor UID."}},"description":"Normalized result of the applied event projection."},"AppendMessageEventResponse":{"type":"object","additionalProperties":false,"required":["status","data"],"properties":{"status":{"type":"integer","const":200,"description":"Application-level status fixed at 200."},"data":{"$ref":"#/components/schemas/AppendMessageEventData","description":"Normalized data for the applied event."}},"description":"Successful event-projection response."},"MessageSyncRequest":{"type":"object","additionalProperties":true,"required":["uid"],"properties":{"uid":{"type":"string","minLength":1,"pattern":"\\S","description":"Non-blank user ID whose command messages are synchronized."},"message_seq":{"type":"integer","format":"uint64","minimum":0,"deprecated":true,"description":"Deprecated compatibility input accepted and ignored by the server."},"limit":{"type":"integer","minimum":0,"default":200,"description":"Maximum messages returned; 0 uses 200, negative values are rejected, and values above 10000 are capped at 10000; it does not bound the total cost of enumerating Channels and scanning messages."}},"description":"Legacy command-message synchronization parameters."},"MessageSyncAckRequest":{"type":"object","additionalProperties":true,"required":["uid","last_message_seq"],"properties":{"uid":{"type":"string","minLength":1,"pattern":"\\S","description":"Non-blank user ID acknowledging command-message synchronization."},"last_message_seq":{"type":"integer","format":"uint64","minimum":1,"deprecated":true,"description":"Compatibility field that must be positive; acknowledgement uses the latest server-recorded generation rather than this supplied value."}},"description":"Legacy command-message synchronization acknowledgement parameters."},"MessageCMDBindingRequest":{"type":"object","additionalProperties":true,"properties":{"uid":{"type":"string","minLength":1,"pattern":"\\S","description":"Unique identifier of the target user."},"channel_id":{"type":"string","minLength":1,"pattern":"\\S","description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"uids":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"},"description":"Source-Channel recipients, at most 1000 entries; trims blanks and duplicates. Exclusive with uid and subscribers."},"subscribers":{"type":"array","minItems":1,"maxItems":1000,"items":{"type":"string"},"description":"Use this field alone to bind the SEND temporary recipient scope; at most 1000 entries, in the same order as SEND. Exclusive with source-Channel fields."}},"oneOf":[{"required":["uid","channel_id","channel_type"],"not":{"anyOf":[{"required":["uids"]},{"required":["subscribers"]}]}},{"required":["uids","channel_id","channel_type"],"not":{"anyOf":[{"required":["uid"]},{"required":["subscribers"]}]}},{"required":["subscribers"],"not":{"anyOf":[{"required":["uid"]},{"required":["uids"]},{"required":["channel_id"]},{"required":["channel_type"]}]}}],"description":"Command-Channel offline-discovery binding parameters."},"ChannelMessageSyncRequest":{"type":"object","additionalProperties":true,"required":["login_uid","channel_id","channel_type"],"properties":{"login_uid":{"type":"string","minLength":1,"pattern":"\\S","description":"User identity performing the read and required to own the corresponding Channel membership."},"channel_id":{"type":"string","minLength":1,"pattern":"\\S","description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"start_message_seq":{"type":"integer","format":"uint64","minimum":0,"default":0,"description":"Inclusive Channel message-sequence starting boundary; 0 selects the open end, and newer reads also raise it to the membership visibility floor."},"end_message_seq":{"type":"integer","format":"uint64","minimum":0,"default":0,"description":"Exclusive Channel message-sequence ending boundary; 0 selects the open end."},"limit":{"type":"integer","default":100,"description":"Maximum messages returned by this read; values at or below 0 use 100 and values above 10000 are capped at 10000."},"pull_mode":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Pull direction; 1 reads toward newer messages and every other uint8 value uses the compatibility branch for older messages."},"include_event_meta":{"type":"integer","default":0,"description":"Message-event summary switch; a non-zero value requests event metadata and defaults an empty event_summary_mode to full."},"event_summary_mode":{"type":"string","default":"","description":"Event-summary mode; empty disables enrichment, full includes snapshots, and any other non-empty value returns the basic summary without snapshots."}},"description":"Single-Channel committed-message synchronization parameters."},"ChannelMessageSyncBatchItemRequest":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type"],"properties":{"login_uid":{"type":"string","deprecated":true,"description":"Accepted for compatibility but ignored; batch requests always use the top-level login_uid."},"channel_id":{"type":"string","minLength":1,"pattern":"\\S","description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"start_message_seq":{"type":"integer","format":"uint64","minimum":0,"default":0,"description":"Inclusive Channel message-sequence starting boundary; 0 selects the open end, and newer reads also raise it to the membership visibility floor."},"end_message_seq":{"type":"integer","format":"uint64","minimum":0,"default":0,"description":"Exclusive Channel message-sequence ending boundary; 0 selects the open end."},"limit":{"type":"integer","default":100,"description":"Maximum messages returned by this read; values at or below 0 use 100 and values above 10000 are capped at 10000."},"pull_mode":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Pull direction; 1 reads toward newer messages and every other uint8 value uses the compatibility branch for older messages."},"include_event_meta":{"type":"integer","default":0,"description":"Message-event summary switch; a non-zero value requests event metadata and defaults an empty event_summary_mode to full."},"event_summary_mode":{"type":"string","default":"","description":"Event-summary mode; empty disables enrichment, full includes snapshots, and any other non-empty value returns the basic summary without snapshots."}},"description":"Read criteria for one Channel inside a batch synchronization request."},"ChannelMessageSyncBatchRequest":{"type":"object","additionalProperties":true,"required":["login_uid","items"],"properties":{"login_uid":{"type":"string","minLength":1,"pattern":"\\S","description":"User identity performing the read and required to own the corresponding Channel membership."},"items":{"type":"array","minItems":1,"maxItems":200,"items":{"$ref":"#/components/schemas/ChannelMessageSyncBatchItemRequest"},"description":"Channels to synchronize; between 1 and 200 items are accepted and response order matches request order."}},"description":"Batch Channel committed-message synchronization parameters."},"LegacyMessageHeader":{"type":"object","additionalProperties":false,"required":["no_persist","red_dot","sync_once"],"properties":{"no_persist":{"type":"integer","enum":[0,1],"description":"1 means the message is non-durable."},"red_dot":{"type":"integer","enum":[0,1],"description":"1 means the client should show a red-dot indicator."},"sync_once":{"type":"integer","enum":[0,1],"description":"1 means a one-shot command message."}},"description":"Legacy message-header projection."},"LegacyMessageEventKeyMeta":{"type":"object","additionalProperties":false,"required":["event_key","status"],"properties":{"event_key":{"type":"string","description":"Event lane key."},"status":{"type":"string","description":"Current state of the lane."},"last_msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Latest known event sequence for the lane."},"snapshot":{"description":"Arbitrary JSON snapshot in full summary mode."},"end_reason":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Event-stream terminal Reason Code."},"error":{"type":"string","description":"Event-stream error description."}},"description":"Summary of one event lane."},"LegacyMessageEventMeta":{"type":"object","additionalProperties":false,"required":["has_events","completed"],"properties":{"has_events":{"type":"boolean","description":"Whether events exist."},"completed":{"type":"boolean","description":"Whether all known event lanes have completed."},"event_version":{"type":"integer","format":"uint64","minimum":0,"description":"Event-summary version."},"last_msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Latest event sequence across all lanes."},"event_count":{"type":"integer","minimum":0,"description":"Total event count."},"open_event_count":{"type":"integer","minimum":0,"description":"Number of event lanes still open."},"events":{"type":"array","items":{"$ref":"#/components/schemas/LegacyMessageEventKeyMeta"},"description":"Per-lane event summaries."}},"description":"Aggregated event summary for one message."},"LegacyMessageEventSyncHint":{"type":"object","additionalProperties":false,"required":["client_msg_no","from_msg_event_seq"],"properties":{"client_msg_no":{"type":"string","description":"Client message number of the target message."},"from_msg_event_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Starting sequence for the next event synchronization."}},"description":"Hint for continuing message-event synchronization."},"LegacyMessage":{"type":"object","additionalProperties":false,"required":["header","setting","message_id","message_idstr","client_msg_no","message_seq","from_uid","channel_id","channel_type","expire","timestamp","payload"],"properties":{"header":{"$ref":"#/components/schemas/LegacyMessageHeader","description":"Legacy message header."},"setting":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"WKProto Setting bitset."},"message_id":{"type":"integer","format":"int64","description":"Server int64 message ID."},"message_idstr":{"type":"string","description":"Decimal string mirror of message_id only; it is not a replacement for message_seq."},"client_msg_no":{"type":"string","description":"Original client number, or the stable read-only alias wk3-legacy-<message_id> for an old empty-number record with a message ID. The alias supports /messages lookup; it is not a SEND idempotency or event mutation key. Stored records are unchanged."},"end":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Stream-message terminal compatibility flag."},"end_reason":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Stream-message terminal Reason Code."},"error":{"type":"string","description":"Stream-message error description."},"stream_data":{"type":["string","null"],"contentEncoding":"base64","description":"Base64-encoded stream data; it may be null."},"event_meta":{"$ref":"#/components/schemas/LegacyMessageEventMeta","description":"Optional message-event summary."},"event_sync_hint":{"$ref":"#/components/schemas/LegacyMessageEventSyncHint","description":"Optional message-event continuation hint."},"message_seq":{"type":"integer","format":"uint64","minimum":0,"description":"uint64 sequence of the message within this Channel."},"from_uid":{"type":"string","description":"Message sender UID."},"channel_id":{"type":"string","description":"Channel ID containing the message."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Channel type containing the message."},"topic":{"type":"string","description":"Optional message topic."},"expire":{"type":"integer","format":"uint32","minimum":0,"description":"Message expiration in seconds; 0 means unset."},"timestamp":{"type":"integer","format":"int32","description":"Legacy server timestamp in seconds."},"payload":{"type":["string","null"],"contentEncoding":"base64","description":"Base64-encoded message payload; it may be null."},"version":{"type":"string","pattern":"^[0-9]+$","description":"Edited content version; absent means zero in the same content epoch."},"updated_at_ms":{"type":"integer","format":"int64","minimum":0,"description":"Server edit time in Unix milliseconds; original ordering is unchanged."}},"description":"Legacy message projection used by Product HTTP synchronization."},"ChannelMessageSyncResponse":{"type":"object","additionalProperties":false,"required":["start_message_seq","end_message_seq","more","messages"],"properties":{"start_message_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Starting message sequence of the effective range for this page."},"end_message_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Ending message sequence of the effective range for this page."},"more":{"type":"integer","enum":[0,1],"description":"1 means another page may exist in the same direction; 0 means the current range is exhausted."},"messages":{"type":"array","items":{"$ref":"#/components/schemas/LegacyMessage"},"description":"Messages are returned in ascending message_seq order regardless of pull direction."}},"description":"Message synchronization page for one Channel."},"ChannelMessageSyncBatchItemResponse":{"type":"object","additionalProperties":false,"required":["channel_id","channel_type","start_message_seq","end_message_seq","more","messages"],"properties":{"channel_id":{"type":"string","description":"Channel ID from the corresponding request item."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Channel type from the corresponding request item."},"start_message_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Starting sequence of this item effective range."},"end_message_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Ending sequence of this item effective range."},"more":{"type":"integer","enum":[0,1],"description":"Whether another page may exist for this item."},"messages":{"type":"array","items":{"$ref":"#/components/schemas/LegacyMessage"},"description":"Messages returned when this item succeeds."},"error":{"type":"string","description":"Per-item error text that must be checked even with HTTP 200; empty means no item error."}},"description":"Independent result for one Channel in a batch sync."},"ChannelMessageSyncBatchResponse":{"type":"object","additionalProperties":false,"required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ChannelMessageSyncBatchItemResponse"},"description":"Independent per-Channel synchronization results."}},"description":"Batch result aligned in order with request items."},"ConversationListRequest":{"type":"object","additionalProperties":true,"required":["uid"],"properties":{"uid":{"type":"string","minLength":1,"description":"User ID whose Conversation directory is read."},"cursor":{"type":"string","default":"","description":"Opaque next_cursor from the previous page; omit it or send an empty string for the first page."},"limit":{"type":"integer","minimum":0,"maximum":200,"default":50,"description":"Maximum membership entries scanned for this page; 0 uses the default 50 and the maximum is 200."},"completed_coverage":{"type":"integer","format":"int64","minimum":0,"default":0,"description":"Coverage saved from the client's latest pass that ended with done=true; send 0 for the first synchronization."}},"description":"Conversation-directory pagination parameters."},"ConversationKey":{"type":"object","additionalProperties":true,"required":["channel_id","channel_type"],"properties":{"channel_id":{"type":"string","minLength":1,"description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."}},"description":"Channel key for one Conversation."},"ConversationMutationRequest":{"type":"object","additionalProperties":true,"required":["uid","channel_id","channel_type"],"properties":{"uid":{"type":"string","minLength":1,"description":"Unique identifier of the target user."},"channel_id":{"type":"string","minLength":1,"description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."}},"description":"Shared key for Conversation clear-unread, hide, or activate operations."},"ConversationSetUnreadRequest":{"type":"object","additionalProperties":true,"required":["uid","channel_id","channel_type","unread"],"properties":{"uid":{"type":"string","minLength":1,"description":"Unique identifier of the target user."},"channel_id":{"type":"string","minLength":1,"description":"Logical identifier of the target Channel; for a person Channel this is normally the other UID."},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255,"description":"Numeric Channel type; 1 is a person Channel, 2 is a group Channel, and other values are extension types."},"unread":{"type":"integer","minimum":0,"description":"Maximum unread messages to retain; it must be at least 0 and the server only advances read_seq monotonically."}},"description":"Parameters for setting a Conversation maximum unread count."},"ConversationListResponse":{"type":"object","additionalProperties":false,"required":["conversations","deletes","done","coverage","tombstones_retained_since","reset_required"],"properties":{"conversations":{"type":"array","items":{"$ref":"#/components/schemas/ConversationListItem"},"description":"Resolved Conversations in this page."},"deletes":{"type":"array","items":{"$ref":"#/components/schemas/ConversationKey"},"description":"Conversation keys the client should delete."},"next_cursor":{"type":"string","description":"Opaque cursor for the next page; return it unchanged."},"done":{"type":"boolean","description":"true means the full pass is complete; only then may coverage be saved."},"coverage":{"type":"integer","format":"int64","minimum":0,"description":"Coverage version observed by the server for this synchronization pass."},"tombstones_retained_since":{"type":"integer","format":"int64","minimum":0,"description":"Earliest coverage for which deletion tombstones are still retained."},"reset_required":{"type":"boolean","description":"true means client coverage predates the retention window and the local Conversation directory must be rebuilt."}},"description":"One canonical Conversation-directory page and its synchronization control state."},"ConversationListItem":{"type":"object","additionalProperties":false,"required":["channel_id","channel_type","active_at","read_seq","deleted_to_seq","unread","last_message"],"properties":{"channel_id":{"type":"string","description":"Conversation Channel ID."},"channel_type":{"type":"integer","minimum":1,"maximum":255,"description":"Conversation Channel type."},"active_at":{"type":"integer","format":"int64","description":"Most recent Conversation activation time."},"read_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Greatest message sequence read by the user."},"deleted_to_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Greatest message sequence deleted by the user."},"unread":{"type":"integer","format":"uint64","minimum":0,"description":"Unread count derived from the current last message and read_seq."},"last_message":{"oneOf":[{"$ref":"#/components/schemas/ConversationLastMessage"},{"type":"null"}],"description":"Latest visible ordinary message persisted on the current Leader, regardless of SEND success; null when absent."}},"description":"Canonical Conversation state for one user."},"ConversationLastMessage":{"type":"object","additionalProperties":false,"required":["message_id","message_idstr","message_seq","from_uid","client_msg_no","server_timestamp_ms","payload"],"properties":{"message_id":{"type":"integer","format":"uint64","minimum":0,"description":"Server int64 message ID."},"message_idstr":{"type":"string","description":"Decimal string mirror of message_id only."},"message_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Sequence of this message within the Channel."},"from_uid":{"type":"string","description":"Message sender UID."},"client_msg_no":{"type":"string","description":"Client message number."},"server_timestamp_ms":{"type":"integer","format":"int64","description":"Server timestamp in milliseconds."},"payload":{"type":["string","null"],"contentEncoding":"base64","description":"Base64-encoded message payload; it may be null."},"version":{"type":"string","pattern":"^[0-9]+$","description":"Edited content version; absent means zero in the same content epoch."},"updated_at_ms":{"type":"integer","format":"int64","minimum":0,"description":"Server edit time in Unix milliseconds; original ordering is unchanged."}},"description":"Last-message summary in the Conversation directory."},"ConversationSyncLegacyRequest":{"type":"object","additionalProperties":true,"required":["uid"],"properties":{"uid":{"type":"string","minLength":1,"pattern":"\\S","description":"Non-blank user ID whose legacy Conversations are synchronized."},"version":{"type":"integer","format":"int64","default":0,"description":"Conversation version known by the client; 0 disables version filtering."},"last_msg_seqs":{"type":"string","default":"","description":"Pipe-delimited channel_id:channel_type:message_seq cursors; malformed entries are skipped."},"msg_count":{"type":"integer","default":0,"description":"Recent messages read per Conversation; values at or below 0 return an empty array and positive values are capped at 10000."},"only_unread":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"default":0,"description":"Unread-filter compatibility flag; exactly 1 selects unread Conversations only."},"exclude_channel_types":{"type":["array","null"],"items":{"type":"integer","format":"uint8","minimum":0,"maximum":255},"description":"Channel types to exclude; it may be omitted, empty, or null, and an explicit Channel cursor overrides this filter."},"page":{"type":"integer","default":0,"description":"Legacy page number; values at or below 0 disable legacy page slicing."},"page_size":{"type":"integer","default":100,"description":"Legacy page size; when page>0, values at or below 0 use 100 and values above 500 are capped at 500."}},"description":"Legacy sync parameters. Retry the original request on failure. List and sync share 16 active requests and a five-second deadline; at most 1,000 candidates, 200 Channels per batch, 10,000 requested recents and 32 MiB of base/stream payloads. Budget exhaustion fails the whole request."},"ConversationSyncLegacyItem":{"type":"object","additionalProperties":false,"required":["channel_id","channel_type","unread","timestamp","last_msg_seq","last_client_msg_no","offset_msg_seq","readed_to_msg_seq","version","recents"],"properties":{"channel_id":{"type":"string","description":"Conversation Channel ID."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Conversation Channel type."},"unread":{"type":"integer","format":"uint64","minimum":0,"description":"Legacy unread count."},"timestamp":{"type":"integer","format":"int64","description":"Legacy Conversation timestamp."},"last_msg_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Current last-message sequence."},"last_client_msg_no":{"type":"string","description":"Last-message client number; old empty-number records use the same read-only alias as recents."},"offset_msg_seq":{"type":"integer","format":"int64","description":"Offset sequence for this recent-message window."},"readed_to_msg_seq":{"type":"integer","format":"uint64","minimum":0,"description":"Message sequence read by the user."},"version":{"type":"integer","format":"int64","description":"Legacy Conversation version."},"recents":{"type":"array","items":{"$ref":"#/components/schemas/LegacyMessage"},"description":"Recent messages bounded by msg_count. To repair old empty-key collisions, the latest empty-number message or edited tail may be returned again after the client cursor advances; read and delete positions are unchanged."}},"description":"v2.2-compatible Conversation projection."},"MessageLookupRequest":{"type":"object","description":"Exact message selectors within one visible channel. Selector arrays form a union; results are unique and ordered by sequence. The runtime validates the combined 1–128 selector count.","required":["login_uid","channel_id","channel_type"],"properties":{"login_uid":{"type":"string","minLength":1,"pattern":"\\S"},"channel_id":{"type":"string","minLength":1,"pattern":"\\S"},"channel_type":{"type":"integer","format":"uint8","minimum":1,"maximum":255},"message_ids":{"type":["array","null"],"maxItems":128,"items":{"type":"integer","format":"uint64","minimum":1},"description":"Exact message IDs. Combined selector count must be 1–128."},"message_seqs":{"type":["array","null"],"maxItems":128,"items":{"type":"integer","format":"uint64","minimum":1},"description":"Exact message sequences. Combined selector count must be 1–128."},"client_msg_nos":{"type":["array","null"],"maxItems":128,"items":{"type":"string","minLength":1,"maxLength":1024,"pattern":"\\S"},"description":"Exact client message numbers. Combined selector count must be 1–128."}},"additionalProperties":true,"anyOf":[{"required":["message_ids"],"properties":{"message_ids":{"type":"array","minItems":1}}},{"required":["message_seqs"],"properties":{"message_seqs":{"type":"array","minItems":1}}},{"required":["client_msg_nos"],"properties":{"client_msg_nos":{"type":"array","minItems":1}}}]},"UpdateMessageRequest":{"type":"object","additionalProperties":false,"required":["channel_id","channel_type","message_id","expected_content_epoch","expected_version","request_id","payload"],"properties":{"login_uid":{"type":"string","description":"User identity; required for person-channel normalization and edit sync. It does not authorize editing."},"channel_id":{"type":"string","minLength":1,"description":"Channel ID; use the peer UID for a person channel."},"channel_type":{"type":"integer","minimum":1,"maximum":255,"description":"Channel type: 1 person, 2 group."},"message_id":{"type":"string","pattern":"^[0-9]+$","description":"Existing nonzero message ID."},"expected_content_epoch":{"type":"string","pattern":"^[0-9]+$","description":"Epoch from the response that supplied the displayed message."},"expected_version":{"type":"string","pattern":"^[0-9]+$","description":"Displayed version; use 0 for an unedited original."},"request_id":{"type":"string","minLength":1,"maxLength":128,"description":"Stable retry ID, at most 128 UTF-8 bytes."},"payload":{"type":"string","contentEncoding":"base64","minLength":1,"description":"Complete replacement; 1 to 1 MiB decoded bytes, 2 MiB request-body limit."}},"description":"Replace an ordinary retained message; the backend owns editing permission."},"MessageUpdatesRequest":{"type":"object","additionalProperties":false,"required":["login_uid","channel_id","channel_type"],"properties":{"login_uid":{"type":"string","description":"User identity; required for person-channel normalization and edit sync. It does not authorize editing."},"channel_id":{"type":"string","minLength":1,"description":"Channel ID; use the peer UID for a person channel."},"channel_type":{"type":"integer","minimum":1,"maximum":255,"description":"Channel type: 1 person, 2 group."},"update_cursor":{"type":"string","maxLength":4096,"description":"Opaque cursor, at most 4096 bytes. Empty bootstraps before loading history."},"limit":{"type":"integer","minimum":0,"maximum":200,"default":100,"description":"Maximum updates; omitted or 0 uses 100."}},"description":"Pull latest edits for one visible channel."},"MessageUpdateResult":{"type":"object","additionalProperties":false,"required":["message_id","message_seq","version","updated_at_ms"],"properties":{"message_id":{"type":"string","pattern":"^[0-9]+$","description":"Original message ID."},"message_seq":{"type":"string","pattern":"^[0-9]+$","description":"Original channel sequence."},"version":{"type":"string","pattern":"^[0-9]+$","description":"Edited content version; absent means zero in the same content epoch."},"updated_at_ms":{"type":"integer","format":"int64","minimum":0,"description":"Server edit time in Unix milliseconds; original ordering is unchanged."}},"description":"Originally committed edit result, also returned on an identical retry."},"UpdateMessageResponse":{"type":"object","additionalProperties":false,"required":["status","data"],"properties":{"status":{"type":"integer","const":200,"description":"HTTP status."},"data":{"$ref":"#/components/schemas/MessageUpdateResult","description":"Committed edit result."}},"description":"Successful edit envelope."},"UpdatedMessage":{"type":"object","additionalProperties":false,"required":["header","setting","message_id","message_idstr","client_msg_no","message_seq","from_uid","channel_id","channel_type","expire","timestamp","payload","version","updated_at_ms"],"properties":{"header":{"$ref":"#/components/schemas/LegacyMessageHeader","description":"Legacy message header."},"setting":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"WKProto Setting bitset."},"message_id":{"type":"string","pattern":"^[0-9]+$","description":"Server int64 message ID."},"message_idstr":{"type":"string","description":"Decimal string mirror of message_id only; it is not a replacement for message_seq."},"client_msg_no":{"type":"string","description":"Original client number, or the stable read-only alias wk3-legacy-<message_id> for an old empty-number record with a message ID. The alias supports /messages lookup; it is not a SEND idempotency or event mutation key. Stored records are unchanged."},"end":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Stream-message terminal compatibility flag."},"end_reason":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Stream-message terminal Reason Code."},"error":{"type":"string","description":"Stream-message error description."},"stream_data":{"type":["string","null"],"contentEncoding":"base64","description":"Base64-encoded stream data; it may be null."},"event_meta":{"$ref":"#/components/schemas/LegacyMessageEventMeta","description":"Optional message-event summary."},"event_sync_hint":{"$ref":"#/components/schemas/LegacyMessageEventSyncHint","description":"Optional message-event continuation hint."},"message_seq":{"type":"string","pattern":"^[0-9]+$","description":"uint64 sequence of the message within this Channel."},"from_uid":{"type":"string","description":"Message sender UID."},"channel_id":{"type":"string","description":"Channel ID containing the message."},"channel_type":{"type":"integer","format":"uint8","minimum":0,"maximum":255,"description":"Channel type containing the message."},"topic":{"type":"string","description":"Optional message topic."},"expire":{"type":"integer","format":"uint32","minimum":0,"description":"Message expiration in seconds; 0 means unset."},"timestamp":{"type":"integer","format":"int32","description":"Legacy server timestamp in seconds."},"payload":{"type":["string","null"],"contentEncoding":"base64","description":"Base64-encoded message payload; it may be null."},"version":{"type":"string","pattern":"^[0-9]+$","description":"Edited content version; absent means zero in the same content epoch."},"updated_at_ms":{"type":"integer","format":"int64","minimum":0,"description":"Server edit time in Unix milliseconds; original ordering is unchanged."}},"description":"Legacy message projection used by Product HTTP synchronization."},"MessageUpdatesResponse":{"type":"object","additionalProperties":false,"required":["updates","next_update_cursor","more","reset_required"],"properties":{"updates":{"type":"array","maxItems":200,"items":{"$ref":"#/components/schemas/UpdatedMessage"},"description":"Latest states, not a full edit history; empty is possible while more is true."},"next_update_cursor":{"type":"string","description":"Commit with merged rows in one local transaction."},"more":{"type":"boolean","description":"Continue this channel until false."},"reset_required":{"type":"boolean","description":"Hold the returned baseline, reload visible history, then commit history and baseline in one local transaction. Reset old version comparisons after an epoch change."}},"description":"Latest-state incremental page."},"MessageUpdateError":{"type":"object","additionalProperties":false,"required":["status","code"],"properties":{"status":{"type":"integer","description":"HTTP status."},"code":{"type":"string","description":"Stable rejection code; uncertain writes retain their exact retry identity."},"msg":{"type":"string","description":"Optional legacy diagnostic message."}},"description":"Edit or transient read failure; no partial results."}}}}