Skip to content

Notifications and cards

A notification is multipart, with JSON as the base. Each notification carries several representations of the same content, and each client uses the best one it supports. The idea comes from e-mail, without its problems (free HTML, tracking, visual phishing).

{
"summary": "Deploy finished: api-v2 (3m12s)",
"card": { "title": "Deploy", "blocks": [] },
"rich": { "html_ref": "…", "height": 480 }
}
Part Required Where it shows
summary Yes Push, watch, small devices, the inbox list
card Recommended App, web app, open source clients
rich (HTML) No, always with card as the fallback App and web only, in a sandbox

A card has an optional title, an optional theme (accent color #RRGGBB and an icon, a URL or a short emoji) and 1 to 40 blocks.

Block Use Main fields
text Paragraph (plain text, up to 4000 characters) text
metric A number with a label and a change label, value, unit, delta ("+18%")
chart Line or bar chart from series kind (line/bar), x, series (up to 6)
table Columns and rows columns, rows (up to 200)
list Items with an optional icon items[].text, items[].icon
image An image by URL src, alt
progress Progress bar and steps (great for live cards) value (0..1), steps, current
buttons Links and plugin actions, not decisions (up to 4) buttons[].label, url or action
options Renders a yesno, single or multi question question_id
input Renders a text, voice, number or date question question_id

Here is a card using several of them, as the web app renders it:

Push / watchDaily sales: 1,284 orders (+18%)

Daily sales

Orders1,284+18%
Revenue48,210 USD+9%
MonSun
This week Last week
RegionOrdersChange
BR612+21%
US433+15%
EU239—

A decision is always rendered by the app, never by HTML.

  • Approval buttons, options, inputs and the biometrics prompt are native and declared in JSON.
  • HTML runs in an isolated WebView, with no network by default and no access to the app.
  • HTML can only call notific.reply() with actions already declared in JSON, and the final confirmation appears on a native screen the sender does not control.

The web renderer also treats every text as plain text (no HTML or markdown injection), opens only http(s) links in a new tab with noopener, accepts only http(s) or raster data:image images, and only #RRGGBB accent colors.

The same content becomes plain text in a push, a full card in the app, and a two-line summary on a small device. Live cards update the same card instead of creating new notifications.