# Fakturor (/api/referens/invoices)

> Kundfakturor – lista, skapa, hämta och uppdatera fakturor samt bokföra, maila, skriva ut, makulera och kreditera via /3/invoices.

Fakturaresursen speglar Fortnox `/3/invoices`. Fakturan adresseras på sitt publika nummer (`DocumentNumber`), inte på ett internt id, och numret kan inte ändras. Det finns ingen `DELETE` – makulering sker via `/cancel` och kreditering via `/credit`.

Klirr bokför vid **utfärdandet**: när en faktura bokförs allokeras fakturanummer och OCR, verifikatet postas och status blir skickad – i ett och samma steg. Fortnox skiljer på att skapa, bokföra och skicka; i Klirr är `/bookkeep` och `/externalprint` därför samma sak.

**Scope:** `invoice` · <Plan min="ai_pro" />

## Endpoints [#endpoints]

| Metod och sökväg | Beskrivning |
|---|---|
| <Endpoint method="GET" path="/api/v1/3/invoices" /> | Lista fakturor (reducerad listform, utan rader) |
| <Endpoint method="POST" path="/api/v1/3/invoices" /> | Skapa ett utkast. Svarar `201`. |
| <Endpoint method="GET" path="/api/v1/3/invoices/{DocumentNumber}" /> | Hämta en faktura (fullständig form) |
| <Endpoint method="PUT" path="/api/v1/3/invoices/{DocumentNumber}" /> | Uppdatera ett utkast (partiellt) |
| <Endpoint method="PUT" path="/api/v1/3/invoices/{DocumentNumber}/bookkeep" /> | Utfärda och bokför |
| <Endpoint method="PUT" path="/api/v1/3/invoices/{DocumentNumber}/externalprint" /> | Markera som skickad (utfärdar och bokför) |
| <Endpoint method="GET" path="/api/v1/3/invoices/{DocumentNumber}/email" /> | Maila fakturan till kunden (utfärdar först om det behövs) |
| <Endpoint method="GET" path="/api/v1/3/invoices/{DocumentNumber}/print" /> | PDF – utfärdar först om det behövs |
| <Endpoint method="GET" path="/api/v1/3/invoices/{DocumentNumber}/preview" /> | PDF-förhandsgranskning utan sidoeffekter |
| <Endpoint method="PUT" path="/api/v1/3/invoices/{DocumentNumber}/cancel" /> | Makulera ett utkast |
| <Endpoint method="PUT" path="/api/v1/3/invoices/{DocumentNumber}/credit" /> | Kreditera en bokförd faktura i sin helhet |

Bas-URL: `https://app.klirr.ai/api/v1`. Skrivningar kuverteras i `Invoice`. Åtgärdsendpointen tar ingen kropp.

Ett `DocumentNumber` som inte är ett positivt heltal ger `404`.

## Listparametrar [#listparametrar]

Utöver [paginering](/api/paginering) (`page`, `limit`, `offset`) och `sortorder` (`asc`/`desc`):

| Parameter | Värden | Beskrivning |
|---|---|---|
| `filter` | `cancelled`, `fullypaid`, `unpaid`, `unpaidoverdue`, `unbooked` | Se tabellen nedan. Okänt värde = inget filter. |
| `sortby` | `customername`, `customernumber`, `documentnumber`, `invoicedate`, `ocr`, `total` | Standard är `documentnumber`. |
| `customernumber` | text | Exakt kundnummer. Okänd kund ger en tom lista, inte `404`. |
| `fromdate` | `ÅÅÅÅ-MM-DD` | Fakturadatum från och med. Ogiltigt datum ger `400`. |
| `todate` | `ÅÅÅÅ-MM-DD` | Fakturadatum till och med. Ogiltigt datum ger `400`. |
| `ocr` | text | Exakt OCR-nummer. |

Fortnox-parametrarna `yourordernumber` och `lastmodified` stöds inte ännu och ger `400` i stället för ett ofiltrerat svar.

### Filtervärden [#filtervärden]

| `filter` | Fakturor som ingår |
|---|---|
| `cancelled` | Makulerade (fullt krediterade) |
| `fullypaid` | Fullt betalda |
| `unpaid` | Bokförda och obetalda, inklusive förfallna. En delbetald faktura räknas hit. |
| `unpaidoverdue` | Som `unpaid`, men bara med förfallodatum före idag |
| `unbooked` | Utkast |

## Fält [#fält]

