# FIZ Public API

> Markdown edition of the API overview at https://api.fiz.co/. Endpoint reference: OpenAPI at https://api.fiz.co/-json. Index: https://api.fiz.co/llms.txt

FIZ's public REST API for issuing and managing invoices, customers, and items.

## Authentication
API-key access requires an API key in the `x-api-key` header.
Each key belongs to one account/NIF and issues only for that account. Create your key at
[app.fiz.co/settings/integrations](https://app.fiz.co/settings/integrations).

Building an integration for customers? Follow the [partner app guide](https://api.fiz.co/docs/apps.md) for a working example, OAuth, signup, permissions and retries.
Registered apps can also use `Authorization: Bearer <access_token>` with resource `https://api.fiz.co`. Create an app at [Settings → Integrations](https://app.fiz.co/settings/integrations) and request explicit company consent. Never send a bearer and an API key together. A token for `/mcp` is not valid for REST.

OAuth supports invoices, customers and items (`invoicing.read`, `invoicing.write`, `invoicing.issue`), plus `GET /company` and `GET /series` (`company.read`). Other routes require an API key. Registered apps read their own records; `invoicing.read_all` additionally permits company-wide reads, without permission to modify other records. Customer cards are separate for each app, even for the same tax number.

Before issuing, check `GET /company` for readiness reasons and send the draft’s `updatedAt` as `expectedUpdatedAt` in the issue body. A changed draft is rejected. Readiness is a preliminary check, not a guarantee for a particular document. OAuth grants share a 300-request/minute budget across API replicas; a 429 carries `Retry-After`.

## Issuing flow
Invoices are first created as a **draft** (`POST /invoices`) and are only reported to the
Portuguese tax authority (AT) at the moment of **issuance** (`POST /invoices/{id}/issue`). You
can validate all the data — and even generate the PDF — before issuing. Use drafts to test your
integration without reporting to AT.

## Series and PDF templates
- **Series** — list the account’s series at `GET /series` and pass the relevant `id` in the
  `seriesId` field when creating an invoice to issue it in a specific series. If omitted, the
  default series is used.
- **PDF templates** — list templates at `GET /templates` and pass the relevant `id` in
  `GET /invoices/{id}/pdf?templateId=...` to generate the PDF with that template.

## Recurring invoices
A schedule is an invoice template that FIZ issues — and reports to AT — on its own, at the
frequency you set (`POST /invoices/scheduled`: `MONTHLY` on day 1, `WEEKLY` on Monday, …).
Manage it from your system: `PATCH /invoices/scheduled/{id}` changes the frequency, dates or
auto-send, or pauses and resumes it (`status`); `DELETE` ends it. Every document a schedule
issues carries its id as `scheduleTemplateId`, so `GET /invoices?scheduleTemplateId=...`
lists exactly what went out — that is how to reconcile. Requires a plan with recurring invoices.

## Idempotency
Every write endpoint accepts an optional `Idempotency-Key` (a UUID, say), recommended for safe retries. Retrying a
request with the same key returns the original response instead of executing it again — so a
timeout or a dropped connection never costs you a duplicate invoice. Send a new key for a new
request. Keys are scoped to your API key (or to the app, authorizing user and company for registered REST clients) and are remembered for 30 days.

- A replayed response carries `Idempotent-Replayed: true` and repeats the original status code.
- Reusing a key with a different request body is rejected with `422`.
- `409` means the first attempt is still running (retry with the same key, honouring `Retry-After`)
  or that its outcome is unknown — check whether it took effect, then retry with a **new** key.

A request we rejected before sending it on (a `400` from validation) leaves the key free to reuse.
Any other failure — including one the invoicing backend reports — may already have taken effect, so
the key is spent: check the result, then use a new key. Correcting a rejected payload is a new
request, so give it a new key.

Writes without the header execute without replay protection. If a response is lost, check the result before repeating an unkeyed request.

## Specification
OpenAPI is available at [`/-json`](https://api.fiz.co/-json) and [`/-yaml`](https://api.fiz.co/-yaml), ideal for generating a REST
client.
For AI coding agents: [`/llms.txt`](https://api.fiz.co/llms.txt) indexes Markdown editions of these docs.

## For Claude and ChatGPT (MCP connector)
FIZ is also an **MCP server**: connect it once and your assistant reads your documents, drafts
invoices and — only after you confirm each one — issues them.

Server URL: `https://api.fiz.co/mcp`

- **Claude** (web, desktop, mobile) — Settings → Connectors → *Add custom connector*, paste the URL,
  then sign in to FIZ and choose the company and permissions.
- **ChatGPT** — Settings → Apps & Connectors → *Create*, paste the URL, sign in to FIZ.
- **Claude Code** — `claude mcp add --transport http fiz https://api.fiz.co/mcp`, then `/mcp` → Authenticate.

No API key is involved: access is an OAuth connection you can revoke at any time in
[app.fiz.co/settings/integrations](https://app.fiz.co/settings/integrations). Details, permissions
and the list of tools: [api.fiz.co/docs/mcp](https://api.fiz.co/docs/mcp.md).

Prefer a coding agent with shell access? The open-source *skill*
[FIZ-co/fiz-invoicing-skill](https://github.com/FIZ-co/fiz-invoicing-skill) (MIT) drives this REST API instead.
