[{"data":1,"prerenderedAt":759},["ShallowReactive",2],{"docs:/docs/scopes/getting-started":3},{"id":4,"title":5,"body":6,"description":752,"extension":753,"meta":754,"navigation":261,"path":755,"seo":756,"stem":757,"__hash__":758},"docs/docs/scopes/getting-started.md","Access Scopes - Getting Started",{"type":7,"value":8,"toc":744},"minimark",[9,13,17,22,30,33,37,61,68,72,87,309,313,320,462,466,469,664,713,717,740],[10,11,5],"h1",{"id":12},"access-scopes-getting-started",[14,15,16],"p",{},"Set up tenant isolation for actor communication in minutes.",[18,19,21],"h2",{"id":20},"what-are-access-scopes","What are Access Scopes?",[14,23,24,25,29],{},"Access Scopes provide ",[26,27,28],"strong",{},"tenant isolation"," for actor communication. When you assign an actor to a scope, all of that actor's MQTT topics are automatically namespaced under the scope's slug. Actors in different scopes cannot see or communicate with each other, even if they are in the same app and room.",[14,31,32],{},"This is the foundation for building multi-tenant applications on NoLag. Instead of creating separate apps or projects for each tenant, you create a single app and isolate tenants using scopes.",[18,34,36],{"id":35},"prerequisites","Prerequisites",[38,39,40,50,53],"ul",{},[41,42,43,44,49],"li",{},"A NoLag account (",[45,46,48],"a",{"href":47},"/pricing","free tier available",")",[41,51,52],{},"A project with at least one app and actor created",[41,54,55,56,60],{},"A project-scoped API key (",[57,58,59],"code",{},"nlg_live_...",") with write access to actors and scopes",[14,62,63,64,67],{},"All API calls are automatically scoped to your project based on the API key you provide in the ",[57,65,66],{},"Authorization"," header. You do not need to pass organization or project IDs in the URL.",[18,69,71],{"id":70},"step-1-create-a-scope","Step 1: Create a Scope",[14,73,74,75,78,79,82,83,86],{},"Create a scope via the REST API. Each scope has a ",[57,76,77],{},"slug"," (URL-safe identifier used in topic namespacing) and an optional ",[57,80,81],{},"name"," (human-readable label). The slug is ",[26,84,85],{},"immutable after creation",".",[88,89,90],"code-tabs",{},[91,92,98],"pre",{"className":93,"code":94,"filename":95,"language":96,"meta":97,"style":97},"language-typescript shiki shiki-themes github-light github-dark","const response = await fetch(\n  `https://api.nolag.app/v1/scopes`,\n  {\n    method: \"POST\",\n    headers: {\n      \"Authorization\": `Bearer ${apiKey}`,\n      \"Content-Type\": \"application/json\",\n    },\n    body: JSON.stringify({\n      slug: \"client-acme\",\n      name: \"Acme Corporation\",\n    }),\n  }\n);\n\nconst scope = await response.json();\nconsole.log(\"Created scope:\", scope.accessScopeId);\n// => { accessScopeId: \"01HZ...\", slug: \"client-acme\", name: \"Acme Corporation\" }\n","TypeScript","typescript","",[57,99,100,127,137,143,154,160,180,193,199,216,227,238,244,250,256,263,284,302],{"__ignoreMap":97},[101,102,105,109,113,116,119,123],"span",{"class":103,"line":104},"line",1,[101,106,108],{"class":107},"szBVR","const",[101,110,112],{"class":111},"sj4cs"," response",[101,114,115],{"class":107}," =",[101,117,118],{"class":107}," await",[101,120,122],{"class":121},"sScJk"," fetch",[101,124,126],{"class":125},"sVt8B","(\n",[101,128,130,134],{"class":103,"line":129},2,[101,131,133],{"class":132},"sZZnC","  `https://api.nolag.app/v1/scopes`",[101,135,136],{"class":125},",\n",[101,138,140],{"class":103,"line":139},3,[101,141,142],{"class":125},"  {\n",[101,144,146,149,152],{"class":103,"line":145},4,[101,147,148],{"class":125},"    method: ",[101,150,151],{"class":132},"\"POST\"",[101,153,136],{"class":125},[101,155,157],{"class":103,"line":156},5,[101,158,159],{"class":125},"    headers: {\n",[101,161,163,166,169,172,175,178],{"class":103,"line":162},6,[101,164,165],{"class":132},"      \"Authorization\"",[101,167,168],{"class":125},": ",[101,170,171],{"class":132},"`Bearer ${",[101,173,174],{"class":125},"apiKey",[101,176,177],{"class":132},"}`",[101,179,136],{"class":125},[101,181,183,186,188,191],{"class":103,"line":182},7,[101,184,185],{"class":132},"      \"Content-Type\"",[101,187,168],{"class":125},[101,189,190],{"class":132},"\"application/json\"",[101,192,136],{"class":125},[101,194,196],{"class":103,"line":195},8,[101,197,198],{"class":125},"    },\n",[101,200,202,205,208,210,213],{"class":103,"line":201},9,[101,203,204],{"class":125},"    body: ",[101,206,207],{"class":111},"JSON",[101,209,86],{"class":125},[101,211,212],{"class":121},"stringify",[101,214,215],{"class":125},"({\n",[101,217,219,222,225],{"class":103,"line":218},10,[101,220,221],{"class":125},"      slug: ",[101,223,224],{"class":132},"\"client-acme\"",[101,226,136],{"class":125},[101,228,230,233,236],{"class":103,"line":229},11,[101,231,232],{"class":125},"      name: ",[101,234,235],{"class":132},"\"Acme Corporation\"",[101,237,136],{"class":125},[101,239,241],{"class":103,"line":240},12,[101,242,243],{"class":125},"    }),\n",[101,245,247],{"class":103,"line":246},13,[101,248,249],{"class":125},"  }\n",[101,251,253],{"class":103,"line":252},14,[101,254,255],{"class":125},");\n",[101,257,259],{"class":103,"line":258},15,[101,260,262],{"emptyLinePlaceholder":261},true,"\n",[101,264,266,268,271,273,275,278,281],{"class":103,"line":265},16,[101,267,108],{"class":107},[101,269,270],{"class":111}," scope",[101,272,115],{"class":107},[101,274,118],{"class":107},[101,276,277],{"class":125}," response.",[101,279,280],{"class":121},"json",[101,282,283],{"class":125},"();\n",[101,285,287,290,293,296,299],{"class":103,"line":286},17,[101,288,289],{"class":125},"console.",[101,291,292],{"class":121},"log",[101,294,295],{"class":125},"(",[101,297,298],{"class":132},"\"Created scope:\"",[101,300,301],{"class":125},", scope.accessScopeId);\n",[101,303,305],{"class":103,"line":304},18,[101,306,308],{"class":307},"sJ8bj","// => { accessScopeId: \"01HZ...\", slug: \"client-acme\", name: \"Acme Corporation\" }\n",[18,310,312],{"id":311},"step-2-assign-an-actor-to-the-scope","Step 2: Assign an Actor to the Scope",[14,314,315,316,319],{},"Patch the actor to set its ",[57,317,318],{},"accessScopeId",". The actor will immediately begin receiving topics namespaced under the scope's slug. You can assign the scope at actor creation time or update it later.",[88,321,322],{},[91,323,325],{"className":93,"code":324,"filename":95,"language":96,"meta":97,"style":97},"const response = await fetch(\n  `https://api.nolag.app/v1/actors/${actorId}`,\n  {\n    method: \"PATCH\",\n    headers: {\n      \"Authorization\": `Bearer ${apiKey}`,\n      \"Content-Type\": \"application/json\",\n    },\n    body: JSON.stringify({\n      accessScopeId: scope.accessScopeId,\n    }),\n  }\n);\n\nconst actor = await response.json();\nconsole.log(\"Actor scoped to:\", actor.accessScopeId);\n",[57,326,327,341,353,357,366,370,384,394,398,410,415,419,423,427,431,448],{"__ignoreMap":97},[101,328,329,331,333,335,337,339],{"class":103,"line":104},[101,330,108],{"class":107},[101,332,112],{"class":111},[101,334,115],{"class":107},[101,336,118],{"class":107},[101,338,122],{"class":121},[101,340,126],{"class":125},[101,342,343,346,349,351],{"class":103,"line":129},[101,344,345],{"class":132},"  `https://api.nolag.app/v1/actors/${",[101,347,348],{"class":125},"actorId",[101,350,177],{"class":132},[101,352,136],{"class":125},[101,354,355],{"class":103,"line":139},[101,356,142],{"class":125},[101,358,359,361,364],{"class":103,"line":145},[101,360,148],{"class":125},[101,362,363],{"class":132},"\"PATCH\"",[101,365,136],{"class":125},[101,367,368],{"class":103,"line":156},[101,369,159],{"class":125},[101,371,372,374,376,378,380,382],{"class":103,"line":162},[101,373,165],{"class":132},[101,375,168],{"class":125},[101,377,171],{"class":132},[101,379,174],{"class":125},[101,381,177],{"class":132},[101,383,136],{"class":125},[101,385,386,388,390,392],{"class":103,"line":182},[101,387,185],{"class":132},[101,389,168],{"class":125},[101,391,190],{"class":132},[101,393,136],{"class":125},[101,395,396],{"class":103,"line":195},[101,397,198],{"class":125},[101,399,400,402,404,406,408],{"class":103,"line":201},[101,401,204],{"class":125},[101,403,207],{"class":111},[101,405,86],{"class":125},[101,407,212],{"class":121},[101,409,215],{"class":125},[101,411,412],{"class":103,"line":218},[101,413,414],{"class":125},"      accessScopeId: scope.accessScopeId,\n",[101,416,417],{"class":103,"line":229},[101,418,243],{"class":125},[101,420,421],{"class":103,"line":240},[101,422,249],{"class":125},[101,424,425],{"class":103,"line":246},[101,426,255],{"class":125},[101,428,429],{"class":103,"line":252},[101,430,262],{"emptyLinePlaceholder":261},[101,432,433,435,438,440,442,444,446],{"class":103,"line":258},[101,434,108],{"class":107},[101,436,437],{"class":111}," actor",[101,439,115],{"class":107},[101,441,118],{"class":107},[101,443,277],{"class":125},[101,445,280],{"class":121},[101,447,283],{"class":125},[101,449,450,452,454,456,459],{"class":103,"line":265},[101,451,289],{"class":125},[101,453,292],{"class":121},[101,455,295],{"class":125},[101,457,458],{"class":132},"\"Actor scoped to:\"",[101,460,461],{"class":125},", actor.accessScopeId);\n",[18,463,465],{"id":464},"step-3-verify-isolation","Step 3: Verify Isolation",[14,467,468],{},"Once an actor is scoped, its topic namespace changes. The scope slug is injected between the app slug and the room slug, creating a partition that prevents cross-tenant communication.",[88,470,471],{},[91,472,474],{"className":93,"code":473,"filename":95,"language":96,"meta":97,"style":97},"// Without a scope, the actor subscribes to:\n//   app-slug/room-slug/topic\n//\n// With scope \"client-acme\", the same actor subscribes to:\n//   app-slug/client-acme/room-slug/topic\n//\n// The scope slug is injected into the topic namespace automatically.\n// Actors in different scopes CANNOT see each other's messages.\n\nimport NoLag from \"@nolag/js-sdk\";\n\n// Actor assigned to \"client-acme\" scope\nconst connection = await NoLag.connect({ actorToken: SCOPED_ACTOR_TOKEN });\n\n// The topic namespace is partitioned automatically\n// This actor only receives messages within the \"client-acme\" scope\nconst topic = connection.subscribe(\"my-room/updates\");\ntopic.on(\"message\", (data) => {\n  // Only messages from actors in the same scope arrive here\n  console.log(\"Scoped message:\", data);\n});\n",[57,475,476,481,486,491,496,501,505,510,515,519,536,540,545,571,575,580,585,607,636,642,658],{"__ignoreMap":97},[101,477,478],{"class":103,"line":104},[101,479,480],{"class":307},"// Without a scope, the actor subscribes to:\n",[101,482,483],{"class":103,"line":129},[101,484,485],{"class":307},"//   app-slug/room-slug/topic\n",[101,487,488],{"class":103,"line":139},[101,489,490],{"class":307},"//\n",[101,492,493],{"class":103,"line":145},[101,494,495],{"class":307},"// With scope \"client-acme\", the same actor subscribes to:\n",[101,497,498],{"class":103,"line":156},[101,499,500],{"class":307},"//   app-slug/client-acme/room-slug/topic\n",[101,502,503],{"class":103,"line":162},[101,504,490],{"class":307},[101,506,507],{"class":103,"line":182},[101,508,509],{"class":307},"// The scope slug is injected into the topic namespace automatically.\n",[101,511,512],{"class":103,"line":195},[101,513,514],{"class":307},"// Actors in different scopes CANNOT see each other's messages.\n",[101,516,517],{"class":103,"line":201},[101,518,262],{"emptyLinePlaceholder":261},[101,520,521,524,527,530,533],{"class":103,"line":218},[101,522,523],{"class":107},"import",[101,525,526],{"class":125}," NoLag ",[101,528,529],{"class":107},"from",[101,531,532],{"class":132}," \"@nolag/js-sdk\"",[101,534,535],{"class":125},";\n",[101,537,538],{"class":103,"line":229},[101,539,262],{"emptyLinePlaceholder":261},[101,541,542],{"class":103,"line":240},[101,543,544],{"class":307},"// Actor assigned to \"client-acme\" scope\n",[101,546,547,549,552,554,556,559,562,565,568],{"class":103,"line":246},[101,548,108],{"class":107},[101,550,551],{"class":111}," connection",[101,553,115],{"class":107},[101,555,118],{"class":107},[101,557,558],{"class":125}," NoLag.",[101,560,561],{"class":121},"connect",[101,563,564],{"class":125},"({ actorToken: ",[101,566,567],{"class":111},"SCOPED_ACTOR_TOKEN",[101,569,570],{"class":125}," });\n",[101,572,573],{"class":103,"line":252},[101,574,262],{"emptyLinePlaceholder":261},[101,576,577],{"class":103,"line":258},[101,578,579],{"class":307},"// The topic namespace is partitioned automatically\n",[101,581,582],{"class":103,"line":265},[101,583,584],{"class":307},"// This actor only receives messages within the \"client-acme\" scope\n",[101,586,587,589,592,594,597,600,602,605],{"class":103,"line":286},[101,588,108],{"class":107},[101,590,591],{"class":111}," topic",[101,593,115],{"class":107},[101,595,596],{"class":125}," connection.",[101,598,599],{"class":121},"subscribe",[101,601,295],{"class":125},[101,603,604],{"class":132},"\"my-room/updates\"",[101,606,255],{"class":125},[101,608,609,612,615,617,620,623,627,630,633],{"class":103,"line":304},[101,610,611],{"class":125},"topic.",[101,613,614],{"class":121},"on",[101,616,295],{"class":125},[101,618,619],{"class":132},"\"message\"",[101,621,622],{"class":125},", (",[101,624,626],{"class":625},"s4XuR","data",[101,628,629],{"class":125},") ",[101,631,632],{"class":107},"=>",[101,634,635],{"class":125}," {\n",[101,637,639],{"class":103,"line":638},19,[101,640,641],{"class":307},"  // Only messages from actors in the same scope arrive here\n",[101,643,645,648,650,652,655],{"class":103,"line":644},20,[101,646,647],{"class":125},"  console.",[101,649,292],{"class":121},[101,651,295],{"class":125},[101,653,654],{"class":132},"\"Scoped message:\"",[101,656,657],{"class":125},", data);\n",[101,659,661],{"class":103,"line":660},21,[101,662,663],{"class":125},"});\n",[665,666,668,673],"callout",{"type":667},"info",[14,669,670],{},[26,671,672],{},"Topic Namespace Format",[674,675,676,689],"table",{},[677,678,679],"thead",{},[680,681,682,686],"tr",{},[683,684,685],"th",{},"Scenario",[683,687,688],{},"Topic Format",[690,691,692,703],"tbody",{},[680,693,694,698],{},[695,696,697],"td",{},"Without scope",[695,699,700],{},[57,701,702],{},"app-slug/room-slug/topic",[680,704,705,708],{},[695,706,707],{},"With scope",[695,709,710],{},[57,711,712],{},"app-slug/scope-slug/room-slug/topic",[18,714,716],{"id":715},"next-steps","Next Steps",[38,718,719,726,733],{},[41,720,721,725],{},[45,722,724],{"href":723},"/docs/scopes/concepts","Concepts"," - understand how scopes work under the hood",[41,727,728,732],{},[45,729,731],{"href":730},"/docs/scopes/multi-tenancy","Multi-Tenancy Patterns"," - real-world patterns for tenant isolation",[41,734,735,739],{},[45,736,738],{"href":737},"/docs/scopes/api-reference","API Reference"," - complete endpoint documentation",[741,742,743],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":97,"searchDepth":129,"depth":129,"links":745},[746,747,748,749,750,751],{"id":20,"depth":129,"text":21},{"id":35,"depth":129,"text":36},{"id":70,"depth":129,"text":71},{"id":311,"depth":129,"text":312},{"id":464,"depth":129,"text":465},{"id":715,"depth":129,"text":716},"Quickstart guide to Access Scopes for tenant isolation in NoLag. Create scopes, assign actors, and verify communication isolation.","md",{},"/docs/scopes/getting-started",{"title":5,"description":752},"docs/scopes/getting-started","UqC-vbLHFTKMfj-UNsTEhZwRscVEpmWibwfWrHyNbQI",1788160344408]