# `PhoenixKitBilling.Notifications`
[🔗](https://github.com/BeamLabEU/phoenix_kit_billing/blob/0.8.1/lib/phoenix_kit_billing/notifications.ex#L1)

Billing notifications: who hears about an invoice or a payment, and when.

Sends go through core's notification layer, so each recipient's own
per-type preferences and delivery channels (in-app inbox, email,
Telegram, digest cadence) apply. This module only decides the audience
and the copy.

## Recipients

`admin_recipients/1` unions three sources, because no single one is
complete:

  * holders of the relevant permission key (`users_with_permission/1`)
  * **Owner-role holders**, whose access is implicit and who therefore
    have no permission rows at all
  * holders of the `"*"` superadmin key, likewise absent from a
    key-specific query

A resolver that queried only the first would miss the primary operator
of a default install — the person most likely to want the notification.

## Money copy carries no PII

Notification text names an invoice or order NUMBER and an amount, never
a customer name, address or email: a notification lands in someone's
inbox and can be routed onward to email or Telegram.

## Failure is never fatal

Every send is wrapped. A notification reports a committed fact — a
payment that has been recorded, an invoice that has been issued — and
must never be able to undo it.

# `admin_recipients`

Everyone who should hear about billing operations: holders of `key`,
unioned with Owner-role holders and `"*"` superadmins.

# `invoice_issued`

An invoice was issued: tells billing operators, and the customer.

Separate sub-types, so an operator muting the invoice firehose does not
also silence their own receipts.

# `payment_failed`

A payment attempt failed.

Admin-only: the customer already saw the failure in the checkout flow,
and a second channel telling them their card was declined is noise at
best. Operators need it, because a failed payment is work.

# `payment_received`

A payment was recorded against an invoice.

`paid` is the amount actually recorded. It matters: quoting the invoice
total on a PARTIAL payment tells an operator 500 arrived when 50 did.
Falls back to the invoice total when a caller has no amount to hand.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
