> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure and run the Email Digest admin console

> Walk the Email Digest page end-to-end — enable the org roll-up, pick a cadence and categories, manage the recipient list, preview before you send, and do the same over the API.

# Configure and run the Email Digest admin console

The Email Digest console at **Settings → Notifications → Email Digest** (`/settings/notifications/digest`) is the admin-controlled side of notification delivery. This guide walks every control on the page in order, then shows the equivalent API calls.

## 1. The two-layer notification model

Notifications serve two layers. The **per-user layer** is each member's own preference sheet at **Settings → Notifications**: per-category channel toggles (email, push, webhook) and a per-category frequency (immediate, daily digest, weekly digest). The **org layer** is the digest described here: one administrative page that decides whether the org sends a periodic roll-up email at all (the master toggle), how often (frequency), what it covers (included categories), and who receives it (the recipients list). Both layers gate a digest send — a member only gets the roll-up if the org digest is enabled *and* their recipient row is opted in. For the per-user layer, see [Notification digest vs. per-user preferences](https://docs.orbit.devotel.io/guides/digest-and-notification-channels-faq.md).

## 2. Walk the digest page controls

Open **Settings → Notifications → Email Digest**. The page loads with the current org settings; writes are gated to owners and admins.

**Enabled (org master toggle).** The switch in the page header. Off means no digest email leaves for anyone, whatever the recipients list says. Auto-saves as soon as you flip it — there is no separate save button. Below the switch, the card shows the timestamp of the last digest sent, or that none has been sent yet. While the digest is disabled, the frequency buttons and category checkboxes stay visible but are disabled.

**Frequency — Daily or Weekly.** Pick one. This sets both how often the scheduler fires and the lookback window the roll-up aggregates: daily covers the last 24 hours, weekly covers the last 7 days. One email per opted-in recipient per cycle. Applying the choice takes effect immediately.

**Included categories.** Six checkboxes — Billing, Security, Messaging, Campaigns, Agents, System. These cap which per-user "digest me" categories the roll-up may cover. An **empty selection means all categories** — that is the default, and unchecking every box returns you to it rather than selecting nothing. To exclude one category, uncheck just that box.

**Preview next digest.** The button at the bottom computes the payload that would go out right now without emailing anyone. The preview dialog shows the window it aggregated (start to end timestamp), per-window counts — campaigns sent, messages delivered, messages failed, conversations started, agent runs, credits spent — and the highlights list. **Run it before enabling the digest**: if the window is empty, recipients would get nothing anyway, and the preview confirms the roll-up contains what you expect before the org starts receiving it. Every control auto-saves, so previewing is the only "try before you commit" step the page offers — use it.

A typical first-time flow: check the recipients list, run **Preview next digest**, confirm the counts look right, then flip **Enabled** on.

## 3. Recipients management

The **Recipients** list holds one row per org member, each with its own opt-in switch.

**How the list is seeded.** Owners and admins are opted in by default; every other role starts opted out. The list merges the explicit recipient registry with the org's membership, so members who never had their row toggled appear with their default. No row is written until an admin actually flips a switch — the first flip materializes a persistent record for that member.

**Flip a row.** Toggle the switch to opt a member in or out. The change saves immediately and applies from the next cycle.

**Drain-on-opt-out.** Opting out is safe to do mid-cycle: recipients are re-checked at fan-out time, so an opted-out member does not receive a queued send. If the registry ever disagrees with membership — say a role changed — re-flipping the row early at most reverts excess rows to the member's default; it never errors.

Because the recipient registry is admin-managed, members cannot subscribe themselves — an owner or admin flips their row. The org never silently subscribes the whole team.

## 4. API parity

Every console action maps to an endpoint under `/api/v1/notifications/digest`. All five routes require an authenticated session; the three writes are additionally gated to the `owner` and `admin` roles. JSON response envelopes are trimmed here for readability.

**Read the current org settings** — the same state the page header, frequency buttons, and category checkboxes render:

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/notifications/digest/settings \
  -H "Authorization: Bearer $API_KEY"