Fullständig form (`GET /3/invoices/{DocumentNumber}`, och svaret på `POST`, `PUT` och åtgärderna som returnerar JSON).

| Fält | Typ | Skrivskyddat | Beskrivning |
|---|---|---|---|
| `@url` | string | ja | Resursens URL. |
| `DocumentNumber` | string | ja | Fakturans publika nummer. |
| `CustomerNumber` | string | nej | **Obligatoriskt vid `POST`.** Kunden måste finnas, annars `404`. |
| `CustomerName` | string | ja | Kundens namn. |
| `Address1`, `ZipCode`, `City` | string | ja | Kundens adress. |
| `Country` | string | nej | Bärs vidare. Standard `Sverige`. |
| `OrganisationNumber` | string | ja | Kundens organisationsnummer. |
| `InvoiceDate` | string | nej | `ÅÅÅÅ-MM-DD`. Standard är dagens datum (svensk tid). |
| `DueDate` | string | nej | `ÅÅÅÅ-MM-DD`. Standard är `InvoiceDate` + `TermsOfPayment`, eller 30 dagar. |
| `TermsOfPayment` | string | nej | Antal dagar. I svaret härlett som `DueDate − InvoiceDate`. |
| `Net` | number | ja | Summa exklusive moms. |
| `TotalVAT` | number | ja | Moms. |
| `Total`, `Gross` | number | ja | Summa inklusive moms. |
| `RoundOff` | number | ja | Öresavrundning. |
| `Balance`, `TotalToPay` | number | ja | Återstående belopp att betala, efter betalningar och krediteringar. `0` för en avskriven kundförlust. |
| `Booked` | boolean | ja | Se [livscykel](#livscykel). |
| `Sent` | boolean | ja | Se [livscykel](#livscykel). |
| `Cancelled` | boolean | ja | Se [livscykel](#livscykel). |
| `OCR` | string | ja | Genereras vid utfärdandet. |
| `Comments` | string | nej | Anteckning. `"API_BLANK"` tömmer. |
| `Currency` | string | nej | Endast `SEK` kan skrivas. |
| `CurrencyRate` | number | nej | Växelkurs. |
| `CurrencyUnit` | number | ja | Alltid `1`. |
| `TaxReductionType` | `none` \| `rot` \| `rut` \| `green` | nej | Husavdrag. |
| `BasisTaxReduction` | number | ja | Underlag för husavdrag. |
| `TaxReduction` | number | ja | Begärt avdrag. |
| `HouseWork` | boolean | ja | `true` när fakturan har husavdrag. |
| `AccountingMethod` | `ACCRUAL` \| `CASH` | ja | Organisationens bokföringsmetod. |
| `InvoiceType` | string | nej | Bärs vidare. Standard `INVOICE`. |
| `PaymentWay` | string | nej | Bärs vidare. Standard `AG`. |
| `Language` | string | nej | Bärs vidare. Standard `SV`. |
| `VATIncluded` | boolean | nej | Alltid `false`. `true` ger `400`. |
| `Credit` | string | ja | Alltid `"false"` (sträng). |
| `CreditInvoiceReference` | string | ja | Alltid `"0"`. |
| `VoucherNumber`, `VoucherSeries`, `VoucherYear` | number / string / number | ja | Utfärdandeverifikatet. `0`/`""` för utkast. |
| `InvoiceRows` | array | nej | Fakturarader, se nedan. |

Skrivskyddade fält som skickas in ignoreras (en klient som läser och skriver tillbaka en faktura orörd får alltså inget fel). Fält som Klirr inte modellerar sparas och returneras oförändrade.

### Fakturarader [#fakturarader]

| Fält | Typ | Skrivskyddat | Beskrivning |
|---|---|---|---|
| `RowId` | number | nej | Radens id. Skicka `{ "RowId": 3 }` för att behålla en rad oförändrad vid `PUT`. |
| `ArticleNumber` | string | nej | Artikelnummer, `""` för fritextrad. |
| `Description` | string | nej | Radtext. |
| `DeliveredQuantity` | string | nej | Antal. **Sträng** i svaret. |
| `Price` | number | nej | À-pris exklusive moms. |
| `VAT` | number | nej | Momssats i procent. |
| `VATCode` | string | nej | Momskod. Måste stämma med `VAT`, annars `400`. |
| `AccountNumber` | number | ja | Intäktskonto, härlett ur momskod och momsbehandling. |
| `Unit` | string | nej | Enhet, returneras som den skickades. |
| `Total` | number | ja | Radsumma. |
| `PriceExcludingVAT`, `TotalExcludingVAT` | number | ja | Pris och summa exklusive moms. |
| `HouseWork` | boolean | nej | Raden omfattas av husavdrag. |
| `HouseWorkType` | string | nej | `EMPTYHOUSEWORK` när fakturan har husavdrag men raden inte. |
| `ContributionPercent`, `ContributionValue` | string | ja | Alltid `"0"`. |

`Discount`/`DiscountType` på rader, samt `Freight` och `AdministrationFee` på fakturan, stöds inte och ger `400` – lägg beloppet som en egen rad.

### Listform [#listform]

`GET /3/invoices` returnerar en reducerad rad utan `InvoiceRows`: `@url`, `Balance`, `Booked`, `Cancelled`, `CostCenter`, `Currency`, `CurrencyRate`, `CurrencyUnit`, `CustomerName`, `CustomerNumber`, `DocumentNumber`, `DueDate`, `ExternalInvoiceReference1`, `ExternalInvoiceReference2`, `FinalPayDate`, `InvoiceDate`, `InvoiceType`, `NoxFinans`, `OCR`, `Project`, `Sent`, `TermsOfPayment`, `Total`, `VoucherNumber`, `VoucherSeries`, `VoucherYear`, `WayOfDelivery`. Belopp och nummer (`Balance`, `Total`, `CurrencyRate`, `VoucherNumber` m.fl.) är **strängar** i listformen.

## Livscykel [#livscykel]

| Klirr-status | `Booked` | `Sent` | `Cancelled` |
|---|---|---|---|
| Utkast | `false` | `false` | `false` |
| Skickad, betald, förfallen, avskriven | `true` | `true` | `false` |
| Makulerad (fullt krediterad) | `false` | `false` | `true` |

En bokförd faktura kan inte ändras med `PUT` (bokföringslagen 5 kap. 5 §) – svaret är `409` med hänvisning till `/credit`.

## Skapa en faktura [#skapa-en-faktura]

`POST` skapar alltid ett obokfört utkast. Bokför det sedan med `/bookkeep`, `/email` eller `/print`. Anropet räknas mot planens fakturakvot (`403` när den är slut).

<Tabs groupId="lang" persist items={['curl','TypeScript']}>
<Tab value="curl">
```bash
curl -X POST https://app.klirr.ai/api/v1/3/invoices \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"Invoice":{"CustomerNumber":"1001","TermsOfPayment":"30","InvoiceRows":[{"Description":"Konsulttimmar","DeliveredQuantity":"10","Price":950,"VAT":25}]}}'
```
</Tab>
<Tab value="TypeScript">
```ts
const res = await fetch('https://app.klirr.ai/api/v1/3/invoices', {
  method: 'POST',
  headers: {
    Authorization: 'Bearer <access_token>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    Invoice: {
      CustomerNumber: '1001',
      TermsOfPayment: '30',
      InvoiceRows: [
        { Description: 'Konsulttimmar', DeliveredQuantity: '10', Price: 950, VAT: 25 },
      ],
    },
  }),
});
const { Invoice } = await res.json(); // 201 Created
```
</Tab>
</Tabs>

Svar (`201`, förkortat):

```json
{
  "Invoice": {
    "@url": "https://app.klirr.ai/api/v1/3/invoices/42",
    "DocumentNumber": "42",
    "CustomerNumber": "1001",
    "CustomerName": "Bergström Bygg AB",
    "InvoiceDate": "2026-10-18",
    "DueDate": "2026-11-17",
    "TermsOfPayment": "30",
    "Net": 9500,
    "TotalVAT": 2375,
    "Total": 11875,
    "Gross": 11875,
    "RoundOff": 0,
    "Balance": 11875,
    "TotalToPay": 11875,
    "Booked": false,
    "Sent": false,
    "Cancelled": false,
    "OCR": "",
    "Currency": "SEK",
    "CurrencyRate": 1,
    "CurrencyUnit": 1,
    "TaxReductionType": "none",
    "VATIncluded": false,
    "Credit": "false",
    "CreditInvoiceReference": "0",
    "VoucherNumber": 0,
    "VoucherSeries": "",
    "VoucherYear": 0,
    "InvoiceRows": [
      {
        "RowId": 0,
        "ArticleNumber": "",
        "Description": "Konsulttimmar",
        "DeliveredQuantity": "10",
        "Price": 950,
        "VAT": 25,
        "VATCode": "services_25",
        "AccountNumber": 3001,
        "Unit": "h",
        "Total": 11875,
        "PriceExcludingVAT": 950,
        "TotalExcludingVAT": 9500,
        "HouseWork": false,
        "HouseWorkType": "",
        "ContributionPercent": "0",
        "ContributionValue": "0"
      }
    ]
  }
}
```

## Lista fakturor [#lista-fakturor]

<Tabs groupId="lang" persist items={['curl','TypeScript']}>
<Tab value="curl">
```bash
curl "https://app.klirr.ai/api/v1/3/invoices?filter=unpaid&fromdate=2026-01-01&sortby=invoicedate" \
  -H "Authorization: Bearer <access_token>"
```
</Tab>
<Tab value="TypeScript">
```ts
const res = await fetch(
  'https://app.klirr.ai/api/v1/3/invoices?filter=unpaid&fromdate=2026-01-01&sortby=invoicedate',
  { headers: { Authorization: 'Bearer <access_token>' } },
);
const { Invoices, MetaInformation } = await res.json();
```
</Tab>
</Tabs>

```json
{
  "Invoices": [
    {
      "@url": "https://app.klirr.ai/api/v1/3/invoices/42",
      "Balance": "11875",
      "Booked": true,
      "Cancelled": false,
      "CostCenter": "",
      "Currency": "SEK",
      "CurrencyRate": "1",
      "CurrencyUnit": "1",
      "CustomerName": "Bergström Bygg AB",
      "CustomerNumber": "1001",
      "DocumentNumber": "42",
      "DueDate": "2026-11-17",
      "ExternalInvoiceReference1": "",
      "ExternalInvoiceReference2": "",
      "FinalPayDate": "",
      "InvoiceDate": "2026-10-18",
      "InvoiceType": "INVOICE",
      "NoxFinans": false,
      "OCR": "4200007",
      "Project": "",
      "Sent": true,
      "TermsOfPayment": "30",
      "Total": "11875",
      "VoucherNumber": "17",
      "VoucherSeries": "B",
      "VoucherYear": "1",
      "WayOfDelivery": ""
    }
  ],
  "MetaInformation": { "@TotalResources": 1, "@TotalPages": 1, "@CurrentPage": 1 }
}
```

## Uppdatera ett utkast [#uppdatera-ett-utkast]

`PUT` ändrar bara de huvudfält du skickar. Raderna följer Fortnox regel: utelämnas `InvoiceRows` behålls befintliga rader; skickas fältet **ersätts alla rader**. Ange `{ "RowId": n }` för de rader som ska stå kvar oförändrade. Se [Fortnox-kompatibilitet](/api/fortnox-kompatibilitet).

<Tabs groupId="lang" persist items={['curl','TypeScript']}>
<Tab value="curl">
```bash
curl -X PUT https://app.klirr.ai/api/v1/3/invoices/42 \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"Invoice":{"Comments":"Avser oktober","InvoiceRows":[{"RowId":0},{"Description":"Resekostnad","DeliveredQuantity":"1","Price":400,"VAT":25}]}}'
```
</Tab>
<Tab value="TypeScript">
```ts
await fetch('https://app.klirr.ai/api/v1/3/invoices/42', {
  method: 'PUT',
  headers: {
    Authorization: 'Bearer <access_token>',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    Invoice: {
      Comments: 'Avser oktober',
      InvoiceRows: [
        { RowId: 0 },
        { Description: 'Resekostnad', DeliveredQuantity: '1', Price: 400, VAT: 25 },
      ],
    },
  }),
});
```
</Tab>
</Tabs>

## Åtgärder [#åtgärder]

Alla åtgärder adresserar fakturan på `DocumentNumber` och tar ingen kropp. De som svarar med JSON returnerar `{"Invoice": {...}}` i fullständig form, läst om efter åtgärden.

### bookkeep [#bookkeep]

`PUT /3/invoices/{DocumentNumber}/bookkeep` utfärdar ett utkast: fakturanummer och OCR allokeras, verifikatet bokförs och status blir skickad. Ingenting mailas. En redan bokförd faktura ger `200` med resursen (idempotent), även vid samtidiga anrop.

<Tabs groupId="lang" persist items={['curl','TypeScript']}>
<Tab value="curl">
```bash
curl -X PUT https://app.klirr.ai/api/v1/3/invoices/42/bookkeep \
  -H "Authorization: Bearer <access_token>"
```
</Tab>
<Tab value="TypeScript">
```ts
const res = await fetch('https://app.klirr.ai/api/v1/3/invoices/42/bookkeep', {
  method: 'PUT',
  headers: { Authorization: 'Bearer <access_token>' },
});
const { Invoice } = await res.json(); // Invoice.Booked === true
```
</Tab>
</Tabs>

### externalprint [#externalprint]

`PUT /3/invoices/{DocumentNumber}/externalprint` – för när du levererar fakturan i ditt eget system. I Klirr gör den exakt samma sak som `/bookkeep`.

### email [#email]

`GET /3/invoices/{DocumentNumber}/email` mailar fakturan till kundens e-postadress. Observera att det är en `GET` med sidoeffekt, precis som hos Fortnox.

- Är fakturan ett utkast utfärdas och bokförs den först, och mailas i samma anrop.
- Är den redan bokförd skickas bara mejlet igen – inget nytt nummer eller verifikat.
- Saknar kunden e-postadress svarar API:t `400`.
- Misslyckas utskicket av en redan bokförd faktura svarar API:t `502`. Fakturan är oförändrad och anropet kan göras om.

### print [#print]

`GET /3/invoices/{DocumentNumber}/print` returnerar fakturan som PDF (`Content-Type: application/pdf`, `Content-Disposition: inline; filename="faktura-<nummer>.pdf"`). Ett utkast **utfärdas och bokförs först** – utskrift räknas som leverans. Klirr mailar ingenting. Personnummer maskeras i PDF:en. En faktura utan rader ger `400`.

<Tabs groupId="lang" persist items={['curl','TypeScript']}>
<Tab value="curl">
```bash
curl https://app.klirr.ai/api/v1/3/invoices/42/print \
  -H "Authorization: Bearer <access_token>" \
  -o faktura-42.pdf
```
</Tab>
<Tab value="TypeScript">
```ts
const res = await fetch('https://app.klirr.ai/api/v1/3/invoices/42/print', {
  headers: { Authorization: 'Bearer <access_token>' },
});
const pdf = await res.arrayBuffer(); // application/pdf
```
</Tab>
</Tabs>

### preview [#preview]

`GET /3/invoices/{DocumentNumber}/preview` returnerar en PDF utan sidoeffekter – fakturan utfärdas inte och ändras inte. Fungerar på utkast, som då märks `UTKAST`. Filnamnet är `forhandsgranskning-<nummer>.pdf`, svaret har `Cache-Control: no-store` och personnummer maskeras. En faktura utan rader ger `400`.

### cancel [#cancel]

`PUT /3/invoices/{DocumentNumber}/cancel` makulerar ett **utkast**. Utkastet raderas, och svaret är fakturan som den såg ut före raderingen med `Cancelled: true`. Efteråt ger `GET` på numret `404`.

En bokförd faktura kan inte makuleras – svaret är `409` med hänvisning till `/credit`.

### credit [#credit]

`PUT /3/invoices/{DocumentNumber}/credit` skapar en kreditfaktura för **hela** den bokförda fakturan, rad för rad, daterad idag. Delkreditering stöds inte via den här endpointen.

Avvikelse från Fortnox: kreditfakturan får en egen nummerserie i Klirr och är inte adresserbar som faktura. Svaret är i stället den **ursprungliga** fakturan, nu med `Cancelled: true` och `Balance` nollat.

- Ett utkast kan inte krediteras: `400` (makulera det med `/cancel`).
- En redan helt krediterad faktura: `409`.

## Fel [#fel]

| Status | `Code` | När |
|---|---|---|
| 400 | 9000400 | `CustomerNumber` saknas vid `POST`; ogiltigt datum eller `TermsOfPayment`; annan valuta än `SEK`; `VATIncluded: true`; `Discount`, `Freight` eller `AdministrationFee`; `VATCode` och `VAT` stämmer inte överens; ostödd sökparameter (`yourordernumber`, `lastmodified`); `/credit` på utkast; `/email` utan kundens e-post; `/print` eller `/preview` på faktura utan rader. |
| 403 | 9000403 | Planens fakturakvot är förbrukad (vid `POST`). |
| 404 | 9000404 | `Kan inte hitta fakturan`, eller kunden i `CustomerNumber` finns inte. |
| 409 | 9000409 | `PUT` eller `/cancel` på en bokförd faktura; `/credit` på en redan krediterad faktura. |
| 502 | 9000500 | Mejlet kunde inte skickas via `/email` (fakturan är oförändrad). |

Allmänna fel (401, 403, 429) beskrivs under [Felkoder](/api/felkoder).
