---
title: "Retrieve a invoice by number"
method: GET
path: "/v1/invoices/by-number/{year}/{number}"
tags: ["Invoices"]
---

# Retrieve a invoice by number

`GET /v1/invoices/by-number/{year}/{number}`

## Request

- Base URL: `https://api.officina.it`
- URL: `https://api.officina.it/v1/invoices/by-number/{year}/{number}`
- Auth: HTTP bearer

Returns the invoice carrying number `number` in year `year` (the year it was issued in) — the number shown in the app, e.g. 12/2026. Numbers repeat across sezionali: pass `sezionale_id` (a sezionale id, or `default` for the series without one) to search one series; without it every series is searched.

The response is identical to `GET /v1/invoices/{id}`. A number that matches more than one document (repeated in historical data) returns 409 `ambiguous_number` with their ids in `candidates`.

## Response `200`

The invoice, exactly as retrieving it by id returns it.

- Invoice: A workshop invoice. Multi-tenant: belongs to one company. Created from a worksheet; transitions draft → issued via `POST /v1/invoices/{id}/issue`.
  - `object` 'invoice', required
  - `id` string, required
  - `status` 'draft' | 'issued', required: Derived from `issued_at`. Soft-deleted invoices 404 before reaching the client — "deleted" is never emitted.
  - `title` string, nullable
  - `comments` string, nullable
  - `internal_comments` string, nullable
  - `payment_method` string, required
  - `payment_condition` string, required
  - `payment_due_at` string, date-time, required
  - `vat_exigibility` string, required
  - `sezionale_id` string, nullable
  - `pa_document_type` string, nullable
  - `pa_document_number` string, nullable
  - `pa_document_date` string, date-time, nullable
  - `pa_cig` string, nullable
  - `pa_cup` string, nullable
  - `customer_id` string, required
  - `vehicle_id` string, nullable
  - `worksheet_id` string, nullable
  - `seq_number` integer, required: Per-company monotonic invoice number. 0 on drafts; assigned atomically at issuance.
  - `total_before_tax` number, double, required: Money. Float64 — clients render via the workshop locale formatter; avoid arithmetic.
  - `total_tax` number, double, required
  - `total_after_tax` number, double, required
  - `total_discount` number, double, required
  - `total_after_discount` number, double, required
  - `total_payments` number, double, required
  - `outstanding_payments` number, double, required
  - `customer_name` string, required
  - `vehicle_name` string, nullable
  - `vehicle_license` string, nullable
  - `created_by_full_name` string, required
  - `sezionale_code` string, nullable
  - `work_category_name` string, nullable
  - `work_category_names` string[], required: Names of the linked worksheet's work categories, in order. `[]` when the invoice has no worksheet or the worksheet has none. `work_category_name` is the first one. Available since revision 2026-10-03.
  - `sdi_status` string, required: Italian SDI e-invoice lifecycle status. Empty string when no e-invoice exists for this invoice. Possible non-empty values: "sent", "rejected", "pending_normal", "pending_warning", "pending_late".
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required
  - `issued_at` string, date-time, nullable: Populated once the invoice is issued.
  - `deleted_at` string, date-time, nullable: Soft-deletion timestamp. Populated only on the response from DELETE /v1/invoices/{id}.
  - `line_items` InvoiceLineItem[]: Populated on detail and post-mutation responses. Omitted from list rows to keep payloads small.
    - `object` 'invoice_line_item', required
    - `id` string, required
    - `line_type` 'item' | 'note' | 'separator', required: `item` is a priced line. `note` is a description-only line and `separator` an empty spacer row: both print without quantity, price and VAT and carry zero amounts (ignore their numeric fields). Lines from documents without types report `item`.
    - `article_id` string, nullable
    - `description` string, required
    - `quantity` number, double, required
    - `unit_type` string, required
    - `unit_price` number, double, required
    - `unit_cost` number, double, nullable
    - `unit_discount_rate` number, double, required
    - `tax_rate` number, double, required
    - `vat_code` string, nullable
    - `vat_description` string, nullable
    - `total_price` number, double, required
    - `total_before_tax` number, double, required
    - `total_tax` number, double, required
    - `total_after_tax` number, double, required
    - `created_at` string, date-time, required

## Other responses

- `401`: Missing, malformed, expired, or wrong-audience bearer token.
- `402`: The company has no active subscription, or its plan does not include API access. API access is included in the Business and Illimitato plans.
- `403`: The authenticated user lacks the required permission.
- `404`: Resource does not exist OR belongs to a different company. The two cases are intentionally indistinguishable.
- `409`: The number matched more than one document — a number repeated in historical data. `candidates` lists their ids; retrieve the right one by id. For sezionale-numbered documents, passing `sezionale_id` narrows the search to one series.
- `422`: A request field is missing or invalid (fast-fail).
- `500`: Unhandled server error. Detail is logged, not exposed.

---

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