Skip to content

Permissions

Roy Padina edited this page Oct 23, 2026 · 2 revisions

Permissions

Every plugin can read the message that triggered it (see ctx in Authoring). Anything more needs a permission. Permissions are:

  • declared in plugin.json, each with a reason in permissionReasons
  • shown to the user before the plugin is enabled, and again when an update adds one
  • enforced: a method on ntfy exists only while its permission is granted, and every call checks again. The user can switch single permissions off at any time.

Grants belong to one copy of a plugin. A local folder with the same id as an installed plugin does not inherit its permissions.

Permission What the user sees API
(always) Read each message that triggers it and that topic's label. Never settings; topic names and server addresses are hidden (best-effort). ctx
history.read Read earlier messages of the topic that triggered it. ntfy.history(options)
topics.read See the labels of all topics. ntfy.topics()
publish Send messages to the user's topics, at most 10 a minute. ntfy.publish(message)
clipboard.write Put text on the clipboard. ntfy.copy(text)
openURL Open web links (http/https). ntfy.openURL(url)
storage Keep up to 1 MB of its own data. ntfy.storage.get/set/remove
ui Show its own popups with buttons. return {popup: …}

API

ntfy.history({topicId?, before?, after?, limit?}) needs history.read. Returns messages, newest first, shaped like ctx.message. topicId omitted means the triggering topic; another topic also needs topics.read. before and after are unix seconds. limit defaults to 50, max 200.

ntfy.topics() needs topics.read. Returns [{id, label}].

ntfy.publish({topicId, message, title?, priority?, tags?, click?, delay?}) needs publish. Sends to one of the user's topics and returns true when queued. message is required (up to 4096 characters). priority is 1 to 5 (default 3) and is lowered during quiet hours. tags up to 10. click only if http/https. NtfyBar recognises its own messages when they come back and runs no rules on them — except scheduled ones: delay (1.1+, 10 s – 3 days) has the server deliver it later, and then it runs rules like any message (that's how Alert Card's Snooze works).

ntfy.copy(text) needs clipboard.write. Replaces the clipboard (up to 1 MB).

ntfy.openURL(url) needs openURL. http or https only; anything else fails.

ntfy.storage needs storage:

  • get(key) returns the stored JSON value or undefined
  • set(key, value) returns true; fails if the data would pass 1 MB
  • remove(key) returns true

Keys are strings up to 200 characters. Each plugin has its own file; plugins cannot read each other's data.

Popups need ui. An action or onPopupAction may return {popup: spec}. See Popup Spec. Without ui that return value is an error.

What plugins can never do

With any permission: run commands or Shortcuts, use the network, read the clipboard or files, read or change settings and rules, subscribe or unsubscribe topics, or see topic names, server addresses or credentials.

A failed call (permission missing or switched off, bad arguments) throws a JavaScript error.

Canonical text: docs/permissions.md.

Clone this wiki locally