---
title: "Read Notifications"
method: GET
path: "/api/autopilot/notifications"
tags: ["autopilot"]
---

# Read Notifications

`GET /api/autopilot/notifications`

## Request

- Base URL: `https://api.taxcompass.it` (the document declares no server; this is the origin it was published from)
- URL: `https://api.taxcompass.it/api/autopilot/notifications`
- Auth: HTTP bearer

The bell: materialise whatever has come due, then return the whole state.

``year`` defaults to the server's year for the same reason ``/incassi`` and
``/estimate`` do — the browser clock may sit in another timezone on
31 December and silence a warning that is owed.

Two kinds are materialised, from the two things that can come due.

**The forfettario ceiling alerts (AP-094)**, whose trigger is a share of the
cash collected in ``year`` and which therefore need nothing but the ledger
this router already keeps.

**The F24 countdowns (AP-061c)**, one per proposed instalment of ``year``
that has entered a reminder window. Their subject is the stored F24 row's own
identity (``f24-2026-acconto1``) rather than one composed here, so the bell
and the F24 page are talking about the same payment; :func:`_f24_reminders`
says which rows contribute and why the others do not.

Two properties of the write, both from the store and both load-bearing:
materialising is an upsert on the dedupe key, so this read is idempotent and
concurrent reads across replicas produce one row; and nothing due costs no
write at all, which is the overwhelmingly common case.

The ceiling alerts are written only for a profile that *says* it is
forfettario. The ceiling is a rule of that regime, so raising it against a
profile in regime ordinario — or one that has not chosen yet — would be a
warning about a limit the user is not subject to. Unlike ``/estimate`` this is
not a 422: the bell is a background surface and has other kinds to show, so a
profile it cannot compute an alert from simply contributes none. The F24
countdowns need no such gate: a stored row exists only where ``GET /f24``
already accepted the profile, so the ledger *is* the gate.

## Query parameters

- `year` integer, nullable

## Response `200`

Successful Response

- NotificationList: ``GET /api/autopilot/notifications`` — the bell's whole state. ``unread`` is counted over exactly the returned ``items``, so the badge can never disagree with the list the user then opens.
  - `items` NotificationRead[]
    - `id` string, uuid, required
    - `kind` string, required
    - `dedupe_key` string, required
    - `due_date` string, date, nullable
    - `payload` object
    - `read_at` string, date-time, nullable
    - `created_at` string, date-time, nullable
  - `unread` integer

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/taxcompass/apis/taxcompass-api.md) · [All operations](https://skmtc.dev/taxcompass/apis/taxcompass-api/llms.txt) · [OpenAPI document](https://skmtc.dev/taxcompass/apis/taxcompass-api/revisions/fef5fc6a9b91?raw)
