Message anatomy
A publish body is a small JSON object. Only message is required:
{
"title": "Deploy done",
"message": "v1.2.3 is live",
"priority": "normal",
"level": "success",
"badges": { "env": "prod", "region": "eu-west" },
"data": { "commit": "9b1759a", "pipeline": "release", "duration_s": 142 }
}
| Field | Required | Type | Default |
|---|---|---|---|
message |
yes | string (alias: body) |
— |
title |
no | string | topic name |
priority |
no | silent | normal | urgent |
normal |
level |
no | error | warning | success | info |
info |
badges |
no | flat object, max 3 pairs | — |
data |
no | flat object (Pro plans) | — |
Priority — how loudly it arrives
priority controls intrusiveness — how the notification behaves when it lands on a device:
| Priority | Behaviour |
|---|---|
silent |
Delivered quietly: no sound, no wake. It appears in the notification list and topic history. |
normal |
A standard notification with a sound. The default. |
urgent |
Time-sensitive: breaks through iOS Focus / Android DND where the user allows it. Reserve for things that need a human now. |
Priority must be one of those strings. Numeric priorities (ntfy-style "priority": 4) are rejected with 400.
Level — how it’s displayed
level is display-only severity: it colours the message in the app (and the badge rail on the feed card) but has no effect on delivery. error, warning, success, info.
Priority and level are orthogonal on purpose. A recovery notice might be "level": "success" with "priority": "normal"; a disk-space warning might be "level": "warning" but "priority": "silent" overnight.
Badges — pills on the card
badges is a flat key/value map rendered as up to 3 short pills on the notification card — ideal for at-a-glance context like environment or region:
{ "badges": { "env": "prod", "build": 128 } }
- Keys up to 24 characters, string values up to 32. Over-length keys or values are rejected with
400(nothing is silently truncated). - More than 3 pairs: the extras are dropped.
- Available on every plan.
Data — the metadata bag
data is a flat key/value map shown in the message’s detail sheet — room for longer context like URLs, commit hashes, or runbook links:
- Keys up to 64 characters, string values up to 256. Over-length fields are rejected with
400. - Values must be scalars (string, number, boolean). Nested objects, arrays and nulls are dropped silently.
- Pro plans only. On the Solo plan the bag is dropped at publish time — the message still delivers, badges included, so free-tier webhook integrations keep working.
Size limit
The whole payload — title, message, data, badges, plus the topic address and delivery envelope — must fit within ~4 KB (the APNs/FCM ceiling). Oversized publishes return 413 with the measured size.
What the device receives
Alongside your fields, Pinglet injects system keys into every push — topic, id, priority, level, and the badges — so the app files the message under the right topic even from a cold start. These take precedence over any same-named keys in your data.