# Quickstart: your first invoice from code

> Markdown edition of https://api.fiz.co/docs/quickstart. Português: https://api.fiz.co/docs/quickstart.md?lang=pt. Index: https://api.fiz.co/llms.txt

Five requests take you from an API key to a draft invoice you can open as a PDF, with your own code or with a coding agent. Nothing reaches the tax authority until the last, optional step.

## 1. Get an API key

Sign in to FIZ and open [Settings → Integrations](https://app.fiz.co/settings/integrations). Create an API key: it belongs to **one company** and can only issue for that company. Copy it once; FIZ stores only a hash.

Put it in the environment as `FIZ_API_KEY` and load it into the shell before running anything. Every snippet below, and the FIZ skill for coding agents, reads that variable, so you never paste the key into a chat, a prompt or a repository. A new terminal needs the load step again.

```
# .env (never commit it; add it to .gitignore)
FIZ_API_KEY=fiz_api_...
```

```
# A shell does not read .env by itself. Run this in the terminal you use for
# the snippets; a coding agent started from that terminal inherits the key.
set -a; source .env; set +a
```

> The key works against your real company. There is no fiscal sandbox: drafts are the test surface, and only the issue step (section 5) reports anything to the tax authority (AT).

## 2. Check the connection

The first request tells you whether the key works and whether the company can issue.

```
curl https://api.fiz.co/company \
  --header "x-api-key: $FIZ_API_KEY"
```

The response carries `id`, `name`, `taxpayerNumber`, `cae` and `readiness`. If `readiness.ready` is false, `reasons[].code` says what is missing (`AT_CREDENTIALS_REQUIRED`, `AT_SYNC_REQUIRED`, `SERIES_REQUIRED`) and `actionUrl` is the page in FIZ that fixes it. You can still create drafts while not ready.

A `401` means the key is missing or revoked. Note the `cae` value: a draft needs one of the company's activity codes.

## 3. Create a customer and an item

An invoice references a customer and one or more catalogue items by id. Create one of each and keep the returned `id` values. The `Idempotency-Key` header makes a retry safe: the same key returns the first response instead of creating a second record.

```
curl --request POST https://api.fiz.co/customers \
  --header "x-api-key: $FIZ_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: quickstart-customer-1' \
  --data '{"name":"Example customer","country":"PT"}'
```

```
curl --request POST https://api.fiz.co/items \
  --header "x-api-key: $FIZ_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: quickstart-item-1' \
  --data '{"name":"Example service","type":"SERVICE","unitPrice":10,"vatRate":"NORMAL"}'
```

Send only documented fields: validation is strict and an unknown field is a `400`. `vatRate` and any exemption code are a tax decision for the company; the example category is not tax advice.

## 4. Create a draft and look at it

Save this as `draft.json`, replacing the two ids with the ones you just received and `cae` with a value from your company response. The item reference is `items[].id`.

```
{
  "type": "INVOICE",
  "cae": "62010",
  "customerId": "aaaaaaaaaaaaaaaaaaaaaaaa",
  "items": [
    {
      "id": "bbbbbbbbbbbbbbbbbbbbbbbb",
      "quantity": 1
    }
  ]
}
```

```
curl --request POST https://api.fiz.co/invoices \
  --header "x-api-key: $FIZ_API_KEY" \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: quickstart-draft-1' \
  --data @draft.json
```

The response is the draft, with its `id`, `status` and `updatedAt`. Read it back and check totals, VAT and the customer block in the PDF before anything fiscal happens. The PDF endpoint returns a download link, not the file: fetch `url` from its response.

```
curl https://api.fiz.co/invoices/$INVOICE_ID \
  --header "x-api-key: $FIZ_API_KEY"

# The PDF endpoint answers { id, name, url }: download the url (jq extracts it).
PDF_URL=$(curl -s https://api.fiz.co/invoices/$INVOICE_ID/pdf \
  --header "x-api-key: $FIZ_API_KEY" | jq -r .url)
curl -L "$PDF_URL" --output draft.pdf
```

A draft can be changed with `PATCH /invoices/{id}` and removed with `DELETE /invoices/{id}`. Create as many as you need.

## 5. Issue (fiscal, irreversible)

Issuing assigns the number and ATCUD and reports the document to the AT. It cannot be undone; a mistake is corrected with a credit note. Do the first one by hand, after reading the PDF, and only when `readiness.ready` is true.

```
# Once per issue attempt. Store it next to the invoice id; a retry must reuse it.
ISSUE_KEY=$(uuidgen)
```

```
# Fiscal and irreversible. expectedUpdatedAt is the draft's updatedAt from GET /invoices/{id}.
# Safe to re-run after a lost response: the same ISSUE_KEY returns the recorded result.
curl --request POST https://api.fiz.co/invoices/$INVOICE_ID/issue \
  --header "x-api-key: $FIZ_API_KEY" \
  --header 'Content-Type: application/json' \
  --header "Idempotency-Key: $ISSUE_KEY" \
  --data '{ "expectedUpdatedAt": "2026-09-15T10:20:30.000Z" }'
```

Send the draft's current `updatedAt` as `expectedUpdatedAt`: if the draft changed in between, the request is refused instead of issuing a stale version. Generate the `Idempotency-Key` once per issue and store it next to the invoice id; after a lost response, retry with that same key and the server returns the recorded result instead of issuing twice. A new key is a new attempt.

> Recurring invoices (`/invoices/scheduled`) issue on their own once created or resumed. Payments, cancellations and credit notes are fiscal in the same way. The API reference documents each one.

## 6. Build it with a coding agent

Give your agent this prompt. It points it at the Markdown docs written for agents, fixes the key convention and keeps fiscal actions behind your explicit request.

```
I'm integrating FIZ, a certified invoicing API for Portugal (https://api.fiz.co).
Read https://api.fiz.co/llms.txt first and follow its links before writing any code.
My API key is in the FIZ_API_KEY environment variable. Never print it, log it or ask me to paste it.
Start with GET https://api.fiz.co/company to verify the key and the company's readiness.
Drafts are safe to create, change and delete. Do not call /issue, /pay, /cancel or credit-note endpoints unless I explicitly ask: they are fiscal and irreversible.
Task: <describe what to build>
```

- [Open in Claude ↗](https://claude.ai/new?q=I'm%20integrating%20FIZ%2C%20a%20certified%20invoicing%20API%20for%20Portugal%20(https%3A%2F%2Fapi.fiz.co).%0ARead%20https%3A%2F%2Fapi.fiz.co%2Fllms.txt%20first%20and%20follow%20its%20links%20before%20writing%20any%20code.%0AMy%20API%20key%20is%20in%20the%20FIZ_API_KEY%20environment%20variable.%20Never%20print%20it%2C%20log%20it%20or%20ask%20me%20to%20paste%20it.%0AStart%20with%20GET%20https%3A%2F%2Fapi.fiz.co%2Fcompany%20to%20verify%20the%20key%20and%20the%20company's%20readiness.%0ADrafts%20are%20safe%20to%20create%2C%20change%20and%20delete.%20Do%20not%20call%20%2Fissue%2C%20%2Fpay%2C%20%2Fcancel%20or%20credit-note%20endpoints%20unless%20I%20explicitly%20ask%3A%20they%20are%20fiscal%20and%20irreversible.%0ATask%3A%20%3Cdescribe%20what%20to%20build%3E)
- [Open in ChatGPT ↗](https://chatgpt.com/?q=I'm%20integrating%20FIZ%2C%20a%20certified%20invoicing%20API%20for%20Portugal%20(https%3A%2F%2Fapi.fiz.co).%0ARead%20https%3A%2F%2Fapi.fiz.co%2Fllms.txt%20first%20and%20follow%20its%20links%20before%20writing%20any%20code.%0AMy%20API%20key%20is%20in%20the%20FIZ_API_KEY%20environment%20variable.%20Never%20print%20it%2C%20log%20it%20or%20ask%20me%20to%20paste%20it.%0AStart%20with%20GET%20https%3A%2F%2Fapi.fiz.co%2Fcompany%20to%20verify%20the%20key%20and%20the%20company's%20readiness.%0ADrafts%20are%20safe%20to%20create%2C%20change%20and%20delete.%20Do%20not%20call%20%2Fissue%2C%20%2Fpay%2C%20%2Fcancel%20or%20credit-note%20endpoints%20unless%20I%20explicitly%20ask%3A%20they%20are%20fiscal%20and%20irreversible.%0ATask%3A%20%3Cdescribe%20what%20to%20build%3E)

For a project that keeps evolving, add one line to `CLAUDE.md`, `AGENTS.md` or `.cursorrules` so every session starts from the right place:

```
FIZ invoicing API: read https://api.fiz.co/llms.txt before touching the integration.
The API key is in FIZ_API_KEY; never print it. Drafts are safe; never call /issue, /pay, /cancel or credit notes unless asked.
```

### Other ways in

**Claude Code**: connect the FIZ MCP server and your assistant reads and drafts documents itself, with OAuth instead of a key. Details on the [MCP page](https://api.fiz.co/docs/mcp.md).

```
claude mcp add --transport http fiz https://api.fiz.co/mcp
```

-   **Skill**: the open-source [fiz-invoicing skill](https://github.com/FIZ-co/fiz-invoicing-skill) adds Portuguese VAT rules and a curl helper to Claude Code and other Agent Skills runtimes.
-   **Docs for agents**: [llms.txt](https://api.fiz.co/llms.txt) indexes Markdown editions of every page here; the OpenAPI document is at [/-json](https://api.fiz.co/-json).
-   **Building for your customers?** That is an OAuth app, not an API key: follow [Build an app with FIZ](https://api.fiz.co/docs/apps.md).
