Skip to main content
Most of what an expansion does needs no permission: pages, sidebar buttons, editors, item types, settings tabs, themes, events. None of that reaches outside the app. Four things do, and each is declared in meta.json and approved by the user.
A permission not in this list is a manifest error, so a typo is caught at load rather than at the call.

How approval works

1

Needs approval

An expansion that declares permissions loads as Needs approval and does not run.
2

Review permissions

The user presses Review permissions on the Expansions page and sees the plain-language lines above.
3

Approved

On approval the expansion starts. The grant is remembered.
An update that adds a permission asks again, listing only the new ones. The user can take approval back at any time with Revoke permissions, which stops the expansion and returns it to Needs approval.

Being refused

A call without its permission throws SdkPermissionError and logs:
fetch without network rejects with a message naming your expansion. Nothing is half-done; the call simply does not happen.

Asking for less

Declare only what you use. Every permission is a line the user reads before saying yes, and an expansion that asks for nothing starts immediately. If a feature needs a permission, consider putting the feature behind a button rather than making the whole expansion wait on approval.

What the environment gives you anyway

Inside your code you have standard JavaScript (Promise, Map, JSON, Intl, URL, TextEncoder, crypto, …), console, and timers that are cleaned up when your expansion unloads. You do not have window, document, require, process, localStorage or the app’s internals. fetch exists only with network.
This is a controlled environment rather than a hard sandbox: it keeps well-behaved expansions on the SDK and makes going around it a deliberate act, and NMCrate review is the gate for the rest. Do not treat it as a security boundary when deciding what to ship.