Server API

Every endpoint and server-only function the plugin adds, with its input and what it returns.

The plugin adds endpoints to auth.api. Each one is one of two kinds: server-only, or own rows.

  • Server-only endpoints are callable through auth.api from your server code. They are never exposed as an HTTP route.
  • Own rows endpoints need a session. They only ever see or change the caller’s own notifications.

Server-only endpoints

auth.api.notify

Creates notifications. Pass userId, organizationId, or both.

  • type and title are required.
  • userId creates one row for that user.
  • organizationId alone fans out one row per member. Fan-out also takes roles and excludeUserIds.
  • userId with organizationId creates one row for that member, stamped with the org. The user must be a member.
  • body, href and data (JSON) are optional.

Returns { count, notifications }.

See Notify an organization for the fan-out rules.

Inside a better-auth transaction (runWithTransaction, as in a @better-auth/scim projection), the notification and delivery rows are written in that transaction and commit or roll back with it. Nothing is sent inside the call: the emails go out from processDeliveries after the commit.

auth.api.processDeliveries

Sends due email deliveries. Call it from a cron. The optional body is { limit }, which overrides batchSize.

Returns { sent, skipped, retrying, failed, hasMore }.

See Email if unread.

notify rejects a type that starts with notifications. with BAD_REQUEST (RESERVED_NOTIFICATION_TYPE): those are the plugin’s own events. Both endpoints emit events through inbox({ onEvent }).

Own-row endpoints

auth.api.listNotifications

Query: filter ("unread" or "all"), limit (up to 100), offset, and organizationId.

Returns { notifications, hasMore }.

auth.api.markRead

Body: { id }. Marks one of the caller’s notifications read.

Returns { notification }.

auth.api.markSeen

Body: { ids }, up to 100 ids. Stamps seenAt on the caller’s notifications, which cancels pending emails. The panel calls it for rows that have been on screen.

Returns { count }.

auth.api.markAllRead

Body: an optional { organizationId }, which scopes the update to one org.

Returns { count }.

auth.api.unreadCount

Query: an optional organizationId.

Returns { count }.

Server-only functions

These are functions, not endpoints. Use them in your own scripts and hooks.

Function Description
deleteOrganizationData(auth, organizationId) Deletes an org’s notifications and their deliveries. Returns { notifications }, the count
deleteMemberData(auth, { userId, organizationId }) Deletes one member’s notifications in one org. Returns { notifications }
exportNotificationsData(auth, { organizationId?, cursor?, limit? }) One page (500 by default) of notifications, each with its deliveries and the user’s userEmail, as plain JSON with ISO dates. Returns { notifications, cursor }. Pass cursor back until it’s null

The plugin also declares byo hooks, so @byo-oss/core reaches it. sweepAll(auth) runs the same sweep as processDeliveries, so one cron route for every BYO plugin can replace the processDeliveries call. Core’s deleteOrganizationData and deleteMemberData call the functions above. With organizationCleanup: false only the sweep is declared.

exportNotificationsData pages by createdAt and resumes after the last row it returned, so a row deleted mid-export (a member leaving, say) doesn’t make the next page skip one. The cursor is opaque. A cursor from an earlier release (a bare number) throws: start over with no cursor and keep one copy of each id. See Upgrading.

Channel exports

@byo-oss/notifications/mailer exports mailerChannel, which returns an InboxChannel for inbox({ channels }):

Option Type Meaning
mailer Mailer Any mailer from @byo-oss/mailer. It owns the sender address
replyTo string, optional Reply-to address on every email
render (ctx) => { subject, html, text }, optional Builds the email, sync or async. Default: the title, the body and a View button

The entry also re-exports the Mailer, MailMessage and MailResult types from @byo-oss/mailer, and the RenderedEmail type with the renderEmail and notificationUrl helpers, for a custom render that wraps the default email or builds the link.

@byo-oss/notifications/wraps exports wrapsEmail, which is deprecated. Use mailerChannel with wrapsMailer from @byo-oss/mailer/wraps.

Edit this page on GitHub ↗@byo-oss/notifications 0.11.4