---
title: "Read Today"
method: GET
path: "/api/autopilot/today"
tags: ["autopilot"]
---

# Read Today

`GET /api/autopilot/today`

## 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/today`
- Auth: HTTP bearer

The signed-in home screen: one ordered list of everything true today.

The composition, the ordering and every refusal live in
``services.today_list``; this route's whole job is the gate, the year and the
response model. Three things about it are worth saying here, because each is a
property of the *endpoint* rather than of the composer:

* **It is a read.** Unlike ``/invoices`` (which polls SdI first), ``/f24``
  (which regenerates the year's proposed records) and ``/notifications``
  (which materialises what is due), nothing behind this path writes. That
  matters more here than anywhere else on the router: this is the screen a
  client polls, and a poll that moved rows would make the user's books a
  function of how long they left the tab open.
* **``year`` is the tax year**, defaulting to the server's, exactly as on
  ``/incassi``, ``/estimate`` and ``/deadlines`` — and for the same reason,
  that the browser clock may sit in another timezone on 31 December. It
  selects the imposta-sostitutiva instalments and nothing else; documents and
  bank movements are read for every year, because an invoice rejected on
  28 December is not less rejected on 1 January.
* **No route-level rate limit**, like every other read here: the autopilot's
  tighter bucket guards writes, and throttling the home screen would only
  break the UI.

There is no 422 for a profile this product cannot model. The list answers 200
with ``onboarding_incomplete`` naming the reason, because a home screen that
refuses is a dead end, where a home screen carrying the one thing to do next
is the whole point of the design.

## Query parameters

- `year` integer, nullable

## Response `200`

Successful Response

- TodayList: ``GET /api/autopilot/today`` — the whole signed-in home screen, in order. ``items`` arrives **sorted** and the client renders it as given: ordering is a judgement about what matters most today, it is made once here, and a client that re-sorted would be a second such judgement that the other two locales' clients would not share. ``clear_until`` is the load-bearing half of an empty list. A screen that says only "nothing to do" sends the user hunting through the other screens to check, and then we have built two products; a screen that says "nothing else is waiting until <date>" and names what falls then is a claim the user can act on. It is therefore the day the **next item appears** — not the day that obligation falls due, which ``next_after_clear.due_date`` carries — so the sentence stays true right up to the morning it changes. Both are ``None`` whenever ``items`` is non-empty: "nothing else is waiting" is not a thing to say next to a list of things that are. In the ``opening`` phase they are ``None`` for a second reason as well — the obligations they name are dated ones (an instalment, a payment term), and someone who has not opened a partita IVA has none. A date invented to fill the gap would be the product inventing a deadline. ``phase`` is carried rather than inferred from the kinds present: the client changes the whole frame of the screen on it (what the empty state says, which nav is shown), and deriving that from "do any of the item kinds start with ``plan_``" would be a second, weaker copy of a decision made once here. It has no default — every construction site states which half of the product it is describing, because the wrong answer is not a missing field, it is a screen telling someone with no partita IVA to go and reconcile their bank.
  - `as_of` string, date, required
  - `phase` 'opening' | 'running', required
  - `items` TodayItem[]
    - `id` string, required
    - `kind` 'plan_missing' | 'plan_clarifications_open' | 'plan_ateco_undecided' | 'piva_not_opened' | 'piva_arrived_unconfirmed' | 'onboarding_incomplete' | 'sdi_rejected' | 'invoice_overdue' | 'draft_invoice_waiting' | 'bank_unreconciled' | 'f24_due' | 'no_clients' | 'no_invoices', required
    - `urgency` 'overdue' | 'soon' | 'open'
    - `due_date` string, date, nullable
    - `amount_eur` string, nullable
    - `params` object
    - `href` string, required
  - `clear_until` string, date, nullable
  - `next_after_clear` TodayNext: The first thing that will land on the list once it is empty. Three fields and no ``href``: this is not something to do yet, and giving it a link would put a fourth tappable row under a screen whose whole claim is that there are none.
    - `kind` 'plan_missing' | 'plan_clarifications_open' | 'plan_ateco_undecided' | 'piva_not_opened' | 'piva_arrived_unconfirmed' | 'onboarding_incomplete' | 'sdi_rejected' | 'invoice_overdue' | 'draft_invoice_waiting' | 'bank_unreconciled' | 'f24_due' | 'no_clients' | 'no_invoices', required
    - `due_date` string, date, nullable
    - `amount_eur` string, nullable

## 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)
