Core concepts

Organizations, projects, keys, project users, notifications, audiences, segments, read states and counts.

Organization

Your company or team. It owns team members, projects and the Stripe subscription. Plan limits such as monthly API requests (the requests your app's SDKs make) are counted across all projects of the organization. See Billing and limits.

Project

One app in one environment, for example "Acme web (production)". Everything else (keys, project users, notifications, segments, theme) belongs to exactly one project. A project has:

  • a default locale (en unless you change it), used when no better translation exists;
  • a theme sent to the SDKs;
  • signing keys for user tokens, and allowed origins.

Keys

KeyPrefixUsed bySecret?
Publishable keypk_SDKs in browsers and apps, sent with every client requestNo. It identifies the project; it can be rotated.
Signing keyssig_ (key id)Your backend, to sign a user token for each userThe private key is. Only its public half is stored; the private key is shown once. Up to two, for rotation.
Secret keyssk_Your backend, as Authorization: Bearer sk_… on server endpointsYes. Stored hashed, shown once, revocable. You can have several.

Every SDK request carries the publishable key and a user token: a short-lived JWT your backend signs with a signing key, naming the user (see Identity verification). See Security for what is safe where.

Project user

An end user of your app, as one project knows them. A project user is identified by your own user id (userId, up to 255 characters), so the same user id in two projects is two project users. A project user is created on the SDK's first request for that user, when you upsert it from your backend (PUT /v1/project-users/{userId}), or as an empty placeholder when you send a notification to its user id.

Project users have profile fields (email, name, avatarUrl, locale, timezone), custom attributes (up to 100 key/value pairs) and tags (up to 100 short labels). Profile fields and attributes can also be synced by the SDK; tags can only be set from your backend. Attributes and tags power segments and templates.

Notification

What you send. A notification has:

  • contents: the title, optional body and optional action label, keyed by locale ({ "en": {…}, "de": {…} }; more than one locale needs the Growth plan or higher);
  • an audience: who receives it;
  • optional category, actionUrl, imageUrl and arbitrary data;
  • optional publishAt (scheduling needs the Growth plan or higher) and expiresAt;
  • a status: draft, scheduled, published, expired or canceled.

Published notifications are immutable. Drafts and scheduled notifications can be edited; any notification can be canceled (removed from every feed, kept in history) or deleted.

Audience

TypeReachesPlans
allEvery user of the project, including users created laterAll
usersUp to 1,000 of your user idsAll
tagsProject users with any (or all) of up to 20 tagsGrowth and up
segmentProject users matching a saved segmentGrowth and up

all, tags and segment are evaluated when each user's feed loads, against the user's current profile. See Targeting.

Segment

A saved, named condition tree over project user fields, attributes and tags, such as attributes.plan = "pro" AND tags contains "beta". Because segments are evaluated at read time, editing a segment changes who sees every notification that targets it, including ones already published. See Segments.

Feed

The list of notifications a project user can currently see: published, not expired, not canceled, inside the plan's retention window, and matching the audience. Feed items are already localized (the locale field tells you which translation was used) and personalized. They are sorted newest first and paginated with a cursor.

States: read, seen, archived, clicked

Each feed item carries per-user state:

StateSet whenEffect
seenAtThe user opens the drawer (seen_all), or reads, clicks or archives the itemStops counting towards the badge
readAtThe user reads, clicks or archives an item, or uses "mark all as read" (read_all)Removes the unread dot
archivedAtThe user archives an itemHides it from the default feed; visible with status=archived
clickedThe user clicks the item or its actionCounted in notification stats

Users can also mark items unread and unarchive them. "Mark all as read/seen" is one request that covers every notification published before it, however many the user has. It doesn't add to each notification's read stats; only actions on single notifications do.

Counts

Every feed response and action response includes two counts:

  • unseenCount: unread notifications published since the user last opened the drawer. Show it on the bell badge. It drops to zero when the SDK sends seen_all.
  • unreadCount: notifications not yet read, excluding archived ones. Show it in the drawer or inbox (for example on an "Unread" tab).

Both counts cover the user's newest 100 notifications, so they never go above 100. The SDK badges show "99+" above 99.