Worked sequences
The endpoint list below documents each operation with its parameters. These four sequences cover the read-and-triage loop that powers a notification center of your own: poll the badge, page through the filtered feed, clear it either selectively or in bulk, and set the toggles that decide which categories each member gets notified about. Every request uses your API key (X-API-Key) against https://api.orbit.devotel.io. For the operator-facing
breakdown of kinds, delivery channels and the console workflow, see
Triage the Notification Center.
Sequence 1 — poll the badge, then read the feed
The loop an external notification center runs on a cadence (the dashboard bell runs it every ~30 seconds per tab): check the counter, and only fetch the filtered list when the counter moved. Step 1 — check the unread counter.cURL
200 OK
unread_only, kind, severity,
source_pillar, and category combine on the query string, newest rows
first. meta.pagination.has_more tells you whether another page exists; pass
meta.pagination.cursor back as cursor and treat it as opaque, keeping the
same filters across pages. A malformed filter value is ignored rather than
rejected — the list loads unfiltered.
cURL
200 OK
has_more is false, so this page is the whole result set — no cursor
to pass. Neither this sequence nor the next has any write side effects, so
the badge still reports 3 until Step 2 of Sequence 2 runs.
Sequence 2 — clear items, selectively or in bulk
Marking read and dismissing are addressed one row per request — there is no batchids body on either. When you clear several rows at once (select-all in
a notification UI, or a sync loop draining its backlog), loop over the ids and
issue the per-row calls in parallel. For “clear everything”, prefer one call
to read-all over N per-row calls.
Step 1 — mark two rows read. PUT /{id}/read is idempotent, so a
parallel-loop retry past the first success is safe; it returns the updated row
with read_at populated.
cURL
200 OK
DELETE /{id} hides the row immediately
for the caller. It takes a 404 NOT_FOUND when the row is org-wide
(user_id: null) rather than addressed to you — those rows age out on their
own expires_at clock instead of being dismissible.
cURL
200 OK
data.affected counts genuine
unread→read transitions here — re-marking already-read rows returns zero.
cURL
200 OK
notifications.list / notifications.markRead /
notifications.markAllRead / notifications.archive helpers wrap these exact
routes. For the routes it has no helper for — the unread counter, the org
digest toggles below, the /{id}/read PUT — use the generic orbit.request
escape hatch:
Node.js
Sequence 3 — read + tune the org digest toggles
The per-organization email digest is the corporate preference surface: which categories are emailed, on what cadence, and to which members. Owner/admin leaves configure it; members inherit it. Security-critical kinds (sign-in alerts, API-key mints, role changes) ignore mute settings and always mint a bell row. Step 1 — read the current digest settings.cURL
200 OK
categories: [] (empty array) means every category is emailed, not none.
Step 2 — flip the toggles. PUT accepts any one of enabled,
frequency (daily or weekly), or categories (from billing,
security, messaging, campaigns, agents, system); it returns the
full saved record so no follow-up GET is needed.
cURL
200 OK
cURL
200 OK
PATCH /digest/recipients/{user_id} flips one member’s flag (owner/admin):
cURL
Sequence 4 — mute a category for your own seat (user-level)
The org digest above is a corporate preference; the per-seat mute is yours alone. Muting lives onGET/PUT /api/v1/settings/preferences — a namespaced
user-preferences blob the dashboard uses for theme, locale and notification
toggles, not under /notifications itself. Each category sits under the
notifications key; a muted category still mints an in-app bell row (only
outbound email/push/webhook delivery is suppressed), and security-critical
kinds (sign-in, API-key, role-change events) override the mute entirely.
cURL
200 OK
theme block survives):
cURL
200 OK