```

```json theme={null}
{
  "data": {
    "enabled": true,
    "frequency": "daily",
    "categories": [],
    "last_digest_at": "2026-09-08T06:00:00.000Z"
  }
}
```

**Update settings** — equivalent to flipping the master toggle, picking a frequency, or changing included categories. Send at least one of `enabled`, `frequency`, `categories`; omit fields you are not changing. An empty `categories` array means *include all*. Every update writes an audit entry recording the before/after transition.

```bash theme={null}
curl -X PUT https://api.orbit.devotel.io/api/v1/notifications/digest/settings \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"enabled": true, "frequency": "weekly", "categories": ["billing", "messaging"]}'
```

A body with none of the three fields returns `422` with `VALIDATION_ERROR`.

**List recipients with their opt-in state** — the recipients table:

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/notifications/digest/recipients \
  -H "Authorization: Bearer $API_KEY"
```

```json theme={null}
{
  "data": {
    "data": [
      { "user_id": "user_2abc", "name": "Ada", "email": "ada@example.com", "role": "admin", "opted_in": true },
      { "user_id": "user_2def", "name": "Sam", "email": "sam@example.com", "role": "viewer", "opted_in": false }
    ]
  }
}
```

**Toggle one recipient** — one row's switch:

```bash theme={null}
curl -X PATCH https://api.orbit.devotel.io/api/v1/notifications/digest/recipients/user_2def \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"opted_in": true}'
```

Toggling a `user_id` that is not a member of the org returns `404`.

**Preview the next digest** — the preview dialog. With no query parameter the lookback window follows the stored frequency (24h for daily, 168h for weekly); pass `?hours=` to override it (integer, 1–168):

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/notifications/digest/preview?hours=24" \
  -H "Authorization: Bearer $API_KEY"
```

```json theme={null}
{
  "data": {
    "window_start": "2026-09-08T06:00:00.000Z",
    "window_end": "2026-09-09T06:00:00.000Z",
    "is_empty": false,
    "counts": {
      "campaigns_sent": 3,
      "messages_delivered": 10412,
      "messages_failed": 87,
      "conversations_started": 642,
      "agent_runs": 210,
      "credits_debited": 48190
    },
    "highlights": [{ "kind": "campaign", "title": "…", "body": "…" }]
  }
}
```

## 5. How the digest interacts with per-user frequency

The digest only ever re-batches what per-user preferences deferred. A category a member set to **immediate** fires as the event happens and is *never* re-batched into the roll-up — the digest does not echo it a second time. Categories set to **daily digest** or **weekly digest** batch only when the org digest also fires: org toggle on, member opted in, category included. If the org digest is off, a per-user digest frequency simply has no roll-up to land in — nothing sends. Muting a channel stops outbound delivery for that category only; the in-app bell row is still minted and readable in the [Notification Center](https://docs.orbit.devotel.io/guides/in-dashboard-notifications.md).

## 6. Security categories are always-on

Security-notification kinds — new sign-in from an unknown IP or device, password and email changes, two-factor changes, API key creation or revocation, member role changes — are delivered regardless of channel mutes and regardless of category inclusion in the digest. A suppressible security preference would let a hijacked session mute the takeover signal, so the platform does not offer one. Muting stops routine noise; it can never blind you to a compromise.

## Troubleshooting

* **The digest page is read-only for me.** Writes are gated to the `owner` and `admin` roles — viewers, supervisors, and developers can open the page but cannot change the toggle, cadence, categories, or recipient rows. Ask an admin to make the change.
* **Preview shows an empty window.** No aggregatable events landed in the lookback window. The scheduler behaves the same way: it skips the cycle rather than emailing an empty summary, so an empty preview means receivers would have gotten nothing.
* **A late scheduler tick worries me about double-sends.** The scheduler enforces a minimum interval between digest sends, so a delayed tick cannot fire a second roll-up inside the same window.
* **A member set `daily` but got no digest.** Three gates must all pass: the org **Enabled** toggle, the member's row in **Recipients**, and the category not excluded under **Included categories**. Check them in that order.
* **I excluded a category and now nothing is excluded.** Unchecking the last checked box collapses back to the include-all state. To keep exclusions, leave at least one box checked.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.