# Notifications

National Compute emails your organization when its account needs a
person. The console's **Notifications** page (Settings → Notifications)
sets who receives each category of email and what sends it. Billing is
the only category, and email the only channel: there is no in-app
notification, no Slack or webhook delivery, and no digest.

## Recipients

Each category has one recipient list. A recipient receives every
notification in the category or none; there is no subscription per
notification.

By default, Billing email goes to every member of your organization
who has an email address, and to the organization's
[billing contact email](#billing-contact-email) when one is set. Any
member can change the list: tick or untick any member, themselves or
others, and the billing contact. A member who joins later receives
Billing email until someone unticks them. A member with no email
address is listed and receives nothing. An address that is both a
member's and the billing contact receives one copy.

Members and the billing contact email are the only recipients. There
are no extra addresses and no distribution lists.

### Billing contact email

The billing contact email is the email of the organization's
[billing profile](https://docs.nationalcompute.com/billing.md#invoices), the one invoices print. Any
member can set, change or clear it on the Notifications page, with or
without a name and address in the profile. An email alone is not a
billing profile: issuing an invoice still needs a name and address. A
change prints on invoices issued
afterwards and never rewrites an issued one. A cleared billing contact
stays on the recipient list and receives nothing.

The address is one plain address, at most 254 characters. Before the
`@`: letters, digits and `. _ % + -`, with no dot at the start, at the
end or doubled. After it: at least two labels joined by dots, each of
letters, digits and hyphens with no hyphen at either end, the last one
two or more letters. Anything else, a list, a display name or quoting
included, is refused `422 bad-request` with `field` `email`. The
invoice billing profile's email follows the same rule. Notification
email skips a billing contact email that fails it, such as one saved
before the rule existed. A member's own address needs only to be one
plain address of at most 254 characters with no control characters;
notification email skips a member address that fails that.

## Billing notifications

| Notification | Sends | Default |
|---|---|---|
| [Low balance](#low-balance) | when the balance is projected to run out within 3 days at the last 24 hours' spend, or falls below an amount you set | on, with [two exceptions](#low-balance) |
| [Auto-reload failed](#auto-reload-failed) | when an auto reload card charge fails | on |
| [Promo credits expiring](#promo-credits-expiring) | before [Promo credits](https://docs.nationalcompute.com/credits.md#promo-credits) expire | on |

Any member can turn each notification on or off and change the low
balance threshold. A saved setting wins over the default either way.
**Reset** removes it, and the default follows your organization's facts
again: a reset low balance email turns off by itself once auto reload
is turned on. The page states why a default is off ("Off by default
because auto-reload is on").

### Low balance

The low balance email warns before the credits that pay for usage run
out. The threshold is one of two modes:

| Mode | Below the threshold when | Limits |
|---|---|---|
| Runway (the default) | the projected time left is under N days | N in whole days, 1 to 30; default 3 |
| Amount | the balance is under an amount | $1 to $1,000,000 |

A balance at or below zero is below the threshold in either mode.

It is off by default for an organization with
[auto reload](https://docs.nationalcompute.com/api/billing.md#balance-and-totals) on, whose card tops the
balance up, and for one that has never paid for credits, whose credits
all came from grants. Either can turn it on.

#### The projection

- **Balance**: the credits available to spend organization wide. For
  an organization whose money is one pool it is the
  [total balance](https://docs.nationalcompute.com/credits.md#total-balance-and-available-to-spend).
  Otherwise it is the available to spend for anything else (credits
  with no restriction, plus organization wide [advances](https://docs.nationalcompute.com/credits.md#advances)),
  less the unpaid that hits it. Restricted and locked credits are not
  part of it.
- **Spend**: your organization's usage charges over the last 24 hours:
  capacity, storage, Marshall model usage and Public Research, the
  ledger's category `usage`.
- **Runway**: the balance drained at that 24-hour spend rate. A Promo
  balance counts only until it expires. Promo credits are spent first,
  so only the part left unspent at the expiry drops out.

The spend counts every usage charge, including what Restricted and
locked credits pay. For an organization holding those, the projection
runs out sooner than its unrestricted credits really do. A Restricted
balance running low on one cluster sends no email.

With no usage charges in the last 24 hours there is no projection. In
runway mode only a balance at or below zero is then below the
threshold. An organization whose usage is not billed to its credits is
never checked and never receives the email.

The balance is checked every 15 minutes (currently), from ledger
figures 5 to 10 minutes behind real usage. The Billing page shows the same
projection beside the balance, and the
[billing summary](https://docs.nationalcompute.com/api/billing.md#runway) carries it as `runway`.

#### Cadence

An **episode** starts at the first check, with the email on, that
finds the balance below the threshold, and ends at the first check that
finds it above.

- At most one email goes out a day, whichever episode sent the last
  one. An organization that crosses its threshold back and forth within
  a day receives one email, not one per crossing.
- An episode's first email goes at the first check the daily limit
  allows. Later ones go at most once a day, and only while your
  organization had usage charges in the last 7 days: an idle
  organization below the threshold stops receiving it after a week.
- The first time in an episode the balance reaches zero, an out of
  credits email goes out at once, even within a day of a low balance
  email, unless an out of credits email already went in the last 24
  hours. At most one out of credits email goes out a day.

While the email is off and the balance stays below the threshold, the
episode stays open: turning the email on again continues it instead of
starting a new one. Since both daily limits count the last email of any
episode, turning the email off and on or changing the threshold adds no
email beyond them.

### Auto-reload failed

At most one email goes out per organization per 24 hours. It names
the newest failed auto reload charge, its amount and why it failed, and
counts every failed attempt since the previous email, those inside the
24 hours that sent no email of their own included. A failure is never
emailed twice, and one that happens while the email is off is never
emailed later. A failed charge pauses auto reload for 24 hours;
saving the auto reload setting on the Billing page again, after fixing
the card, ends the pause. The billing summary's
[`auto_reload`](https://docs.nationalcompute.com/api/billing.md#balance-and-totals) carries the same
attempt as `last` and the pause as `cooldown_until`.

### Promo credits expiring

The email goes out when the Billing page's notice starts: 3 days
before the expiry by default ([Promo credits](https://docs.nationalcompute.com/credits.md#promo-credits)). The lead
time is the platform's setting; the page shows it and no member can
change it.

At most one email goes out per organization per UTC day. It covers
every Promo balance inside the notice window that no earlier email
named, listed by expiry day with the amount for each day and the
total. A balance that enters the window
after the day's email is in the next day's. When the new balances total
under $1.00, no email goes out and they are never named later.

## The email

Every notification is a plain text email from
`National Compute <no-reply@nationalcompute.com>`; a reply goes to
support@nationalcompute.com. Each recipient gets their own message and
sees no other recipient's address. The email links to your
organization's Billing page and Notifications page. Its footer says why
the address receives it (a member of the organization, or its billing
contact) and that any member can change who receives Billing email on
the Notifications page.

There is no unsubscribe link. To stop receiving Billing email, untick
the address on the Notifications page, or ask a member to.

## Recent notifications

The Notifications page lists the last 20 notifications sent to your organization,
newest first: when, which notification, the subject and how many
addresses received it.

## Agent access

Two MCP tools carry the page for an agent signed in as a member
([MCP server](https://docs.nationalcompute.com/api/mcp.md)). Where notifications are not available to
your organization, `tools/list` leaves them out and `tools/call`
answers as for an unknown tool. There is no org API token route for
these settings. `notifications_write` is the ordinary two phase gate,
never the [human confirmation](https://docs.nationalcompute.com/api/mcp.md#human-confirmation) class: a
setting spends no money and destroys nothing.

| Tool | What it does |
|---|---|
| `notifications_read` | no arguments; answers the page as JSON: `categories[]` with each category's `recipients[]` and `rules[]`, `billing_email`, `recent[]` and `writable` |
| `notifications_write` | [two phase](https://docs.nationalcompute.com/api/mcp.md#two-phase-confirmation): the first call checks the arguments and answers a preview (`current` and `proposed`) with a `confirm_token`; the same call with the token applies the change and answers the same JSON as `notifications_read` |

`notifications_write` takes an `action`:

| `action` | Arguments |
|---|---|
| `subscribe` | `category` (`billing`), `recipient_kind` (`member` or `billing_email`), `recipient_id` (the member's username, or `billing_email`), `subscribed` |
| `rule` | `rule`, and `enabled` with optional `params`, or `reset: true` |
| `billing_email` | `email`; `null` or `""` clears it |

Saving the default value still saves a setting; `reset` is the way back
to the default. The read's fields:

| Field | Meaning |
|---|---|
| `recipients[]` | `kind`, `id`, `email` (`null`: no address, receives nothing), `name`, `subscribed`, and `default` (`true` while no member has changed this row). The `billing_email` row is always present |
| `rules[]` | `key` (`billing.low_balance`, `billing.reload_failed`, `billing.promo_expiring`), `label`, `enabled`, `default_enabled`, `default_reason` (`auto_reload`, `promo_only` or `null`), `customized`, `params`, `limits`, `status` and `last_sent_ms` |
| `params` | low balance: `mode` (`runway` or `amount`), `runway_days`, `amount_ucredits`. Promo credits expiring: `lead_days`, read only. Auto-reload failed: none |
| `status` | low balance only, else `null`: `state`, `figure_ucredits`, `spend_24h_ucredits`, `runway_hours` and `as_of_ms`, read as the billing summary's [runway](https://docs.nationalcompute.com/api/billing.md#runway) (`runway_hours` is its `hours`) |
| `recent[]` | `at_ms`, `category`, `rule`, `variant` (`low_balance`, `out_of_credits`, `reload_failed` or `promo_expiring`), `subject`, `recipients` (the number of addresses) |
| `writable` | whether the caller can change the settings |

A write refuses `422 bad-request` with `field` naming the problem:

| `field` | Cause |
|---|---|
| `action` | `action` missing, not a string, or other than `subscribe`, `rule` or `billing_email` |
| an argument's name | an argument the action does not take |
| `category` | an unknown category |
| `recipient` | a `recipient_kind` other than `member` or `billing_email`, a username that is not a member of your organization, or a `billing_email` row whose `recipient_id` is not `billing_email` |
| `subscribed` | not `true` or `false` |
| `rule` | an unknown rule key |
| `enabled` | not `true` or `false` (required unless `reset`) |
| `reset` | a value other than `true`, or `reset` beside `enabled` or `params` |
| `params` | not an object, an unknown key, `mode` missing, `runway_days` or `amount_ucredits` not a whole number inside the limits, `amount_ucredits` missing in amount mode, or any params on the other two rules (`lead_days` included) |
| `email` | missing, or an address that fails the [billing contact](#billing-contact-email) checks |
