[{"data":1,"prerenderedAt":2646},["ShallowReactive",2],{"docs:/docs/protocol":3},{"id":4,"title":5,"body":6,"description":2638,"extension":2639,"meta":2640,"navigation":2641,"path":2642,"seo":2643,"stem":2644,"__hash__":2645},"docs/docs/protocol.md","Wire Protocol",{"type":7,"value":8,"toc":2605},"minimark",[9,13,22,27,80,84,89,96,211,245,248,382,409,412,438,461,465,468,477,481,489,594,611,615,618,708,718,721,756,759,866,892,899,903,951,966,969,1033,1045,1049,1084,1088,1159,1166,1170,1255,1266,1270,1273,1362,1383,1387,1453,1455,1493,1499,1503,1549,1553,1713,1747,1751,2015,2036,2040,2097,2102,2105,2154,2172,2174,2252,2265,2413,2417,2447,2450,2528,2532,2535,2548,2552,2555,2569,2573,2601],[10,11,5],"h1",{"id":12},"wire-protocol",[14,15,16,17,21],"p",{},"NoLag communicates over WebSocket using MessagePack-encoded binary frames. Every message is a map (key-value object) with a ",[18,19,20],"code",{},"type"," field that identifies what kind of message it is. There is no custom binary framing; the entire message is a single MessagePack-encoded map.",[23,24,26],"h2",{"id":25},"transport","Transport",[28,29,30,38,47,56,62,68,74],"ul",{},[31,32,33,37],"li",{},[34,35,36],"strong",{},"Protocol:"," WebSocket (binary frames)",[31,39,40,43,44],{},[34,41,42],{},"Encoding:"," MessagePack with ",[18,45,46],{},"pack_str: from_binary",[31,48,49,52,53],{},[34,50,51],{},"Endpoint:"," ",[18,54,55],{},"wss://broker.nolag.app/ws",[31,57,58,61],{},[34,59,60],{},"Heartbeat:"," the client sends an empty binary frame (0 bytes), the SDKs every 30 seconds, and the server echoes it",[31,63,64,67],{},[34,65,66],{},"Idle timeout:"," the server closes a connection that has sent nothing for 60 seconds",[31,69,70,73],{},[34,71,72],{},"Max message size:"," 900 KB (all plans)",[31,75,76,79],{},[34,77,78],{},"Rate limit:"," 50 publishes/second per connection",[23,81,83],{"id":82},"connection-lifecycle","Connection Lifecycle",[85,86,88],"h3",{"id":87},"_1-authentication","1. Authentication",[14,90,91,92,95],{},"After the WebSocket opens, the client sends an ",[18,93,94],{},"auth"," message immediately:",[97,98,99],"code-tabs",{},[100,101,107],"pre",{"className":102,"code":103,"filename":104,"language":105,"meta":106,"style":106},"language-json shiki shiki-themes github-light github-dark","// Client sends after WebSocket opens\n{\n  \"type\": \"auth\",\n  \"token\": \"at_live_\u003Ckey_id>.\u003Csecret>\",\n  \"protocolVersion\": 2,\n  \"reconnect\": false,\n  \"projectId\": \"proj_123\",\n  \"clientId\": \"worker-1\"\n}\n","JSON","json","",[18,108,109,118,125,142,155,168,181,194,205],{"__ignoreMap":106},[110,111,114],"span",{"class":112,"line":113},"line",1,[110,115,117],{"class":116},"sJ8bj","// Client sends after WebSocket opens\n",[110,119,121],{"class":112,"line":120},2,[110,122,124],{"class":123},"sVt8B","{\n",[110,126,128,132,135,139],{"class":112,"line":127},3,[110,129,131],{"class":130},"sj4cs","  \"type\"",[110,133,134],{"class":123},": ",[110,136,138],{"class":137},"sZZnC","\"auth\"",[110,140,141],{"class":123},",\n",[110,143,145,148,150,153],{"class":112,"line":144},4,[110,146,147],{"class":130},"  \"token\"",[110,149,134],{"class":123},[110,151,152],{"class":137},"\"at_live_\u003Ckey_id>.\u003Csecret>\"",[110,154,141],{"class":123},[110,156,158,161,163,166],{"class":112,"line":157},5,[110,159,160],{"class":130},"  \"protocolVersion\"",[110,162,134],{"class":123},[110,164,165],{"class":130},"2",[110,167,141],{"class":123},[110,169,171,174,176,179],{"class":112,"line":170},6,[110,172,173],{"class":130},"  \"reconnect\"",[110,175,134],{"class":123},[110,177,178],{"class":130},"false",[110,180,141],{"class":123},[110,182,184,187,189,192],{"class":112,"line":183},7,[110,185,186],{"class":130},"  \"projectId\"",[110,188,134],{"class":123},[110,190,191],{"class":137},"\"proj_123\"",[110,193,141],{"class":123},[110,195,197,200,202],{"class":112,"line":196},8,[110,198,199],{"class":130},"  \"clientId\"",[110,201,134],{"class":123},[110,203,204],{"class":137},"\"worker-1\"\n",[110,206,208],{"class":112,"line":207},9,[110,209,210],{"class":123},"}\n",[14,212,213,216,217,219,220,222,223,222,226,229,230,233,234,237,238,241,242,244],{},[18,214,215],{},"protocolVersion"," selects the frame set. Send ",[18,218,165],{},": it is what the current SDKs send (js-sdk 1.6+, Python 2.5+, Go v0.5.0), and it is what gets you the rich error frames (",[18,221,18],{},", ",[18,224,225],{},"hint",[18,227,228],{},"msgRef","), the ",[18,231,232],{},"unknown_topic"," error and ",[18,235,236],{},"published"," acks. A client that omits the field is treated as version 1 and gets a bare ",[18,239,240],{},"not_authorized"," where a v2 client gets ",[18,243,232],{},". The server replies with the lower of the two versions.",[14,246,247],{},"The server answers with one of:",[97,249,250,338],{},[100,251,254],{"className":102,"code":252,"filename":253,"language":105,"meta":106,"style":106},"{\n  \"type\": \"auth\",\n  \"success\": true,\n  \"actorTokenId\": \"actor_123\",\n  \"projectId\": \"proj_123\",\n  \"actorType\": \"user\",\n  \"protocolVersion\": 2,\n  \"restoredSubscriptions\": []\n}\n","Success",[18,255,256,260,270,282,294,304,316,326,334],{"__ignoreMap":106},[110,257,258],{"class":112,"line":113},[110,259,124],{"class":123},[110,261,262,264,266,268],{"class":112,"line":120},[110,263,131],{"class":130},[110,265,134],{"class":123},[110,267,138],{"class":137},[110,269,141],{"class":123},[110,271,272,275,277,280],{"class":112,"line":127},[110,273,274],{"class":130},"  \"success\"",[110,276,134],{"class":123},[110,278,279],{"class":130},"true",[110,281,141],{"class":123},[110,283,284,287,289,292],{"class":112,"line":144},[110,285,286],{"class":130},"  \"actorTokenId\"",[110,288,134],{"class":123},[110,290,291],{"class":137},"\"actor_123\"",[110,293,141],{"class":123},[110,295,296,298,300,302],{"class":112,"line":157},[110,297,186],{"class":130},[110,299,134],{"class":123},[110,301,191],{"class":137},[110,303,141],{"class":123},[110,305,306,309,311,314],{"class":112,"line":170},[110,307,308],{"class":130},"  \"actorType\"",[110,310,134],{"class":123},[110,312,313],{"class":137},"\"user\"",[110,315,141],{"class":123},[110,317,318,320,322,324],{"class":112,"line":183},[110,319,160],{"class":130},[110,321,134],{"class":123},[110,323,165],{"class":130},[110,325,141],{"class":123},[110,327,328,331],{"class":112,"line":196},[110,329,330],{"class":130},"  \"restoredSubscriptions\"",[110,332,333],{"class":123},": []\n",[110,335,336],{"class":112,"line":207},[110,337,210],{"class":123},[100,339,342],{"className":102,"code":340,"filename":341,"language":105,"meta":106,"style":106},"{\n  \"type\": \"auth\",\n  \"success\": false,\n  \"error\": \"access_denied\"\n}\n","Failure",[18,343,344,348,358,368,378],{"__ignoreMap":106},[110,345,346],{"class":112,"line":113},[110,347,124],{"class":123},[110,349,350,352,354,356],{"class":112,"line":120},[110,351,131],{"class":130},[110,353,134],{"class":123},[110,355,138],{"class":137},[110,357,141],{"class":123},[110,359,360,362,364,366],{"class":112,"line":127},[110,361,274],{"class":130},[110,363,134],{"class":123},[110,365,178],{"class":130},[110,367,141],{"class":123},[110,369,370,373,375],{"class":112,"line":144},[110,371,372],{"class":130},"  \"error\"",[110,374,134],{"class":123},[110,376,377],{"class":137},"\"access_denied\"\n",[110,379,380],{"class":112,"line":157},[110,381,210],{"class":123},[14,383,384,385,388,389,222,392,222,395,222,398,222,401,404,405,408],{},"The failure ",[18,386,387],{},"error"," is one of ",[18,390,391],{},"access_denied",[18,393,394],{},"authentication_failed",[18,396,397],{},"connection_failed",[18,399,400],{},"token_expired",[18,402,403],{},"connection_limit_reached"," or ",[18,406,407],{},"broker_unavailable",".",[14,410,411],{},"The broker sets no deadline for the auth exchange beyond its 60 second idle timeout; the 10 second limit you may see is the SDKs giving up client-side.",[14,413,414,415,418,419,422,423,426,427,222,430,433,434,437],{},"If ",[18,416,417],{},"reconnect: true",", the server restores the subscriptions this session had and lists them in ",[18,420,421],{},"restoredSubscriptions"," so the client can rebuild its local state. Each entry names the ",[18,424,425],{},"pattern"," that was subscribed, plus ",[18,428,429],{},"load_balance",[18,431,432],{},"load_balance_group"," and ",[18,435,436],{},"filters"," where they were set. A fresh connect starts with no subscriptions and an empty array.",[14,439,440,443,444,433,447,450,451,453,454,433,457,460],{},[18,441,442],{},"clientId"," is optional and only means anything for actor types whose sessions persist (",[18,445,446],{},"agent",[18,448,449],{},"orchestrator","). It names this client instance. A broker session belongs to an instance rather than to a credential, so two processes sharing one of those tokens are otherwise two attempts at the same session: the first keeps a resumable one and the rest get clean sessions. Give each worker its own stable ",[18,452,442],{}," and they each keep their own, so a worker that goes away still finds its queued messages when it returns. It must be stable across restarts: a random value per process orphans a session that goes on holding messages nobody collects. Letters, digits, ",[18,455,456],{},"-",[18,458,459],{},"_"," only, capped at 64 characters.",[85,462,464],{"id":463},"_2-heartbeat","2. Heartbeat",[14,466,467],{},"The heartbeat is client-driven. The client sends an empty binary frame (0 bytes) as a keep-alive and the server echoes an empty frame back; the server never sends one on its own. The SDKs send one every 30 seconds. A connection that sends nothing at all for 60 seconds is closed by the server. This is not a MessagePack message, just an empty WebSocket binary frame.",[14,469,470,471,476],{},"Heartbeats are also where the broker enforces client-token expiry (see ",[472,473,475],"a",{"href":474},"#disconnect-and-close-codes","close codes",") and starts its periodic revalidation of the actor, roughly every 10 minutes.",[85,478,480],{"id":479},"_3-re-authentication","3. Re-authentication",[14,482,483,484,488],{},"A connection authenticated with a short-lived ",[472,485,487],{"href":486},"/docs/client-tokens","client token"," can renew it in-band, with no disconnect and no resubscribe:",[97,490,491,523,559],{},[100,492,495],{"className":102,"code":493,"filename":494,"language":105,"meta":106,"style":106},"{ \"type\": \"reauth\", \"token\": \"\u003Cfresh client token>\" }\n","Request",[18,496,497],{"__ignoreMap":106},[110,498,499,502,505,507,510,512,515,517,520],{"class":112,"line":113},[110,500,501],{"class":123},"{ ",[110,503,504],{"class":130},"\"type\"",[110,506,134],{"class":123},[110,508,509],{"class":137},"\"reauth\"",[110,511,222],{"class":123},[110,513,514],{"class":130},"\"token\"",[110,516,134],{"class":123},[110,518,519],{"class":137},"\"\u003Cfresh client token>\"",[110,521,522],{"class":123}," }\n",[100,524,526],{"className":102,"code":525,"filename":253,"language":105,"meta":106,"style":106},"{ \"type\": \"reauth\", \"success\": true, \"authExpiresAt\": 1734567890 }\n",[18,527,528],{"__ignoreMap":106},[110,529,530,532,534,536,538,540,543,545,547,549,552,554,557],{"class":112,"line":113},[110,531,501],{"class":123},[110,533,504],{"class":130},[110,535,134],{"class":123},[110,537,509],{"class":137},[110,539,222],{"class":123},[110,541,542],{"class":130},"\"success\"",[110,544,134],{"class":123},[110,546,279],{"class":130},[110,548,222],{"class":123},[110,550,551],{"class":130},"\"authExpiresAt\"",[110,553,134],{"class":123},[110,555,556],{"class":130},"1734567890",[110,558,522],{"class":123},[100,560,562],{"className":102,"code":561,"filename":341,"language":105,"meta":106,"style":106},"{ \"type\": \"reauth\", \"success\": false, \"error\": \"actor_mismatch\" }\n",[18,563,564],{"__ignoreMap":106},[110,565,566,568,570,572,574,576,578,580,582,584,587,589,592],{"class":112,"line":113},[110,567,501],{"class":123},[110,569,504],{"class":130},[110,571,134],{"class":123},[110,573,509],{"class":137},[110,575,222],{"class":123},[110,577,542],{"class":130},[110,579,134],{"class":123},[110,581,178],{"class":130},[110,583,222],{"class":123},[110,585,586],{"class":130},"\"error\"",[110,588,134],{"class":123},[110,590,591],{"class":137},"\"actor_mismatch\"",[110,593,522],{"class":123},[14,595,596,597,600,601,603,604,606,607,610],{},"The new token must resolve to the same actor as the connection; a token for a different actor is refused with ",[18,598,599],{},"actor_mismatch",". An expired token is refused with ",[18,602,400],{},", and anything else fails with the same strings as ",[18,605,94],{},". On failure the connection stays open under its current credentials. ",[18,608,609],{},"authExpiresAt"," (unix seconds) is present when the new token carries an expiry.",[23,612,614],{"id":613},"client-to-server-messages","Client to Server Messages",[85,616,617],{"id":617},"subscribe",[97,619,620],{},[100,621,623],{"className":102,"code":622,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"subscribe\",\n  \"topic\": \"chat/general/messages\",\n  \"qos\": 1,\n  \"filters\": [\"user_123\", \"user_456\"],\n  \"loadBalance\": false,\n  \"loadBalanceGroup\": \"worker-pool-1\"\n}\n",[18,624,625,629,640,652,664,683,694,704],{"__ignoreMap":106},[110,626,627],{"class":112,"line":113},[110,628,124],{"class":123},[110,630,631,633,635,638],{"class":112,"line":120},[110,632,131],{"class":130},[110,634,134],{"class":123},[110,636,637],{"class":137},"\"subscribe\"",[110,639,141],{"class":123},[110,641,642,645,647,650],{"class":112,"line":127},[110,643,644],{"class":130},"  \"topic\"",[110,646,134],{"class":123},[110,648,649],{"class":137},"\"chat/general/messages\"",[110,651,141],{"class":123},[110,653,654,657,659,662],{"class":112,"line":144},[110,655,656],{"class":130},"  \"qos\"",[110,658,134],{"class":123},[110,660,661],{"class":130},"1",[110,663,141],{"class":123},[110,665,666,669,672,675,677,680],{"class":112,"line":157},[110,667,668],{"class":130},"  \"filters\"",[110,670,671],{"class":123},": [",[110,673,674],{"class":137},"\"user_123\"",[110,676,222],{"class":123},[110,678,679],{"class":137},"\"user_456\"",[110,681,682],{"class":123},"],\n",[110,684,685,688,690,692],{"class":112,"line":170},[110,686,687],{"class":130},"  \"loadBalance\"",[110,689,134],{"class":123},[110,691,178],{"class":130},[110,693,141],{"class":123},[110,695,696,699,701],{"class":112,"line":183},[110,697,698],{"class":130},"  \"loadBalanceGroup\"",[110,700,134],{"class":123},[110,702,703],{"class":137},"\"worker-pool-1\"\n",[110,705,706],{"class":112,"line":196},[110,707,210],{"class":123},[14,709,710,711,714,715,717],{},"Topics use human-readable slugs in the format ",[18,712,713],{},"app/room/topic",". The server resolves these to internal identifiers. The room must already exist: rooms are never created implicitly, and a subscribe to a room that is not provisioned is answered with an ",[18,716,232],{}," error (42940). Filters narrow delivery to specific entities within the topic. Load balancing distributes messages across clients in the same group (only one client receives each message).",[85,719,720],{"id":720},"unsubscribe",[97,722,723],{},[100,724,726],{"className":102,"code":725,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"unsubscribe\",\n  \"topic\": \"chat/general/messages\"\n}\n",[18,727,728,732,743,752],{"__ignoreMap":106},[110,729,730],{"class":112,"line":113},[110,731,124],{"class":123},[110,733,734,736,738,741],{"class":112,"line":120},[110,735,131],{"class":130},[110,737,134],{"class":123},[110,739,740],{"class":137},"\"unsubscribe\"",[110,742,141],{"class":123},[110,744,745,747,749],{"class":112,"line":127},[110,746,644],{"class":130},[110,748,134],{"class":123},[110,750,751],{"class":137},"\"chat/general/messages\"\n",[110,753,754],{"class":112,"line":144},[110,755,210],{"class":123},[85,757,758],{"id":758},"publish",[97,760,761],{},[100,762,764],{"className":102,"code":763,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"publish\",\n  \"topic\": \"chat/general/messages\",\n  \"data\": { \"text\": \"hello world\", \"sender\": \"user_12\" },\n  \"qos\": 1,\n  \"retain\": false,\n  \"filter\": \"user_123\",\n  \"msgRef\": \"1-k3j9x\"\n}\n",[18,765,766,770,781,791,820,830,841,852,862],{"__ignoreMap":106},[110,767,768],{"class":112,"line":113},[110,769,124],{"class":123},[110,771,772,774,776,779],{"class":112,"line":120},[110,773,131],{"class":130},[110,775,134],{"class":123},[110,777,778],{"class":137},"\"publish\"",[110,780,141],{"class":123},[110,782,783,785,787,789],{"class":112,"line":127},[110,784,644],{"class":130},[110,786,134],{"class":123},[110,788,649],{"class":137},[110,790,141],{"class":123},[110,792,793,796,799,802,804,807,809,812,814,817],{"class":112,"line":144},[110,794,795],{"class":130},"  \"data\"",[110,797,798],{"class":123},": { ",[110,800,801],{"class":130},"\"text\"",[110,803,134],{"class":123},[110,805,806],{"class":137},"\"hello world\"",[110,808,222],{"class":123},[110,810,811],{"class":130},"\"sender\"",[110,813,134],{"class":123},[110,815,816],{"class":137},"\"user_12\"",[110,818,819],{"class":123}," },\n",[110,821,822,824,826,828],{"class":112,"line":157},[110,823,656],{"class":130},[110,825,134],{"class":123},[110,827,661],{"class":130},[110,829,141],{"class":123},[110,831,832,835,837,839],{"class":112,"line":170},[110,833,834],{"class":130},"  \"retain\"",[110,836,134],{"class":123},[110,838,178],{"class":130},[110,840,141],{"class":123},[110,842,843,846,848,850],{"class":112,"line":183},[110,844,845],{"class":130},"  \"filter\"",[110,847,134],{"class":123},[110,849,674],{"class":137},[110,851,141],{"class":123},[110,853,854,857,859],{"class":112,"line":196},[110,855,856],{"class":130},"  \"msgRef\"",[110,858,134],{"class":123},[110,860,861],{"class":137},"\"1-k3j9x\"\n",[110,863,864],{"class":112,"line":207},[110,865,210],{"class":123},[14,867,868,871,872,875,876,879,880,882,883,885,886,888,889,891],{},[18,869,870],{},"qos"," is validated to 0, 1 or 2 (default 1) and passed to the broker's internal MQTT hop. ",[18,873,874],{},"retain"," keeps the last message on the topic for later subscribers. The ",[18,877,878],{},"filter"," field routes the message only to subscribers who have that filter value in their subscription; ",[18,881,436],{}," (an array) publishes to the AND-composite of several values. ",[18,884,228],{}," is any client-chosen string: when present, the server answers with a ",[18,887,236],{}," frame carrying the same ",[18,890,228],{},", and an error caused by this publish carries it too.",[14,893,894,895,898],{},"The publishing actor never receives its own message. An ",[18,896,897],{},"echo"," field is accepted for compatibility but does not change that.",[85,900,902],{"id":901},"setfilters","setFilters",[97,904,905],{},[100,906,908],{"className":102,"code":907,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"setFilters\",\n  \"topic\": \"chat/general/messages\",\n  \"filters\": [\"user_789\"]\n}\n",[18,909,910,914,925,935,947],{"__ignoreMap":106},[110,911,912],{"class":112,"line":113},[110,913,124],{"class":123},[110,915,916,918,920,923],{"class":112,"line":120},[110,917,131],{"class":130},[110,919,134],{"class":123},[110,921,922],{"class":137},"\"setFilters\"",[110,924,141],{"class":123},[110,926,927,929,931,933],{"class":112,"line":127},[110,928,644],{"class":130},[110,930,134],{"class":123},[110,932,649],{"class":137},[110,934,141],{"class":123},[110,936,937,939,941,944],{"class":112,"line":144},[110,938,668],{"class":130},[110,940,671],{"class":123},[110,942,943],{"class":137},"\"user_789\"",[110,945,946],{"class":123},"]\n",[110,948,949],{"class":112,"line":157},[110,950,210],{"class":123},[14,952,953,954,222,957,222,960,404,963,408],{},"Replaces the entire filter set for a topic. An empty array switches to wildcard mode (receive all messages). Max 100 filters per topic. Filter values cannot contain ",[18,955,956],{},"/",[18,958,959],{},"#",[18,961,962],{},"+",[18,964,965],{},"|",[85,967,968],{"id":968},"presence",[97,970,971],{},[100,972,974],{"className":102,"code":973,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"presence\",\n  \"roomId\": \"general\",\n  \"data\": { \"status\": \"online\", \"currentPage\": \"dashboard\" }\n}\n",[18,975,976,980,991,1003,1029],{"__ignoreMap":106},[110,977,978],{"class":112,"line":113},[110,979,124],{"class":123},[110,981,982,984,986,989],{"class":112,"line":120},[110,983,131],{"class":130},[110,985,134],{"class":123},[110,987,988],{"class":137},"\"presence\"",[110,990,141],{"class":123},[110,992,993,996,998,1001],{"class":112,"line":127},[110,994,995],{"class":130},"  \"roomId\"",[110,997,134],{"class":123},[110,999,1000],{"class":137},"\"general\"",[110,1002,141],{"class":123},[110,1004,1005,1007,1009,1012,1014,1017,1019,1022,1024,1027],{"class":112,"line":144},[110,1006,795],{"class":130},[110,1008,798],{"class":123},[110,1010,1011],{"class":130},"\"status\"",[110,1013,134],{"class":123},[110,1015,1016],{"class":137},"\"online\"",[110,1018,222],{"class":123},[110,1020,1021],{"class":130},"\"currentPage\"",[110,1023,134],{"class":123},[110,1025,1026],{"class":137},"\"dashboard\"",[110,1028,522],{"class":123},[110,1030,1031],{"class":112,"line":157},[110,1032,210],{"class":123},[14,1034,1035,1038,1039,1041,1042,1044],{},[18,1036,1037],{},"roomId"," is the room slug. A ",[18,1040,968],{}," frame without ",[18,1043,1037],{}," is accepted but deprecated: it is stored on the connection and not broadcast.",[85,1046,1048],{"id":1047},"getpresence","getPresence",[97,1050,1051],{},[100,1052,1054],{"className":102,"code":1053,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"getPresence\",\n  \"roomId\": \"general\"\n}\n",[18,1055,1056,1060,1071,1080],{"__ignoreMap":106},[110,1057,1058],{"class":112,"line":113},[110,1059,124],{"class":123},[110,1061,1062,1064,1066,1069],{"class":112,"line":120},[110,1063,131],{"class":130},[110,1065,134],{"class":123},[110,1067,1068],{"class":137},"\"getPresence\"",[110,1070,141],{"class":123},[110,1072,1073,1075,1077],{"class":112,"line":127},[110,1074,995],{"class":130},[110,1076,134],{"class":123},[110,1078,1079],{"class":137},"\"general\"\n",[110,1081,1082],{"class":112,"line":144},[110,1083,210],{"class":123},[85,1085,1087],{"id":1086},"ack-batchack","ack / batchAck",[97,1089,1090,1119],{},[100,1091,1094],{"className":102,"code":1092,"filename":1093,"language":105,"meta":106,"style":106},"{ \"type\": \"ack\", \"msgId\": \"550e8400-...\" }\n","Single ACK",[18,1095,1096],{"__ignoreMap":106},[110,1097,1098,1100,1102,1104,1107,1109,1112,1114,1117],{"class":112,"line":113},[110,1099,501],{"class":123},[110,1101,504],{"class":130},[110,1103,134],{"class":123},[110,1105,1106],{"class":137},"\"ack\"",[110,1108,222],{"class":123},[110,1110,1111],{"class":130},"\"msgId\"",[110,1113,134],{"class":123},[110,1115,1116],{"class":137},"\"550e8400-...\"",[110,1118,522],{"class":123},[100,1120,1123],{"className":102,"code":1121,"filename":1122,"language":105,"meta":106,"style":106},"{ \"type\": \"batchAck\", \"msgIds\": [\"id1\", \"id2\", \"id3\"] }\n","Batch ACK",[18,1124,1125],{"__ignoreMap":106},[110,1126,1127,1129,1131,1133,1136,1138,1141,1143,1146,1148,1151,1153,1156],{"class":112,"line":113},[110,1128,501],{"class":123},[110,1130,504],{"class":130},[110,1132,134],{"class":123},[110,1134,1135],{"class":137},"\"batchAck\"",[110,1137,222],{"class":123},[110,1139,1140],{"class":130},"\"msgIds\"",[110,1142,671],{"class":123},[110,1144,1145],{"class":137},"\"id1\"",[110,1147,222],{"class":123},[110,1149,1150],{"class":137},"\"id2\"",[110,1152,222],{"class":123},[110,1154,1155],{"class":137},"\"id3\"",[110,1157,1158],{"class":123},"] }\n",[14,1160,1161,1162,1165],{},"Sent in response to a message with ",[18,1163,1164],{},"requiresAck: true","; the SDKs do this for you. Acks mark the message delivered in the message store.",[85,1167,1169],{"id":1168},"lobbysubscribe-lobbyunsubscribe-getlobbypresence","lobbySubscribe / lobbyUnsubscribe / getLobbyPresence",[97,1171,1172,1201,1228],{},[100,1173,1176],{"className":102,"code":1174,"filename":1175,"language":105,"meta":106,"style":106},"{ \"type\": \"lobbySubscribe\", \"lobbyId\": \"active-trips\" }\n","Subscribe",[18,1177,1178],{"__ignoreMap":106},[110,1179,1180,1182,1184,1186,1189,1191,1194,1196,1199],{"class":112,"line":113},[110,1181,501],{"class":123},[110,1183,504],{"class":130},[110,1185,134],{"class":123},[110,1187,1188],{"class":137},"\"lobbySubscribe\"",[110,1190,222],{"class":123},[110,1192,1193],{"class":130},"\"lobbyId\"",[110,1195,134],{"class":123},[110,1197,1198],{"class":137},"\"active-trips\"",[110,1200,522],{"class":123},[100,1202,1205],{"className":102,"code":1203,"filename":1204,"language":105,"meta":106,"style":106},"{ \"type\": \"lobbyUnsubscribe\", \"lobbyId\": \"active-trips\" }\n","Unsubscribe",[18,1206,1207],{"__ignoreMap":106},[110,1208,1209,1211,1213,1215,1218,1220,1222,1224,1226],{"class":112,"line":113},[110,1210,501],{"class":123},[110,1212,504],{"class":130},[110,1214,134],{"class":123},[110,1216,1217],{"class":137},"\"lobbyUnsubscribe\"",[110,1219,222],{"class":123},[110,1221,1193],{"class":130},[110,1223,134],{"class":123},[110,1225,1198],{"class":137},[110,1227,522],{"class":123},[100,1229,1232],{"className":102,"code":1230,"filename":1231,"language":105,"meta":106,"style":106},"{ \"type\": \"getLobbyPresence\", \"lobbyId\": \"active-trips\" }\n","Get Presence",[18,1233,1234],{"__ignoreMap":106},[110,1235,1236,1238,1240,1242,1245,1247,1249,1251,1253],{"class":112,"line":113},[110,1237,501],{"class":123},[110,1239,504],{"class":130},[110,1241,134],{"class":123},[110,1243,1244],{"class":137},"\"getLobbyPresence\"",[110,1246,222],{"class":123},[110,1248,1193],{"class":130},[110,1250,134],{"class":123},[110,1252,1198],{"class":137},[110,1254,522],{"class":123},[14,1256,1257,1260,1261,1263,1264,408],{},[18,1258,1259],{},"lobbyId"," is the lobby slug. A lobby the actor cannot reach is refused with a ",[18,1262,240],{}," error carrying the ",[18,1265,1259],{},[23,1267,1269],{"id":1268},"server-to-client-messages","Server to Client Messages",[85,1271,1272],{"id":1272},"message",[97,1274,1275],{},[100,1276,1278],{"className":102,"code":1277,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"message\",\n  \"topic\": \"chat/general/messages\",\n  \"data\": { \"text\": \"hello world\", \"sender\": \"user_12\" },\n  \"msgId\": \"550e8400-...\",\n  \"requiresAck\": true,\n  \"filter\": \"user_123\"\n}\n",[18,1279,1280,1284,1295,1305,1327,1338,1349,1358],{"__ignoreMap":106},[110,1281,1282],{"class":112,"line":113},[110,1283,124],{"class":123},[110,1285,1286,1288,1290,1293],{"class":112,"line":120},[110,1287,131],{"class":130},[110,1289,134],{"class":123},[110,1291,1292],{"class":137},"\"message\"",[110,1294,141],{"class":123},[110,1296,1297,1299,1301,1303],{"class":112,"line":127},[110,1298,644],{"class":130},[110,1300,134],{"class":123},[110,1302,649],{"class":137},[110,1304,141],{"class":123},[110,1306,1307,1309,1311,1313,1315,1317,1319,1321,1323,1325],{"class":112,"line":144},[110,1308,795],{"class":130},[110,1310,798],{"class":123},[110,1312,801],{"class":130},[110,1314,134],{"class":123},[110,1316,806],{"class":137},[110,1318,222],{"class":123},[110,1320,811],{"class":130},[110,1322,134],{"class":123},[110,1324,816],{"class":137},[110,1326,819],{"class":123},[110,1328,1329,1332,1334,1336],{"class":112,"line":157},[110,1330,1331],{"class":130},"  \"msgId\"",[110,1333,134],{"class":123},[110,1335,1116],{"class":137},[110,1337,141],{"class":123},[110,1339,1340,1343,1345,1347],{"class":112,"line":170},[110,1341,1342],{"class":130},"  \"requiresAck\"",[110,1344,134],{"class":123},[110,1346,279],{"class":130},[110,1348,141],{"class":123},[110,1350,1351,1353,1355],{"class":112,"line":183},[110,1352,845],{"class":130},[110,1354,134],{"class":123},[110,1356,1357],{"class":137},"\"user_123\"\n",[110,1359,1360],{"class":112,"line":196},[110,1361,210],{"class":123},[14,1363,1364,433,1367,1370,1371,1373,1374,1377,1378,1382],{},[18,1365,1366],{},"msgId",[18,1368,1369],{},"requiresAck"," are present when the message was stored (logging enabled for the topic). ",[18,1372,878],{}," is present when the message was published with one. Messages replayed to a load-balanced worker carry ",[18,1375,1376],{},"isReplay: true","; see ",[472,1379,1381],{"href":1380},"/docs/concepts/replay","Replay"," for when that happens.",[85,1384,1386],{"id":1385},"subscribed-unsubscribed","subscribed / unsubscribed",[97,1388,1389,1426],{},[100,1390,1393],{"className":102,"code":1391,"filename":1392,"language":105,"meta":106,"style":106},"{ \"type\": \"subscribed\", \"topic\": \"chat/general/messages\", \"loadBalance\": false }\n","Subscribed",[18,1394,1395],{"__ignoreMap":106},[110,1396,1397,1399,1401,1403,1406,1408,1411,1413,1415,1417,1420,1422,1424],{"class":112,"line":113},[110,1398,501],{"class":123},[110,1400,504],{"class":130},[110,1402,134],{"class":123},[110,1404,1405],{"class":137},"\"subscribed\"",[110,1407,222],{"class":123},[110,1409,1410],{"class":130},"\"topic\"",[110,1412,134],{"class":123},[110,1414,649],{"class":137},[110,1416,222],{"class":123},[110,1418,1419],{"class":130},"\"loadBalance\"",[110,1421,134],{"class":123},[110,1423,178],{"class":130},[110,1425,522],{"class":123},[100,1427,1430],{"className":102,"code":1428,"filename":1429,"language":105,"meta":106,"style":106},"{ \"type\": \"unsubscribed\", \"topic\": \"chat/general/messages\" }\n","Unsubscribed",[18,1431,1432],{"__ignoreMap":106},[110,1433,1434,1436,1438,1440,1443,1445,1447,1449,1451],{"class":112,"line":113},[110,1435,501],{"class":123},[110,1437,504],{"class":130},[110,1439,134],{"class":123},[110,1441,1442],{"class":137},"\"unsubscribed\"",[110,1444,222],{"class":123},[110,1446,1410],{"class":130},[110,1448,134],{"class":123},[110,1450,649],{"class":137},[110,1452,522],{"class":123},[85,1454,236],{"id":236},[97,1456,1457],{},[100,1458,1460],{"className":102,"code":1459,"filename":104,"language":105,"meta":106,"style":106},"{ \"type\": \"published\", \"topic\": \"chat/general/messages\", \"msgRef\": \"1-k3j9x\" }\n",[18,1461,1462],{"__ignoreMap":106},[110,1463,1464,1466,1468,1470,1473,1475,1477,1479,1481,1483,1486,1488,1491],{"class":112,"line":113},[110,1465,501],{"class":123},[110,1467,504],{"class":130},[110,1469,134],{"class":123},[110,1471,1472],{"class":137},"\"published\"",[110,1474,222],{"class":123},[110,1476,1410],{"class":130},[110,1478,134],{"class":123},[110,1480,649],{"class":137},[110,1482,222],{"class":123},[110,1484,1485],{"class":130},"\"msgRef\"",[110,1487,134],{"class":123},[110,1489,1490],{"class":137},"\"1-k3j9x\"",[110,1492,522],{"class":123},[14,1494,1495,1496,1498],{},"Sent for a publish that carried a ",[18,1497,228],{}," (protocol version 2). It confirms the broker accepted the message; it is not an end-to-end delivery receipt. The SDKs surface it as the emit callback.",[85,1500,1502],{"id":1501},"filtersupdated","filtersUpdated",[97,1504,1505],{},[100,1506,1508],{"className":102,"code":1507,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"filtersUpdated\",\n  \"topic\": \"chat/general/messages\",\n  \"filters\": [\"user_789\"]\n}\n",[18,1509,1510,1514,1525,1535,1545],{"__ignoreMap":106},[110,1511,1512],{"class":112,"line":113},[110,1513,124],{"class":123},[110,1515,1516,1518,1520,1523],{"class":112,"line":120},[110,1517,131],{"class":130},[110,1519,134],{"class":123},[110,1521,1522],{"class":137},"\"filtersUpdated\"",[110,1524,141],{"class":123},[110,1526,1527,1529,1531,1533],{"class":112,"line":127},[110,1528,644],{"class":130},[110,1530,134],{"class":123},[110,1532,649],{"class":137},[110,1534,141],{"class":123},[110,1536,1537,1539,1541,1543],{"class":112,"line":144},[110,1538,668],{"class":130},[110,1540,671],{"class":123},[110,1542,943],{"class":137},[110,1544,946],{"class":123},[110,1546,1547],{"class":112,"line":157},[110,1548,210],{"class":123},[85,1550,1552],{"id":1551},"presence-presencelist","presence / presenceList",[97,1554,1555,1629],{},[100,1556,1559],{"className":102,"code":1557,"filename":1558,"language":105,"meta":106,"style":106},"{\n  \"type\": \"presence\",\n  \"event\": \"join\",\n  \"data\": {\n    \"actor_token_id\": \"actor_123\",\n    \"presence\": { \"status\": \"online\" }\n  }\n}\n","Presence Event",[18,1560,1561,1565,1575,1587,1594,1605,1620,1625],{"__ignoreMap":106},[110,1562,1563],{"class":112,"line":113},[110,1564,124],{"class":123},[110,1566,1567,1569,1571,1573],{"class":112,"line":120},[110,1568,131],{"class":130},[110,1570,134],{"class":123},[110,1572,988],{"class":137},[110,1574,141],{"class":123},[110,1576,1577,1580,1582,1585],{"class":112,"line":127},[110,1578,1579],{"class":130},"  \"event\"",[110,1581,134],{"class":123},[110,1583,1584],{"class":137},"\"join\"",[110,1586,141],{"class":123},[110,1588,1589,1591],{"class":112,"line":144},[110,1590,795],{"class":130},[110,1592,1593],{"class":123},": {\n",[110,1595,1596,1599,1601,1603],{"class":112,"line":157},[110,1597,1598],{"class":130},"    \"actor_token_id\"",[110,1600,134],{"class":123},[110,1602,291],{"class":137},[110,1604,141],{"class":123},[110,1606,1607,1610,1612,1614,1616,1618],{"class":112,"line":170},[110,1608,1609],{"class":130},"    \"presence\"",[110,1611,798],{"class":123},[110,1613,1011],{"class":130},[110,1615,134],{"class":123},[110,1617,1016],{"class":137},[110,1619,522],{"class":123},[110,1621,1622],{"class":112,"line":183},[110,1623,1624],{"class":123},"  }\n",[110,1626,1627],{"class":112,"line":196},[110,1628,210],{"class":123},[100,1630,1633],{"className":102,"code":1631,"filename":1632,"language":105,"meta":106,"style":106},"{\n  \"type\": \"presenceList\",\n  \"roomId\": \"general\",\n  \"data\": [\n    { \"actorTokenId\": \"actor_123\", \"presence\": { \"status\": \"online\" }, \"joinedAt\": 1634567890 }\n  ]\n}\n","Presence Snapshot",[18,1634,1635,1639,1650,1660,1667,1704,1709],{"__ignoreMap":106},[110,1636,1637],{"class":112,"line":113},[110,1638,124],{"class":123},[110,1640,1641,1643,1645,1648],{"class":112,"line":120},[110,1642,131],{"class":130},[110,1644,134],{"class":123},[110,1646,1647],{"class":137},"\"presenceList\"",[110,1649,141],{"class":123},[110,1651,1652,1654,1656,1658],{"class":112,"line":127},[110,1653,995],{"class":130},[110,1655,134],{"class":123},[110,1657,1000],{"class":137},[110,1659,141],{"class":123},[110,1661,1662,1664],{"class":112,"line":144},[110,1663,795],{"class":130},[110,1665,1666],{"class":123},": [\n",[110,1668,1669,1672,1675,1677,1679,1681,1683,1685,1687,1689,1691,1694,1697,1699,1702],{"class":112,"line":157},[110,1670,1671],{"class":123},"    { ",[110,1673,1674],{"class":130},"\"actorTokenId\"",[110,1676,134],{"class":123},[110,1678,291],{"class":137},[110,1680,222],{"class":123},[110,1682,988],{"class":130},[110,1684,798],{"class":123},[110,1686,1011],{"class":130},[110,1688,134],{"class":123},[110,1690,1016],{"class":137},[110,1692,1693],{"class":123}," }, ",[110,1695,1696],{"class":130},"\"joinedAt\"",[110,1698,134],{"class":123},[110,1700,1701],{"class":130},"1634567890",[110,1703,522],{"class":123},[110,1705,1706],{"class":112,"line":170},[110,1707,1708],{"class":123},"  ]\n",[110,1710,1711],{"class":112,"line":183},[110,1712,210],{"class":123},[14,1714,1715,1718,1719,222,1722,404,1725,1728,1729,1731,1732,1735,1736,1738,1739,1742,1743,1746],{},[18,1716,1717],{},"event"," is ",[18,1720,1721],{},"join",[18,1723,1724],{},"update",[18,1726,1727],{},"leave","; a ",[18,1730,1727],{}," event carries only ",[18,1733,1734],{},"actor_token_id",". Note the key spelling: events use ",[18,1737,1734],{},", snapshots use ",[18,1740,1741],{},"actorTokenId",", and ",[18,1744,1745],{},"joinedAt"," (unix seconds) appears only in snapshots.",[85,1748,1750],{"id":1749},"lobbysubscribed-lobbyunsubscribed-lobbypresencelist-lobbypresence","lobbySubscribed / lobbyUnsubscribed / lobbyPresenceList / lobbyPresence",[97,1752,1753,1843,1870,1933],{},[100,1754,1757],{"className":102,"code":1755,"filename":1756,"language":105,"meta":106,"style":106},"{\n  \"type\": \"lobbySubscribed\",\n  \"lobbyId\": \"active-trips\",\n  \"presence\": {\n    \"room_1\": { \"actor_123\": { \"status\": \"driving\" } },\n    \"room_2\": { \"actor_456\": { \"status\": \"waiting\" } }\n  }\n}\n","Lobby Subscribed",[18,1758,1759,1763,1774,1785,1792,1813,1835,1839],{"__ignoreMap":106},[110,1760,1761],{"class":112,"line":113},[110,1762,124],{"class":123},[110,1764,1765,1767,1769,1772],{"class":112,"line":120},[110,1766,131],{"class":130},[110,1768,134],{"class":123},[110,1770,1771],{"class":137},"\"lobbySubscribed\"",[110,1773,141],{"class":123},[110,1775,1776,1779,1781,1783],{"class":112,"line":127},[110,1777,1778],{"class":130},"  \"lobbyId\"",[110,1780,134],{"class":123},[110,1782,1198],{"class":137},[110,1784,141],{"class":123},[110,1786,1787,1790],{"class":112,"line":144},[110,1788,1789],{"class":130},"  \"presence\"",[110,1791,1593],{"class":123},[110,1793,1794,1797,1799,1801,1803,1805,1807,1810],{"class":112,"line":157},[110,1795,1796],{"class":130},"    \"room_1\"",[110,1798,798],{"class":123},[110,1800,291],{"class":130},[110,1802,798],{"class":123},[110,1804,1011],{"class":130},[110,1806,134],{"class":123},[110,1808,1809],{"class":137},"\"driving\"",[110,1811,1812],{"class":123}," } },\n",[110,1814,1815,1818,1820,1823,1825,1827,1829,1832],{"class":112,"line":170},[110,1816,1817],{"class":130},"    \"room_2\"",[110,1819,798],{"class":123},[110,1821,1822],{"class":130},"\"actor_456\"",[110,1824,798],{"class":123},[110,1826,1011],{"class":130},[110,1828,134],{"class":123},[110,1830,1831],{"class":137},"\"waiting\"",[110,1833,1834],{"class":123}," } }\n",[110,1836,1837],{"class":112,"line":183},[110,1838,1624],{"class":123},[110,1840,1841],{"class":112,"line":196},[110,1842,210],{"class":123},[100,1844,1847],{"className":102,"code":1845,"filename":1846,"language":105,"meta":106,"style":106},"{ \"type\": \"lobbyUnsubscribed\", \"lobbyId\": \"active-trips\" }\n","Lobby Unsubscribed",[18,1848,1849],{"__ignoreMap":106},[110,1850,1851,1853,1855,1857,1860,1862,1864,1866,1868],{"class":112,"line":113},[110,1852,501],{"class":123},[110,1854,504],{"class":130},[110,1856,134],{"class":123},[110,1858,1859],{"class":137},"\"lobbyUnsubscribed\"",[110,1861,222],{"class":123},[110,1863,1193],{"class":130},[110,1865,134],{"class":123},[110,1867,1198],{"class":137},[110,1869,522],{"class":123},[100,1871,1874],{"className":102,"code":1872,"filename":1873,"language":105,"meta":106,"style":106},"{\n  \"type\": \"lobbyPresenceList\",\n  \"lobbyId\": \"active-trips\",\n  \"presence\": {\n    \"room_1\": { \"actor_123\": { \"status\": \"driving\" } }\n  }\n}\n","Lobby Presence List",[18,1875,1876,1880,1891,1901,1907,1925,1929],{"__ignoreMap":106},[110,1877,1878],{"class":112,"line":113},[110,1879,124],{"class":123},[110,1881,1882,1884,1886,1889],{"class":112,"line":120},[110,1883,131],{"class":130},[110,1885,134],{"class":123},[110,1887,1888],{"class":137},"\"lobbyPresenceList\"",[110,1890,141],{"class":123},[110,1892,1893,1895,1897,1899],{"class":112,"line":127},[110,1894,1778],{"class":130},[110,1896,134],{"class":123},[110,1898,1198],{"class":137},[110,1900,141],{"class":123},[110,1902,1903,1905],{"class":112,"line":144},[110,1904,1789],{"class":130},[110,1906,1593],{"class":123},[110,1908,1909,1911,1913,1915,1917,1919,1921,1923],{"class":112,"line":157},[110,1910,1796],{"class":130},[110,1912,798],{"class":123},[110,1914,291],{"class":130},[110,1916,798],{"class":123},[110,1918,1011],{"class":130},[110,1920,134],{"class":123},[110,1922,1809],{"class":137},[110,1924,1834],{"class":123},[110,1926,1927],{"class":112,"line":170},[110,1928,1624],{"class":123},[110,1930,1931],{"class":112,"line":183},[110,1932,210],{"class":123},[100,1934,1937],{"className":102,"code":1935,"filename":1936,"language":105,"meta":106,"style":106},"{\n  \"type\": \"lobbyPresence\",\n  \"event\": \"join\",\n  \"lobbyId\": \"active-trips\",\n  \"roomId\": \"room_1\",\n  \"actorId\": \"actor_789\",\n  \"data\": { \"status\": \"driving\" }\n}\n","Lobby Presence Event",[18,1938,1939,1943,1954,1964,1974,1985,1997,2011],{"__ignoreMap":106},[110,1940,1941],{"class":112,"line":113},[110,1942,124],{"class":123},[110,1944,1945,1947,1949,1952],{"class":112,"line":120},[110,1946,131],{"class":130},[110,1948,134],{"class":123},[110,1950,1951],{"class":137},"\"lobbyPresence\"",[110,1953,141],{"class":123},[110,1955,1956,1958,1960,1962],{"class":112,"line":127},[110,1957,1579],{"class":130},[110,1959,134],{"class":123},[110,1961,1584],{"class":137},[110,1963,141],{"class":123},[110,1965,1966,1968,1970,1972],{"class":112,"line":144},[110,1967,1778],{"class":130},[110,1969,134],{"class":123},[110,1971,1198],{"class":137},[110,1973,141],{"class":123},[110,1975,1976,1978,1980,1983],{"class":112,"line":157},[110,1977,995],{"class":130},[110,1979,134],{"class":123},[110,1981,1982],{"class":137},"\"room_1\"",[110,1984,141],{"class":123},[110,1986,1987,1990,1992,1995],{"class":112,"line":170},[110,1988,1989],{"class":130},"  \"actorId\"",[110,1991,134],{"class":123},[110,1993,1994],{"class":137},"\"actor_789\"",[110,1996,141],{"class":123},[110,1998,1999,2001,2003,2005,2007,2009],{"class":112,"line":183},[110,2000,795],{"class":130},[110,2002,798],{"class":123},[110,2004,1011],{"class":130},[110,2006,134],{"class":123},[110,2008,1809],{"class":137},[110,2010,522],{"class":123},[110,2012,2013],{"class":112,"line":196},[110,2014,210],{"class":123},[14,2016,2017,2020,2021,2024,2025,2020,2028,2031,2032,2035],{},[18,2018,2019],{},"lobbySubscribed"," answers ",[18,2022,2023],{},"lobbySubscribe"," with a snapshot keyed by room slug, then by actor; ",[18,2026,2027],{},"lobbyPresenceList",[18,2029,2030],{},"getLobbyPresence"," with the same shape. ",[18,2033,2034],{},"lobbyPresence"," events follow for every join, update and leave in any room of the lobby.",[85,2037,2039],{"id":2038},"replaystart-replayend","replayStart / replayEnd",[97,2041,2042],{},[100,2043,2045],{"className":102,"code":2044,"filename":104,"language":105,"meta":106,"style":106},"{ \"type\": \"replayStart\", \"count\": 247 }\n// ... replayed messages arrive with isReplay: true ...\n{ \"type\": \"replayEnd\", \"replayed\": 247 }\n",[18,2046,2047,2070,2075],{"__ignoreMap":106},[110,2048,2049,2051,2053,2055,2058,2060,2063,2065,2068],{"class":112,"line":113},[110,2050,501],{"class":123},[110,2052,504],{"class":130},[110,2054,134],{"class":123},[110,2056,2057],{"class":137},"\"replayStart\"",[110,2059,222],{"class":123},[110,2061,2062],{"class":130},"\"count\"",[110,2064,134],{"class":123},[110,2066,2067],{"class":130},"247",[110,2069,522],{"class":123},[110,2071,2072],{"class":112,"line":120},[110,2073,2074],{"class":116},"// ... replayed messages arrive with isReplay: true ...\n",[110,2076,2077,2079,2081,2083,2086,2088,2091,2093,2095],{"class":112,"line":127},[110,2078,501],{"class":123},[110,2080,504],{"class":130},[110,2082,134],{"class":123},[110,2084,2085],{"class":137},"\"replayEnd\"",[110,2087,222],{"class":123},[110,2089,2090],{"class":130},"\"replayed\"",[110,2092,134],{"class":123},[110,2094,2067],{"class":130},[110,2096,522],{"class":123},[14,2098,2099,2100,408],{},"Only sent to load-balanced worker groups with persistent sessions; an ordinary reconnect restores subscriptions and replays nothing. See ",[472,2101,1381],{"href":1380},[85,2103,2104],{"id":2104},"hydration",[97,2106,2107],{},[100,2108,2110],{"className":102,"code":2109,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"hydration\",\n  \"topic\": \"messages\",\n  \"data\": { \"recentMessages\": [] }\n}\n",[18,2111,2112,2116,2127,2138,2150],{"__ignoreMap":106},[110,2113,2114],{"class":112,"line":113},[110,2115,124],{"class":123},[110,2117,2118,2120,2122,2125],{"class":112,"line":120},[110,2119,131],{"class":130},[110,2121,134],{"class":123},[110,2123,2124],{"class":137},"\"hydration\"",[110,2126,141],{"class":123},[110,2128,2129,2131,2133,2136],{"class":112,"line":127},[110,2130,644],{"class":130},[110,2132,134],{"class":123},[110,2134,2135],{"class":137},"\"messages\"",[110,2137,141],{"class":123},[110,2139,2140,2142,2144,2147],{"class":112,"line":144},[110,2141,795],{"class":130},[110,2143,798],{"class":123},[110,2145,2146],{"class":130},"\"recentMessages\"",[110,2148,2149],{"class":123},": [] }\n",[110,2151,2152],{"class":112,"line":157},[110,2153,210],{"class":123},[14,2155,2156,2157,2160,2161,2164,2165,2167,2168,408],{},"Sent once per subscribe when the app (or the topic) has a hydration webhook configured; ",[18,2158,2159],{},"data"," is whatever the webhook returned. ",[18,2162,2163],{},"topic"," is the bare topic name, not the full ",[18,2166,713],{}," pattern. See ",[472,2169,2171],{"href":2170},"/docs/concepts/webhooks","Webhooks",[85,2173,387],{"id":387},[97,2175,2176],{},[100,2177,2179],{"className":102,"code":2178,"filename":104,"language":105,"meta":106,"style":106},"{\n  \"type\": \"error\",\n  \"code\": 42940,\n  \"error\": \"unknown_topic\",\n  \"topic\": \"chat/general/messages\",\n  \"hint\": \"room is not configured. Provision it via the control-plane rooms API before use.\",\n  \"msgRef\": \"1-k3j9x\"\n}\n",[18,2180,2181,2185,2195,2207,2218,2228,2240,2248],{"__ignoreMap":106},[110,2182,2183],{"class":112,"line":113},[110,2184,124],{"class":123},[110,2186,2187,2189,2191,2193],{"class":112,"line":120},[110,2188,131],{"class":130},[110,2190,134],{"class":123},[110,2192,586],{"class":137},[110,2194,141],{"class":123},[110,2196,2197,2200,2202,2205],{"class":112,"line":127},[110,2198,2199],{"class":130},"  \"code\"",[110,2201,134],{"class":123},[110,2203,2204],{"class":130},"42940",[110,2206,141],{"class":123},[110,2208,2209,2211,2213,2216],{"class":112,"line":144},[110,2210,372],{"class":130},[110,2212,134],{"class":123},[110,2214,2215],{"class":137},"\"unknown_topic\"",[110,2217,141],{"class":123},[110,2219,2220,2222,2224,2226],{"class":112,"line":157},[110,2221,644],{"class":130},[110,2223,134],{"class":123},[110,2225,649],{"class":137},[110,2227,141],{"class":123},[110,2229,2230,2233,2235,2238],{"class":112,"line":170},[110,2231,2232],{"class":130},"  \"hint\"",[110,2234,134],{"class":123},[110,2236,2237],{"class":137},"\"room is not configured. Provision it via the control-plane rooms API before use.\"",[110,2239,141],{"class":123},[110,2241,2242,2244,2246],{"class":112,"line":183},[110,2243,856],{"class":130},[110,2245,134],{"class":123},[110,2247,861],{"class":137},[110,2249,2250],{"class":112,"line":196},[110,2251,210],{"class":123},[14,2253,2254,433,2256,2258,2259,2261,2262,2264],{},[18,2255,18],{},[18,2257,225],{}," are present where the table lists them. ",[18,2260,2163],{}," names the topic the request referred to. ",[18,2263,228],{}," is present when the error was caused by a publish that carried one.",[2266,2267,2268,2284],"table",{},[2269,2270,2271],"thead",{},[2272,2273,2274,2278,2281],"tr",{},[2275,2276,2277],"th",{},"Code",[2275,2279,2280],{},"Error",[2275,2282,2283],{},"Description",[2285,2286,2287,2301,2314,2330,2344,2361,2375,2389,2401],"tbody",{},[2272,2288,2289,2293,2298],{},[2290,2291,2292],"td",{},"42910",[2290,2294,2295],{},[18,2296,2297],{},"rate_limit_exceeded",[2290,2299,2300],{},"More than 50 publishes per second on this connection",[2272,2302,2303,2306,2311],{},[2290,2304,2305],{},"42920",[2290,2307,2308],{},[18,2309,2310],{},"monthly_quota_exceeded",[2290,2312,2313],{},"Plan message quota reached",[2272,2315,2316,2319,2324],{},[2290,2317,2318],{},"42930",[2290,2320,2321],{},[18,2322,2323],{},"message_too_large",[2290,2325,2326,2327],{},"Payload exceeds 900 KB; the frame carries ",[18,2328,2329],{},"maxSizeBytes",[2272,2331,2332,2334,2338],{},[2290,2333,2204],{},[2290,2335,2336],{},[18,2337,232],{},[2290,2339,2340,2341,2343],{},"The room is not provisioned or not accessible to this actor; carries a ",[18,2342,225],{},". Protocol version 2 only",[2272,2345,2346,2348,2352],{},[2290,2347,456],{},[2290,2349,2350],{},[18,2351,240],{},[2290,2353,2354,2355,2357,2358,2360],{},"What a version 1 client gets instead of ",[18,2356,232],{},"; also a lobby the actor cannot reach (carries ",[18,2359,1259],{},")",[2272,2362,2363,2365,2370],{},[2290,2364,456],{},[2290,2366,2367],{},[18,2368,2369],{},"not_authenticated",[2290,2371,2372,2373],{},"Any frame sent before a successful ",[18,2374,94],{},[2272,2376,2377,2379,2384],{},[2290,2378,456],{},[2290,2380,2381],{},[18,2382,2383],{},"not_subscribed",[2290,2385,2386,2388],{},[18,2387,902],{}," on a topic this connection has not subscribed",[2272,2390,2391,2393,2398],{},[2290,2392,456],{},[2290,2394,2395],{},[18,2396,2397],{},"invalid_filter_chars (/, #, +, | not allowed)",[2290,2399,2400],{},"A filter value contains a reserved character",[2272,2402,2403,2405,2410],{},[2290,2404,456],{},[2290,2406,2407],{},[18,2408,2409],{},"too_many_filters (max 100)",[2290,2411,2412],{},"More than 100 filters on one subscription",[85,2414,2416],{"id":2415},"disconnect-and-close-codes","disconnect and close codes",[97,2418,2419],{},[100,2420,2422],{"className":102,"code":2421,"filename":104,"language":105,"meta":106,"style":106},"{ \"type\": \"disconnect\", \"reason\": \"token_expired\" }\n",[18,2423,2424],{"__ignoreMap":106},[110,2425,2426,2428,2430,2432,2435,2437,2440,2442,2445],{"class":112,"line":113},[110,2427,501],{"class":123},[110,2429,504],{"class":130},[110,2431,134],{"class":123},[110,2433,2434],{"class":137},"\"disconnect\"",[110,2436,222],{"class":123},[110,2438,2439],{"class":130},"\"reason\"",[110,2441,134],{"class":123},[110,2443,2444],{"class":137},"\"token_expired\"",[110,2446,522],{"class":123},[14,2448,2449],{},"The server closes a connection with one of these WebSocket close codes:",[2266,2451,2452,2465],{},[2269,2453,2454],{},[2272,2455,2456,2459,2462],{},[2275,2457,2458],{},"Close code",[2275,2460,2461],{},"Reason",[2275,2463,2464],{},"When",[2285,2466,2467,2497,2511],{},[2272,2468,2469,2474,2490],{},[2290,2470,2471],{},[18,2472,2473],{},"4001",[2290,2475,2476,222,2479,222,2482,222,2484,404,2487],{},[18,2477,2478],{},"token_not_found",[18,2480,2481],{},"token_revoked",[18,2483,400],{},[18,2485,2486],{},"project_not_found",[18,2488,2489],{},"scope_inactive",[2290,2491,2492,2493,2496],{},"The periodic revalidation of the actor failed. The reason travels in the close frame; no ",[18,2494,2495],{},"disconnect"," message precedes it",[2272,2498,2499,2504,2508],{},[2290,2500,2501],{},[18,2502,2503],{},"4002",[2290,2505,2506],{},[18,2507,403],{},[2290,2509,2510],{},"Revalidation found the organization over its connection limit, for example after a plan change",[2272,2512,2513,2518,2522],{},[2290,2514,2515],{},[18,2516,2517],{},"4003",[2290,2519,2520],{},[18,2521,400],{},[2290,2523,2524,2525,2527],{},"The client token (JWT) this connection authenticated with has expired. A ",[18,2526,2495],{}," frame with the same reason is sent first; SDKs with a token provider reconnect with a fresh token",[23,2529,2531],{"id":2530},"delivery-guarantees-qos","Delivery Guarantees (QoS)",[14,2533,2534],{},"QoS is specified per message on both subscribe and publish. Default is 1. The value is validated to 0, 1 or 2 and passed to the broker's internal MQTT hop, where it has the usual MQTT meaning.",[14,2536,2537,2538,2540,2541,2543,2544,408],{},"On the WebSocket leg between your client and the broker there is one acknowledgement, the optional ",[18,2539,236],{}," frame (protocol version 2, ",[18,2542,228],{},"), and no resend. There is no exactly-once guarantee at any QoS level: design consumers to tolerate a duplicate. See ",[472,2545,2547],{"href":2546},"/docs/concepts/qos","Quality of Service",[23,2549,2551],{"id":2550},"why-messagepack","Why MessagePack?",[14,2553,2554],{},"MessagePack encodes the same data as JSON in 30-50% fewer bytes. For real-time applications pushing thousands of messages per second, this reduction in payload size translates directly to lower bandwidth costs and faster delivery.",[28,2556,2557,2560,2563,2566],{},[31,2558,2559],{},"Binary format, no parsing ambiguity",[31,2561,2562],{},"Native support for binary data (no Base64 overhead)",[31,2564,2565],{},"Schema-less, same flexibility as JSON",[31,2567,2568],{},"Implementations available in every major language",[23,2570,2572],{"id":2571},"next-steps","Next Steps",[28,2574,2575,2580,2587,2594],{},[31,2576,2577,2579],{},[472,2578,2547],{"href":2546}," - configure per-message delivery guarantees",[31,2581,2582,2586],{},[472,2583,2585],{"href":2584},"/docs/concepts/filters","Filters"," - narrow message delivery within a topic",[31,2588,2589,2593],{},[472,2590,2592],{"href":2591},"/docs/concepts/presence","Presence"," - track who is online",[31,2595,2596,2600],{},[472,2597,2599],{"href":2598},"/docs/sdks","SDKs"," - the protocol is handled for you in every SDK",[2602,2603,2604],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":106,"searchDepth":120,"depth":120,"links":2606},[2607,2608,2613,2623,2635,2636,2637],{"id":25,"depth":120,"text":26},{"id":82,"depth":120,"text":83,"children":2609},[2610,2611,2612],{"id":87,"depth":127,"text":88},{"id":463,"depth":127,"text":464},{"id":479,"depth":127,"text":480},{"id":613,"depth":120,"text":614,"children":2614},[2615,2616,2617,2618,2619,2620,2621,2622],{"id":617,"depth":127,"text":617},{"id":720,"depth":127,"text":720},{"id":758,"depth":127,"text":758},{"id":901,"depth":127,"text":902},{"id":968,"depth":127,"text":968},{"id":1047,"depth":127,"text":1048},{"id":1086,"depth":127,"text":1087},{"id":1168,"depth":127,"text":1169},{"id":1268,"depth":120,"text":1269,"children":2624},[2625,2626,2627,2628,2629,2630,2631,2632,2633,2634],{"id":1272,"depth":127,"text":1272},{"id":1385,"depth":127,"text":1386},{"id":236,"depth":127,"text":236},{"id":1501,"depth":127,"text":1502},{"id":1551,"depth":127,"text":1552},{"id":1749,"depth":127,"text":1750},{"id":2038,"depth":127,"text":2039},{"id":2104,"depth":127,"text":2104},{"id":387,"depth":127,"text":387},{"id":2415,"depth":127,"text":2416},{"id":2530,"depth":120,"text":2531},{"id":2550,"depth":120,"text":2551},{"id":2571,"depth":120,"text":2572},"NoLag uses MessagePack-encoded maps over WebSocket binary frames. Every message has a type field and topic-specific data.","md",{},true,"/docs/protocol",{"title":5,"description":2638},"docs/protocol","laIN458qgIVRPOKehcrpGiEYrj7f4veHPzyY26X2BX4",1789869420968]