[{"data":1,"prerenderedAt":1935},["ShallowReactive",2],{"docs:/docs/protocol":3},{"id":4,"title":5,"body":6,"description":1927,"extension":1928,"meta":1929,"navigation":1930,"path":1931,"seo":1932,"stem":1933,"__hash__":1934},"docs/docs/protocol.md","Wire Protocol",{"type":7,"value":8,"toc":1896},"minimark",[9,13,22,27,74,78,83,90,192,195,287,298,322,326,329,333,336,427,434,437,472,475,571,581,585,633,647,650,715,719,754,758,831,837,841,899,903,906,1006,1016,1020,1086,1090,1136,1140,1311,1315,1489,1493,1569,1572,1625,1628,1631,1688,1773,1776,1806,1809,1813,1816,1836,1840,1843,1857,1861,1892],[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],"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:"," Empty binary packet (0 bytes) every 30 seconds, both directions",[31,63,64,67],{},[34,65,66],{},"Max message size:"," 900 KB (all plans)",[31,69,70,73],{},[34,71,72],{},"Rate limit:"," 50 messages/second per connection",[23,75,77],{"id":76},"connection-lifecycle","Connection Lifecycle",[79,80,82],"h3",{"id":81},"_1-authentication","1. Authentication",[14,84,85,86,89],{},"After the WebSocket opens, the client sends an ",[18,87,88],{},"auth"," message immediately:",[91,92,93],"code-tabs",{},[94,95,101],"pre",{"className":96,"code":97,"filename":98,"language":99,"meta":100,"style":100},"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  \"reconnect\": false,\n  \"projectId\": \"proj_123\",\n  \"clientId\": \"worker-1\"\n}\n","JSON","json","",[18,102,103,112,119,136,149,162,175,186],{"__ignoreMap":100},[104,105,108],"span",{"class":106,"line":107},"line",1,[104,109,111],{"class":110},"sJ8bj","// Client sends after WebSocket opens\n",[104,113,115],{"class":106,"line":114},2,[104,116,118],{"class":117},"sVt8B","{\n",[104,120,122,126,129,133],{"class":106,"line":121},3,[104,123,125],{"class":124},"sj4cs","  \"type\"",[104,127,128],{"class":117},": ",[104,130,132],{"class":131},"sZZnC","\"auth\"",[104,134,135],{"class":117},",\n",[104,137,139,142,144,147],{"class":106,"line":138},4,[104,140,141],{"class":124},"  \"token\"",[104,143,128],{"class":117},[104,145,146],{"class":131},"\"at_live_\u003Ckey_id>.\u003Csecret>\"",[104,148,135],{"class":117},[104,150,152,155,157,160],{"class":106,"line":151},5,[104,153,154],{"class":124},"  \"reconnect\"",[104,156,128],{"class":117},[104,158,159],{"class":124},"false",[104,161,135],{"class":117},[104,163,165,168,170,173],{"class":106,"line":164},6,[104,166,167],{"class":124},"  \"projectId\"",[104,169,128],{"class":117},[104,171,172],{"class":131},"\"proj_123\"",[104,174,135],{"class":117},[104,176,178,181,183],{"class":106,"line":177},7,[104,179,180],{"class":124},"  \"clientId\"",[104,182,128],{"class":117},[104,184,185],{"class":131},"\"worker-1\"\n",[104,187,189],{"class":106,"line":188},8,[104,190,191],{"class":117},"}\n",[14,193,194],{},"The server responds within 10 seconds:",[91,196,197,243],{},[94,198,201],{"className":96,"code":199,"filename":200,"language":99,"meta":100,"style":100},"{\n  \"type\": \"auth\",\n  \"success\": true,\n  \"actorTokenId\": \"actor_123\"\n}\n","Success",[18,202,203,207,217,229,239],{"__ignoreMap":100},[104,204,205],{"class":106,"line":107},[104,206,118],{"class":117},[104,208,209,211,213,215],{"class":106,"line":114},[104,210,125],{"class":124},[104,212,128],{"class":117},[104,214,132],{"class":131},[104,216,135],{"class":117},[104,218,219,222,224,227],{"class":106,"line":121},[104,220,221],{"class":124},"  \"success\"",[104,223,128],{"class":117},[104,225,226],{"class":124},"true",[104,228,135],{"class":117},[104,230,231,234,236],{"class":106,"line":138},[104,232,233],{"class":124},"  \"actorTokenId\"",[104,235,128],{"class":117},[104,237,238],{"class":131},"\"actor_123\"\n",[104,240,241],{"class":106,"line":151},[104,242,191],{"class":117},[94,244,247],{"className":96,"code":245,"filename":246,"language":99,"meta":100,"style":100},"{\n  \"type\": \"auth\",\n  \"success\": false,\n  \"error\": \"invalid_token\"\n}\n","Failure",[18,248,249,253,263,273,283],{"__ignoreMap":100},[104,250,251],{"class":106,"line":107},[104,252,118],{"class":117},[104,254,255,257,259,261],{"class":106,"line":114},[104,256,125],{"class":124},[104,258,128],{"class":117},[104,260,132],{"class":131},[104,262,135],{"class":117},[104,264,265,267,269,271],{"class":106,"line":121},[104,266,221],{"class":124},[104,268,128],{"class":117},[104,270,159],{"class":124},[104,272,135],{"class":117},[104,274,275,278,280],{"class":106,"line":138},[104,276,277],{"class":124},"  \"error\"",[104,279,128],{"class":117},[104,281,282],{"class":131},"\"invalid_token\"\n",[104,284,285],{"class":106,"line":151},[104,286,191],{"class":117},[14,288,289,290,293,294,297],{},"If ",[18,291,292],{},"reconnect: true",", the server restores previous subscriptions and returns them in a ",[18,295,296],{},"restoredSubscriptions"," array so the client can rebuild its local state.",[14,299,300,303,304,307,308,311,312,314,315,307,318,321],{},[18,301,302],{},"clientId"," is optional and only means anything for actor types whose sessions persist (",[18,305,306],{},"agent"," and ",[18,309,310],{},"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,313,302],{}," 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,316,317],{},"-",[18,319,320],{},"_"," only, capped at 64 characters.",[79,323,325],{"id":324},"_2-heartbeat","2. Heartbeat",[14,327,328],{},"Both client and server send an empty binary packet (0 bytes) every 30 seconds as a keep-alive. This is not a MessagePack message, just an empty WebSocket binary frame.",[23,330,332],{"id":331},"client-to-server-messages","Client to Server Messages",[79,334,335],{"id":335},"subscribe",[91,337,338],{},[94,339,341],{"className":96,"code":340,"filename":98,"language":99,"meta":100,"style":100},"{\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,342,343,347,358,370,382,402,413,423],{"__ignoreMap":100},[104,344,345],{"class":106,"line":107},[104,346,118],{"class":117},[104,348,349,351,353,356],{"class":106,"line":114},[104,350,125],{"class":124},[104,352,128],{"class":117},[104,354,355],{"class":131},"\"subscribe\"",[104,357,135],{"class":117},[104,359,360,363,365,368],{"class":106,"line":121},[104,361,362],{"class":124},"  \"topic\"",[104,364,128],{"class":117},[104,366,367],{"class":131},"\"chat/general/messages\"",[104,369,135],{"class":117},[104,371,372,375,377,380],{"class":106,"line":138},[104,373,374],{"class":124},"  \"qos\"",[104,376,128],{"class":117},[104,378,379],{"class":124},"1",[104,381,135],{"class":117},[104,383,384,387,390,393,396,399],{"class":106,"line":151},[104,385,386],{"class":124},"  \"filters\"",[104,388,389],{"class":117},": [",[104,391,392],{"class":131},"\"user_123\"",[104,394,395],{"class":117},", ",[104,397,398],{"class":131},"\"user_456\"",[104,400,401],{"class":117},"],\n",[104,403,404,407,409,411],{"class":106,"line":164},[104,405,406],{"class":124},"  \"loadBalance\"",[104,408,128],{"class":117},[104,410,159],{"class":124},[104,412,135],{"class":117},[104,414,415,418,420],{"class":106,"line":177},[104,416,417],{"class":124},"  \"loadBalanceGroup\"",[104,419,128],{"class":117},[104,421,422],{"class":131},"\"worker-pool-1\"\n",[104,424,425],{"class":106,"line":188},[104,426,191],{"class":117},[14,428,429,430,433],{},"Topics use human-readable slugs in the format ",[18,431,432],{},"app/room/topic",". The server resolves these to internal identifiers. 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).",[79,435,436],{"id":436},"unsubscribe",[91,438,439],{},[94,440,442],{"className":96,"code":441,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"unsubscribe\",\n  \"topic\": \"chat/general/messages\"\n}\n",[18,443,444,448,459,468],{"__ignoreMap":100},[104,445,446],{"class":106,"line":107},[104,447,118],{"class":117},[104,449,450,452,454,457],{"class":106,"line":114},[104,451,125],{"class":124},[104,453,128],{"class":117},[104,455,456],{"class":131},"\"unsubscribe\"",[104,458,135],{"class":117},[104,460,461,463,465],{"class":106,"line":121},[104,462,362],{"class":124},[104,464,128],{"class":117},[104,466,467],{"class":131},"\"chat/general/messages\"\n",[104,469,470],{"class":106,"line":138},[104,471,191],{"class":117},[79,473,474],{"id":474},"publish",[91,476,477],{},[94,478,480],{"className":96,"code":479,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"publish\",\n  \"topic\": \"chat/general/messages\",\n  \"data\": { \"text\": \"hello world\", \"sender\": \"user_12\" },\n  \"qos\": 1,\n  \"echo\": true,\n  \"filter\": \"user_123\"\n}\n",[18,481,482,486,497,507,536,546,557,567],{"__ignoreMap":100},[104,483,484],{"class":106,"line":107},[104,485,118],{"class":117},[104,487,488,490,492,495],{"class":106,"line":114},[104,489,125],{"class":124},[104,491,128],{"class":117},[104,493,494],{"class":131},"\"publish\"",[104,496,135],{"class":117},[104,498,499,501,503,505],{"class":106,"line":121},[104,500,362],{"class":124},[104,502,128],{"class":117},[104,504,367],{"class":131},[104,506,135],{"class":117},[104,508,509,512,515,518,520,523,525,528,530,533],{"class":106,"line":138},[104,510,511],{"class":124},"  \"data\"",[104,513,514],{"class":117},": { ",[104,516,517],{"class":124},"\"text\"",[104,519,128],{"class":117},[104,521,522],{"class":131},"\"hello world\"",[104,524,395],{"class":117},[104,526,527],{"class":124},"\"sender\"",[104,529,128],{"class":117},[104,531,532],{"class":131},"\"user_12\"",[104,534,535],{"class":117}," },\n",[104,537,538,540,542,544],{"class":106,"line":151},[104,539,374],{"class":124},[104,541,128],{"class":117},[104,543,379],{"class":124},[104,545,135],{"class":117},[104,547,548,551,553,555],{"class":106,"line":164},[104,549,550],{"class":124},"  \"echo\"",[104,552,128],{"class":117},[104,554,226],{"class":124},[104,556,135],{"class":117},[104,558,559,562,564],{"class":106,"line":177},[104,560,561],{"class":124},"  \"filter\"",[104,563,128],{"class":117},[104,565,566],{"class":131},"\"user_123\"\n",[104,568,569],{"class":106,"line":188},[104,570,191],{"class":117},[14,572,573,576,577,580],{},[18,574,575],{},"echo: false"," prevents the message from being delivered back to the sender. The ",[18,578,579],{},"filter"," field routes the message only to subscribers who have that filter value in their subscription.",[79,582,584],{"id":583},"setfilters","setFilters",[91,586,587],{},[94,588,590],{"className":96,"code":589,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"setFilters\",\n  \"topic\": \"chat/general/messages\",\n  \"filters\": [\"user_789\"]\n}\n",[18,591,592,596,607,617,629],{"__ignoreMap":100},[104,593,594],{"class":106,"line":107},[104,595,118],{"class":117},[104,597,598,600,602,605],{"class":106,"line":114},[104,599,125],{"class":124},[104,601,128],{"class":117},[104,603,604],{"class":131},"\"setFilters\"",[104,606,135],{"class":117},[104,608,609,611,613,615],{"class":106,"line":121},[104,610,362],{"class":124},[104,612,128],{"class":117},[104,614,367],{"class":131},[104,616,135],{"class":117},[104,618,619,621,623,626],{"class":106,"line":138},[104,620,386],{"class":124},[104,622,389],{"class":117},[104,624,625],{"class":131},"\"user_789\"",[104,627,628],{"class":117},"]\n",[104,630,631],{"class":106,"line":151},[104,632,191],{"class":117},[14,634,635,636,395,639,642,643,646],{},"Replaces the entire filter set for a topic. An empty array switches to wildcard mode (receive all messages). Max 100 filters per topic. Filters cannot contain ",[18,637,638],{},"/",[18,640,641],{},"#",", or ",[18,644,645],{},"+",".",[79,648,649],{"id":649},"presence",[91,651,652],{},[94,653,655],{"className":96,"code":654,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"presence\",\n  \"roomId\": \"general\",\n  \"data\": { \"status\": \"online\", \"currentPage\": \"dashboard\" }\n}\n",[18,656,657,661,672,684,711],{"__ignoreMap":100},[104,658,659],{"class":106,"line":107},[104,660,118],{"class":117},[104,662,663,665,667,670],{"class":106,"line":114},[104,664,125],{"class":124},[104,666,128],{"class":117},[104,668,669],{"class":131},"\"presence\"",[104,671,135],{"class":117},[104,673,674,677,679,682],{"class":106,"line":121},[104,675,676],{"class":124},"  \"roomId\"",[104,678,128],{"class":117},[104,680,681],{"class":131},"\"general\"",[104,683,135],{"class":117},[104,685,686,688,690,693,695,698,700,703,705,708],{"class":106,"line":138},[104,687,511],{"class":124},[104,689,514],{"class":117},[104,691,692],{"class":124},"\"status\"",[104,694,128],{"class":117},[104,696,697],{"class":131},"\"online\"",[104,699,395],{"class":117},[104,701,702],{"class":124},"\"currentPage\"",[104,704,128],{"class":117},[104,706,707],{"class":131},"\"dashboard\"",[104,709,710],{"class":117}," }\n",[104,712,713],{"class":106,"line":151},[104,714,191],{"class":117},[79,716,718],{"id":717},"getpresence","getPresence",[91,720,721],{},[94,722,724],{"className":96,"code":723,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"getPresence\",\n  \"roomId\": \"general\"\n}\n",[18,725,726,730,741,750],{"__ignoreMap":100},[104,727,728],{"class":106,"line":107},[104,729,118],{"class":117},[104,731,732,734,736,739],{"class":106,"line":114},[104,733,125],{"class":124},[104,735,128],{"class":117},[104,737,738],{"class":131},"\"getPresence\"",[104,740,135],{"class":117},[104,742,743,745,747],{"class":106,"line":121},[104,744,676],{"class":124},[104,746,128],{"class":117},[104,748,749],{"class":131},"\"general\"\n",[104,751,752],{"class":106,"line":138},[104,753,191],{"class":117},[79,755,757],{"id":756},"ack-batchack","ack / batchAck",[91,759,760,791],{},[94,761,764],{"className":96,"code":762,"filename":763,"language":99,"meta":100,"style":100},"{ \"type\": \"ack\", \"msgId\": \"550e8400-...\" }\n","Single ACK",[18,765,766],{"__ignoreMap":100},[104,767,768,771,774,776,779,781,784,786,789],{"class":106,"line":107},[104,769,770],{"class":117},"{ ",[104,772,773],{"class":124},"\"type\"",[104,775,128],{"class":117},[104,777,778],{"class":131},"\"ack\"",[104,780,395],{"class":117},[104,782,783],{"class":124},"\"msgId\"",[104,785,128],{"class":117},[104,787,788],{"class":131},"\"550e8400-...\"",[104,790,710],{"class":117},[94,792,795],{"className":96,"code":793,"filename":794,"language":99,"meta":100,"style":100},"{ \"type\": \"batchAck\", \"msgIds\": [\"id1\", \"id2\", \"id3\"] }\n","Batch ACK",[18,796,797],{"__ignoreMap":100},[104,798,799,801,803,805,808,810,813,815,818,820,823,825,828],{"class":106,"line":107},[104,800,770],{"class":117},[104,802,773],{"class":124},[104,804,128],{"class":117},[104,806,807],{"class":131},"\"batchAck\"",[104,809,395],{"class":117},[104,811,812],{"class":124},"\"msgIds\"",[104,814,389],{"class":117},[104,816,817],{"class":131},"\"id1\"",[104,819,395],{"class":117},[104,821,822],{"class":131},"\"id2\"",[104,824,395],{"class":117},[104,826,827],{"class":131},"\"id3\"",[104,829,830],{"class":117},"] }\n",[14,832,833,834,646],{},"Required when the server sends a message with ",[18,835,836],{},"requiresAck: true",[79,838,840],{"id":839},"lobbysubscribe-lobbyunsubscribe","lobbySubscribe / lobbyUnsubscribe",[91,842,843,872],{},[94,844,847],{"className":96,"code":845,"filename":846,"language":99,"meta":100,"style":100},"{ \"type\": \"lobbySubscribe\", \"lobbyId\": \"active-trips\" }\n","Subscribe",[18,848,849],{"__ignoreMap":100},[104,850,851,853,855,857,860,862,865,867,870],{"class":106,"line":107},[104,852,770],{"class":117},[104,854,773],{"class":124},[104,856,128],{"class":117},[104,858,859],{"class":131},"\"lobbySubscribe\"",[104,861,395],{"class":117},[104,863,864],{"class":124},"\"lobbyId\"",[104,866,128],{"class":117},[104,868,869],{"class":131},"\"active-trips\"",[104,871,710],{"class":117},[94,873,876],{"className":96,"code":874,"filename":875,"language":99,"meta":100,"style":100},"{ \"type\": \"lobbyUnsubscribe\", \"lobbyId\": \"active-trips\" }\n","Unsubscribe",[18,877,878],{"__ignoreMap":100},[104,879,880,882,884,886,889,891,893,895,897],{"class":106,"line":107},[104,881,770],{"class":117},[104,883,773],{"class":124},[104,885,128],{"class":117},[104,887,888],{"class":131},"\"lobbyUnsubscribe\"",[104,890,395],{"class":117},[104,892,864],{"class":124},[104,894,128],{"class":117},[104,896,869],{"class":131},[104,898,710],{"class":117},[23,900,902],{"id":901},"server-to-client-messages","Server to Client Messages",[79,904,905],{"id":905},"message",[91,907,908],{},[94,909,911],{"className":96,"code":910,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"message\",\n  \"topic\": \"chat/general/messages\",\n  \"data\": { \"text\": \"hello world\", \"sender\": \"user_12\" },\n  \"msgId\": \"550e8400-...\",\n  \"requiresAck\": true,\n  \"isReplay\": false,\n  \"filter\": \"user_123\"\n}\n",[18,912,913,917,928,938,960,971,982,993,1001],{"__ignoreMap":100},[104,914,915],{"class":106,"line":107},[104,916,118],{"class":117},[104,918,919,921,923,926],{"class":106,"line":114},[104,920,125],{"class":124},[104,922,128],{"class":117},[104,924,925],{"class":131},"\"message\"",[104,927,135],{"class":117},[104,929,930,932,934,936],{"class":106,"line":121},[104,931,362],{"class":124},[104,933,128],{"class":117},[104,935,367],{"class":131},[104,937,135],{"class":117},[104,939,940,942,944,946,948,950,952,954,956,958],{"class":106,"line":138},[104,941,511],{"class":124},[104,943,514],{"class":117},[104,945,517],{"class":124},[104,947,128],{"class":117},[104,949,522],{"class":131},[104,951,395],{"class":117},[104,953,527],{"class":124},[104,955,128],{"class":117},[104,957,532],{"class":131},[104,959,535],{"class":117},[104,961,962,965,967,969],{"class":106,"line":151},[104,963,964],{"class":124},"  \"msgId\"",[104,966,128],{"class":117},[104,968,788],{"class":131},[104,970,135],{"class":117},[104,972,973,976,978,980],{"class":106,"line":164},[104,974,975],{"class":124},"  \"requiresAck\"",[104,977,128],{"class":117},[104,979,226],{"class":124},[104,981,135],{"class":117},[104,983,984,987,989,991],{"class":106,"line":177},[104,985,986],{"class":124},"  \"isReplay\"",[104,988,128],{"class":117},[104,990,159],{"class":124},[104,992,135],{"class":117},[104,994,995,997,999],{"class":106,"line":188},[104,996,561],{"class":124},[104,998,128],{"class":117},[104,1000,566],{"class":131},[104,1002,1004],{"class":106,"line":1003},9,[104,1005,191],{"class":117},[14,1007,1008,1011,1012,1015],{},[18,1009,1010],{},"msgId"," is present if the message is stored (logging enabled). ",[18,1013,1014],{},"isReplay: true"," marks messages replayed after reconnection.",[79,1017,1019],{"id":1018},"subscribed-unsubscribed","subscribed / unsubscribed",[91,1021,1022,1059],{},[94,1023,1026],{"className":96,"code":1024,"filename":1025,"language":99,"meta":100,"style":100},"{ \"type\": \"subscribed\", \"topic\": \"chat/general/messages\", \"loadBalance\": false }\n","Subscribed",[18,1027,1028],{"__ignoreMap":100},[104,1029,1030,1032,1034,1036,1039,1041,1044,1046,1048,1050,1053,1055,1057],{"class":106,"line":107},[104,1031,770],{"class":117},[104,1033,773],{"class":124},[104,1035,128],{"class":117},[104,1037,1038],{"class":131},"\"subscribed\"",[104,1040,395],{"class":117},[104,1042,1043],{"class":124},"\"topic\"",[104,1045,128],{"class":117},[104,1047,367],{"class":131},[104,1049,395],{"class":117},[104,1051,1052],{"class":124},"\"loadBalance\"",[104,1054,128],{"class":117},[104,1056,159],{"class":124},[104,1058,710],{"class":117},[94,1060,1063],{"className":96,"code":1061,"filename":1062,"language":99,"meta":100,"style":100},"{ \"type\": \"unsubscribed\", \"topic\": \"chat/general/messages\" }\n","Unsubscribed",[18,1064,1065],{"__ignoreMap":100},[104,1066,1067,1069,1071,1073,1076,1078,1080,1082,1084],{"class":106,"line":107},[104,1068,770],{"class":117},[104,1070,773],{"class":124},[104,1072,128],{"class":117},[104,1074,1075],{"class":131},"\"unsubscribed\"",[104,1077,395],{"class":117},[104,1079,1043],{"class":124},[104,1081,128],{"class":117},[104,1083,367],{"class":131},[104,1085,710],{"class":117},[79,1087,1089],{"id":1088},"filtersupdated","filtersUpdated",[91,1091,1092],{},[94,1093,1095],{"className":96,"code":1094,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"filtersUpdated\",\n  \"topic\": \"chat/general/messages\",\n  \"filters\": [\"user_789\"]\n}\n",[18,1096,1097,1101,1112,1122,1132],{"__ignoreMap":100},[104,1098,1099],{"class":106,"line":107},[104,1100,118],{"class":117},[104,1102,1103,1105,1107,1110],{"class":106,"line":114},[104,1104,125],{"class":124},[104,1106,128],{"class":117},[104,1108,1109],{"class":131},"\"filtersUpdated\"",[104,1111,135],{"class":117},[104,1113,1114,1116,1118,1120],{"class":106,"line":121},[104,1115,362],{"class":124},[104,1117,128],{"class":117},[104,1119,367],{"class":131},[104,1121,135],{"class":117},[104,1123,1124,1126,1128,1130],{"class":106,"line":138},[104,1125,386],{"class":124},[104,1127,389],{"class":117},[104,1129,625],{"class":131},[104,1131,628],{"class":117},[104,1133,1134],{"class":106,"line":151},[104,1135,191],{"class":117},[79,1137,1139],{"id":1138},"presence-presencelist","presence / presenceList",[91,1141,1142,1227],{},[94,1143,1146],{"className":96,"code":1144,"filename":1145,"language":99,"meta":100,"style":100},"{\n  \"type\": \"presence\",\n  \"event\": \"join\",\n  \"data\": {\n    \"actorTokenId\": \"actor_123\",\n    \"presence\": { \"status\": \"online\" },\n    \"joinedAt\": 1634567890123\n  }\n}\n","Presence Event",[18,1147,1148,1152,1162,1174,1181,1193,1208,1218,1223],{"__ignoreMap":100},[104,1149,1150],{"class":106,"line":107},[104,1151,118],{"class":117},[104,1153,1154,1156,1158,1160],{"class":106,"line":114},[104,1155,125],{"class":124},[104,1157,128],{"class":117},[104,1159,669],{"class":131},[104,1161,135],{"class":117},[104,1163,1164,1167,1169,1172],{"class":106,"line":121},[104,1165,1166],{"class":124},"  \"event\"",[104,1168,128],{"class":117},[104,1170,1171],{"class":131},"\"join\"",[104,1173,135],{"class":117},[104,1175,1176,1178],{"class":106,"line":138},[104,1177,511],{"class":124},[104,1179,1180],{"class":117},": {\n",[104,1182,1183,1186,1188,1191],{"class":106,"line":151},[104,1184,1185],{"class":124},"    \"actorTokenId\"",[104,1187,128],{"class":117},[104,1189,1190],{"class":131},"\"actor_123\"",[104,1192,135],{"class":117},[104,1194,1195,1198,1200,1202,1204,1206],{"class":106,"line":164},[104,1196,1197],{"class":124},"    \"presence\"",[104,1199,514],{"class":117},[104,1201,692],{"class":124},[104,1203,128],{"class":117},[104,1205,697],{"class":131},[104,1207,535],{"class":117},[104,1209,1210,1213,1215],{"class":106,"line":177},[104,1211,1212],{"class":124},"    \"joinedAt\"",[104,1214,128],{"class":117},[104,1216,1217],{"class":124},"1634567890123\n",[104,1219,1220],{"class":106,"line":188},[104,1221,1222],{"class":117},"  }\n",[104,1224,1225],{"class":106,"line":1003},[104,1226,191],{"class":117},[94,1228,1231],{"className":96,"code":1229,"filename":1230,"language":99,"meta":100,"style":100},"{\n  \"type\": \"presenceList\",\n  \"roomId\": \"general\",\n  \"data\": [\n    { \"actorTokenId\": \"actor_123\", \"presence\": { \"status\": \"online\" }, \"joinedAt\": 1634567890123 }\n  ]\n}\n","Presence Snapshot",[18,1232,1233,1237,1248,1258,1265,1302,1307],{"__ignoreMap":100},[104,1234,1235],{"class":106,"line":107},[104,1236,118],{"class":117},[104,1238,1239,1241,1243,1246],{"class":106,"line":114},[104,1240,125],{"class":124},[104,1242,128],{"class":117},[104,1244,1245],{"class":131},"\"presenceList\"",[104,1247,135],{"class":117},[104,1249,1250,1252,1254,1256],{"class":106,"line":121},[104,1251,676],{"class":124},[104,1253,128],{"class":117},[104,1255,681],{"class":131},[104,1257,135],{"class":117},[104,1259,1260,1262],{"class":106,"line":138},[104,1261,511],{"class":124},[104,1263,1264],{"class":117},": [\n",[104,1266,1267,1270,1273,1275,1277,1279,1281,1283,1285,1287,1289,1292,1295,1297,1300],{"class":106,"line":151},[104,1268,1269],{"class":117},"    { ",[104,1271,1272],{"class":124},"\"actorTokenId\"",[104,1274,128],{"class":117},[104,1276,1190],{"class":131},[104,1278,395],{"class":117},[104,1280,669],{"class":124},[104,1282,514],{"class":117},[104,1284,692],{"class":124},[104,1286,128],{"class":117},[104,1288,697],{"class":131},[104,1290,1291],{"class":117}," }, ",[104,1293,1294],{"class":124},"\"joinedAt\"",[104,1296,128],{"class":117},[104,1298,1299],{"class":124},"1634567890123",[104,1301,710],{"class":117},[104,1303,1304],{"class":106,"line":164},[104,1305,1306],{"class":117},"  ]\n",[104,1308,1309],{"class":106,"line":177},[104,1310,191],{"class":117},[79,1312,1314],{"id":1313},"lobbysubscribed-lobbypresence","lobbySubscribed / lobbyPresence",[91,1316,1317,1407],{},[94,1318,1321],{"className":96,"code":1319,"filename":1320,"language":99,"meta":100,"style":100},"{\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,1322,1323,1327,1338,1349,1356,1377,1399,1403],{"__ignoreMap":100},[104,1324,1325],{"class":106,"line":107},[104,1326,118],{"class":117},[104,1328,1329,1331,1333,1336],{"class":106,"line":114},[104,1330,125],{"class":124},[104,1332,128],{"class":117},[104,1334,1335],{"class":131},"\"lobbySubscribed\"",[104,1337,135],{"class":117},[104,1339,1340,1343,1345,1347],{"class":106,"line":121},[104,1341,1342],{"class":124},"  \"lobbyId\"",[104,1344,128],{"class":117},[104,1346,869],{"class":131},[104,1348,135],{"class":117},[104,1350,1351,1354],{"class":106,"line":138},[104,1352,1353],{"class":124},"  \"presence\"",[104,1355,1180],{"class":117},[104,1357,1358,1361,1363,1365,1367,1369,1371,1374],{"class":106,"line":151},[104,1359,1360],{"class":124},"    \"room_1\"",[104,1362,514],{"class":117},[104,1364,1190],{"class":124},[104,1366,514],{"class":117},[104,1368,692],{"class":124},[104,1370,128],{"class":117},[104,1372,1373],{"class":131},"\"driving\"",[104,1375,1376],{"class":117}," } },\n",[104,1378,1379,1382,1384,1387,1389,1391,1393,1396],{"class":106,"line":164},[104,1380,1381],{"class":124},"    \"room_2\"",[104,1383,514],{"class":117},[104,1385,1386],{"class":124},"\"actor_456\"",[104,1388,514],{"class":117},[104,1390,692],{"class":124},[104,1392,128],{"class":117},[104,1394,1395],{"class":131},"\"waiting\"",[104,1397,1398],{"class":117}," } }\n",[104,1400,1401],{"class":106,"line":177},[104,1402,1222],{"class":117},[104,1404,1405],{"class":106,"line":188},[104,1406,191],{"class":117},[94,1408,1411],{"className":96,"code":1409,"filename":1410,"language":99,"meta":100,"style":100},"{\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",[18,1412,1413,1417,1428,1438,1448,1459,1471,1485],{"__ignoreMap":100},[104,1414,1415],{"class":106,"line":107},[104,1416,118],{"class":117},[104,1418,1419,1421,1423,1426],{"class":106,"line":114},[104,1420,125],{"class":124},[104,1422,128],{"class":117},[104,1424,1425],{"class":131},"\"lobbyPresence\"",[104,1427,135],{"class":117},[104,1429,1430,1432,1434,1436],{"class":106,"line":121},[104,1431,1166],{"class":124},[104,1433,128],{"class":117},[104,1435,1171],{"class":131},[104,1437,135],{"class":117},[104,1439,1440,1442,1444,1446],{"class":106,"line":138},[104,1441,1342],{"class":124},[104,1443,128],{"class":117},[104,1445,869],{"class":131},[104,1447,135],{"class":117},[104,1449,1450,1452,1454,1457],{"class":106,"line":151},[104,1451,676],{"class":124},[104,1453,128],{"class":117},[104,1455,1456],{"class":131},"\"room_1\"",[104,1458,135],{"class":117},[104,1460,1461,1464,1466,1469],{"class":106,"line":164},[104,1462,1463],{"class":124},"  \"actorId\"",[104,1465,128],{"class":117},[104,1467,1468],{"class":131},"\"actor_789\"",[104,1470,135],{"class":117},[104,1472,1473,1475,1477,1479,1481,1483],{"class":106,"line":177},[104,1474,511],{"class":124},[104,1476,514],{"class":117},[104,1478,692],{"class":124},[104,1480,128],{"class":117},[104,1482,1373],{"class":131},[104,1484,710],{"class":117},[104,1486,1487],{"class":106,"line":188},[104,1488,191],{"class":117},[79,1490,1492],{"id":1491},"replaystart-replayend","replayStart / replayEnd",[91,1494,1495],{},[94,1496,1498],{"className":96,"code":1497,"filename":98,"language":99,"meta":100,"style":100},"{ \"type\": \"replayStart\", \"count\": 247, \"oldestTimestamp\": \"...\", \"newestTimestamp\": \"...\" }\n// ... replayed messages arrive with isReplay: true ...\n{ \"type\": \"replayEnd\", \"replayed\": 247 }\n",[18,1499,1500,1542,1547],{"__ignoreMap":100},[104,1501,1502,1504,1506,1508,1511,1513,1516,1518,1521,1523,1526,1528,1531,1533,1536,1538,1540],{"class":106,"line":107},[104,1503,770],{"class":117},[104,1505,773],{"class":124},[104,1507,128],{"class":117},[104,1509,1510],{"class":131},"\"replayStart\"",[104,1512,395],{"class":117},[104,1514,1515],{"class":124},"\"count\"",[104,1517,128],{"class":117},[104,1519,1520],{"class":124},"247",[104,1522,395],{"class":117},[104,1524,1525],{"class":124},"\"oldestTimestamp\"",[104,1527,128],{"class":117},[104,1529,1530],{"class":131},"\"...\"",[104,1532,395],{"class":117},[104,1534,1535],{"class":124},"\"newestTimestamp\"",[104,1537,128],{"class":117},[104,1539,1530],{"class":131},[104,1541,710],{"class":117},[104,1543,1544],{"class":106,"line":114},[104,1545,1546],{"class":110},"// ... replayed messages arrive with isReplay: true ...\n",[104,1548,1549,1551,1553,1555,1558,1560,1563,1565,1567],{"class":106,"line":121},[104,1550,770],{"class":117},[104,1552,773],{"class":124},[104,1554,128],{"class":117},[104,1556,1557],{"class":131},"\"replayEnd\"",[104,1559,395],{"class":117},[104,1561,1562],{"class":124},"\"replayed\"",[104,1564,128],{"class":117},[104,1566,1520],{"class":124},[104,1568,710],{"class":117},[79,1570,1571],{"id":1571},"hydration",[91,1573,1574],{},[94,1575,1577],{"className":96,"code":1576,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"hydration\",\n  \"topic\": \"chat/general/messages\",\n  \"data\": { \"recentMessages\": [...] }\n}\n",[18,1578,1579,1583,1594,1604,1621],{"__ignoreMap":100},[104,1580,1581],{"class":106,"line":107},[104,1582,118],{"class":117},[104,1584,1585,1587,1589,1592],{"class":106,"line":114},[104,1586,125],{"class":124},[104,1588,128],{"class":117},[104,1590,1591],{"class":131},"\"hydration\"",[104,1593,135],{"class":117},[104,1595,1596,1598,1600,1602],{"class":106,"line":121},[104,1597,362],{"class":124},[104,1599,128],{"class":117},[104,1601,367],{"class":131},[104,1603,135],{"class":117},[104,1605,1606,1608,1610,1613,1615,1619],{"class":106,"line":138},[104,1607,511],{"class":124},[104,1609,514],{"class":117},[104,1611,1612],{"class":124},"\"recentMessages\"",[104,1614,389],{"class":117},[104,1616,1618],{"class":1617},"s7hpK","...",[104,1620,830],{"class":117},[104,1622,1623],{"class":106,"line":151},[104,1624,191],{"class":117},[14,1626,1627],{},"Sent on subscribe if a hydration webhook is configured for the topic.",[79,1629,1630],{"id":1630},"error",[91,1632,1633],{},[94,1634,1636],{"className":96,"code":1635,"filename":98,"language":99,"meta":100,"style":100},"{\n  \"type\": \"error\",\n  \"error\": \"rate_limit_exceeded\",\n  \"code\": 42910,\n  \"topic\": \"chat/general/messages\"\n}\n",[18,1637,1638,1642,1653,1664,1676,1684],{"__ignoreMap":100},[104,1639,1640],{"class":106,"line":107},[104,1641,118],{"class":117},[104,1643,1644,1646,1648,1651],{"class":106,"line":114},[104,1645,125],{"class":124},[104,1647,128],{"class":117},[104,1649,1650],{"class":131},"\"error\"",[104,1652,135],{"class":117},[104,1654,1655,1657,1659,1662],{"class":106,"line":121},[104,1656,277],{"class":124},[104,1658,128],{"class":117},[104,1660,1661],{"class":131},"\"rate_limit_exceeded\"",[104,1663,135],{"class":117},[104,1665,1666,1669,1671,1674],{"class":106,"line":138},[104,1667,1668],{"class":124},"  \"code\"",[104,1670,128],{"class":117},[104,1672,1673],{"class":124},"42910",[104,1675,135],{"class":117},[104,1677,1678,1680,1682],{"class":106,"line":151},[104,1679,362],{"class":124},[104,1681,128],{"class":117},[104,1683,467],{"class":131},[104,1685,1686],{"class":106,"line":164},[104,1687,191],{"class":117},[1689,1690,1691,1707],"table",{},[1692,1693,1694],"thead",{},[1695,1696,1697,1701,1704],"tr",{},[1698,1699,1700],"th",{},"Code",[1698,1702,1703],{},"Error",[1698,1705,1706],{},"Description",[1708,1709,1710,1721,1732,1743,1753,1763],"tbody",{},[1695,1711,1712,1715,1718],{},[1713,1714,1673],"td",{},[1713,1716,1717],{},"rate_limit_exceeded",[1713,1719,1720],{},"Too many messages per second",[1695,1722,1723,1726,1729],{},[1713,1724,1725],{},"42920",[1713,1727,1728],{},"monthly_quota_exceeded",[1713,1730,1731],{},"Plan message quota reached",[1695,1733,1734,1737,1740],{},[1713,1735,1736],{},"42930",[1713,1738,1739],{},"message_too_large",[1713,1741,1742],{},"Payload exceeds plan limit",[1695,1744,1745,1747,1750],{},[1713,1746,317],{},[1713,1748,1749],{},"not_authorized",[1713,1751,1752],{},"ACL denied access to topic",[1695,1754,1755,1757,1760],{},[1713,1756,317],{},[1713,1758,1759],{},"not_subscribed",[1713,1761,1762],{},"Publish to a topic not subscribed",[1695,1764,1765,1767,1770],{},[1713,1766,317],{},[1713,1768,1769],{},"invalid_filter_chars",[1713,1771,1772],{},"Filter contains /, #, or +",[79,1774,1775],{"id":1775},"disconnect",[91,1777,1778],{},[94,1779,1781],{"className":96,"code":1780,"filename":98,"language":99,"meta":100,"style":100},"{ \"type\": \"disconnect\", \"reason\": \"token_invalid\" }\n",[18,1782,1783],{"__ignoreMap":100},[104,1784,1785,1787,1789,1791,1794,1796,1799,1801,1804],{"class":106,"line":107},[104,1786,770],{"class":117},[104,1788,773],{"class":124},[104,1790,128],{"class":117},[104,1792,1793],{"class":131},"\"disconnect\"",[104,1795,395],{"class":117},[104,1797,1798],{"class":124},"\"reason\"",[104,1800,128],{"class":117},[104,1802,1803],{"class":131},"\"token_invalid\"",[104,1805,710],{"class":117},[14,1807,1808],{},"Server-initiated disconnect (e.g. token revoked, revalidation failed).",[23,1810,1812],{"id":1811},"delivery-guarantees-qos","Delivery Guarantees (QoS)",[14,1814,1815],{},"QoS is specified per-message on both subscribe and publish. Default is 1.",[28,1817,1818,1824,1830],{},[31,1819,1820,1823],{},[34,1821,1822],{},"QoS 0:"," At-most-once. Best effort, no acknowledgement.",[31,1825,1826,1829],{},[34,1827,1828],{},"QoS 1:"," At-least-once. Server acknowledges delivery, may duplicate.",[31,1831,1832,1835],{},[34,1833,1834],{},"QoS 2:"," Exactly-once. Guaranteed single delivery.",[23,1837,1839],{"id":1838},"why-messagepack","Why MessagePack?",[14,1841,1842],{},"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,1844,1845,1848,1851,1854],{},[31,1846,1847],{},"Binary format, no parsing ambiguity",[31,1849,1850],{},"Native support for binary data (no Base64 overhead)",[31,1852,1853],{},"Schema-less, same flexibility as JSON",[31,1855,1856],{},"Implementations available in every major language",[23,1858,1860],{"id":1859},"next-steps","Next Steps",[28,1862,1863,1871,1878,1885],{},[31,1864,1865,1870],{},[1866,1867,1869],"a",{"href":1868},"/docs/concepts/qos","Quality of Service"," - configure per-message delivery guarantees",[31,1872,1873,1877],{},[1866,1874,1876],{"href":1875},"/docs/concepts/filters","Filters"," - narrow message delivery within a topic",[31,1879,1880,1884],{},[1866,1881,1883],{"href":1882},"/docs/concepts/presence","Presence"," - track who is online",[31,1886,1887,1891],{},[1866,1888,1890],{"href":1889},"/docs/sdks","SDKs"," - the protocol is handled for you in every SDK",[1893,1894,1895],"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);}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}",{"title":100,"searchDepth":114,"depth":114,"links":1897},[1898,1899,1903,1913,1924,1925,1926],{"id":25,"depth":114,"text":26},{"id":76,"depth":114,"text":77,"children":1900},[1901,1902],{"id":81,"depth":121,"text":82},{"id":324,"depth":121,"text":325},{"id":331,"depth":114,"text":332,"children":1904},[1905,1906,1907,1908,1909,1910,1911,1912],{"id":335,"depth":121,"text":335},{"id":436,"depth":121,"text":436},{"id":474,"depth":121,"text":474},{"id":583,"depth":121,"text":584},{"id":649,"depth":121,"text":649},{"id":717,"depth":121,"text":718},{"id":756,"depth":121,"text":757},{"id":839,"depth":121,"text":840},{"id":901,"depth":114,"text":902,"children":1914},[1915,1916,1917,1918,1919,1920,1921,1922,1923],{"id":905,"depth":121,"text":905},{"id":1018,"depth":121,"text":1019},{"id":1088,"depth":121,"text":1089},{"id":1138,"depth":121,"text":1139},{"id":1313,"depth":121,"text":1314},{"id":1491,"depth":121,"text":1492},{"id":1571,"depth":121,"text":1571},{"id":1630,"depth":121,"text":1630},{"id":1775,"depth":121,"text":1775},{"id":1811,"depth":114,"text":1812},{"id":1838,"depth":114,"text":1839},{"id":1859,"depth":114,"text":1860},"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":1927},"docs/protocol","xV0RhOLTsQe8_FZXLrL-jxzkuf-wXBfeDrH5-giVG9U",1788160344317]