# Skapa och skicka en faktura (/api/guider/skapa-och-skicka-faktura)

> Från ny kund till bokförd och mailad kundfaktura – kund, utkast, förhandsgranskning och utskick via API:t.

Den här guiden skapar en kund, lägger upp ett fakturautkast, förhandsgranskar det och mailar fakturan. Alla namn, nummer och belopp nedan är påhittade exempel.

Du behöver en access token med scopes `customer` och `invoice`. Se [Snabbstart](/api/snabbstart) och [Scopes](/api/scopes).

<Callout title="Bokföring sker vid utfärdandet">
I Klirr skapar `POST /3/invoices` alltid ett obokfört utkast. Fakturanummer, OCR och verifikat skapas först när fakturan utfärdas, med `/bookkeep`, `/externalprint`, `/email` eller `/print`. Därefter kan fakturan inte ändras – bara krediteras.
</Callout>

<Steps>
<Step>
### Skapa kunden [#skapa-kunden]

Hoppa över steget om kunden redan finns – sök i så fall med `GET /3/customers`. Enda obligatoriska fältet är `Name`. Ange `Email` om fakturan ska mailas. Utan e-postadress svarar `/email` med `400`.

<Tabs groupId="lang" persist items={['curl','TypeScript']}>
<Tab value="curl">
```bash
curl -X POST https://app.klirr.ai/api/v1/3/customers \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{"Customer":{"Name":"Lundgrens Måleri AB","OrganisationNumber":"556000-0002","Email":"ekonomi@lundgrensmaleri.se","Address1":"Verkstadsgatan 4","ZipCode":"702 10","City":"Örebro"}}'
```
</Tab>
<Tab value="TypeScript">
```ts
const BASE = 'https://app.klirr.ai/api/v1';
const headers = {
  Authorization: 'Bearer <access_token>',
  'Content-Type': 'application/json',
};

const res = await fetch(`${BASE}/3/customers`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    Customer: {
      Name: 'Lundgrens Måleri AB',
      OrganisationNumber: '556000-0002',
      Email: 'ekonomi@lundgrensmaleri.se',
      Address1: 'Verkstadsgatan 4',
      ZipCode: '702 10',
      City: 'Örebro',
    },
  }),
});
const { Customer } = await res.json(); // 201 Created
const customerNumber = Customer.CustomerNumber; // t.ex. "1002"
```
</Tab>
</Tabs>

Svaret är `201` med `{"Customer": {...}}`. Spara `CustomerNumber`, det är en **sträng**.
</Step>

<Step>
### Skapa fakturautkastet [#skapa-fakturautkastet]

`CustomerNumber` är obligatoriskt och kunden måste finnas (annars `404`). Varje rad behöver `Description`, `DeliveredQuantity` (sträng), `Price` exklusive moms och `VAT` i procent. `TermsOfPayment` är antal dagar; utan det blir förfallodatum 30 dagar efter fakturadatum.

<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":"1002","InvoiceDate":"2026-10-18","TermsOfPayment":"30","Comments":"Avser målning av trapphus, oktober","InvoiceRows":[{"Description":"Målning trapphus","DeliveredQuantity":"24","Price":650,"VAT":25},{"Description":"Material","DeliveredQuantity":"1","Price":3200,"VAT":25}]}}'
```
</Tab>
<Tab value="TypeScript">
```ts
const res = await fetch(`${BASE}/3/invoices`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    Invoice: {
      CustomerNumber: customerNumber,
      InvoiceDate: '2026-10-18',
      TermsOfPayment: '30',
      Comments: 'Avser målning av trapphus, oktober',
      InvoiceRows: [
        { Description: 'Målning trapphus', DeliveredQuantity: '24', Price: 650, VAT: 25 },
        { Description: 'Material', DeliveredQuantity: '1', Price: 3200, VAT: 25 },
      ],
    },
  }),
});
if (res.status !== 201) throw new Error(`Kunde inte skapa faktura: ${res.status}`);
const { Invoice } = await res.json();
const documentNumber = Invoice.DocumentNumber; // t.ex. "57"
```
</Tab>
</Tabs>

Svaret (`201`, förkortat) visar ett utkast: `Booked: false`, tomt `OCR` och `VoucherNumber: 0`.

```json
{
  "Invoice": {
    "@url": "https://app.klirr.ai/api/v1/3/invoices/57",
    "DocumentNumber": "57",
    "CustomerNumber": "1002",
    "CustomerName": "Lundgrens Måleri AB",
    "InvoiceDate": "2026-10-18",
    "DueDate": "2026-11-17",
    "Net": 18800,
    "TotalVAT": 4700,
    "Total": 23500,
    "Booked": false,
    "Sent": false,
    "Cancelled": false,
    "OCR": "",
    "VoucherNumber": 0
  }
}
```

Utkastet kan ändras med `PUT /3/invoices/{DocumentNumber}`. Skickar du `InvoiceRows` ersätts alla rader, så ta med `{ "RowId": n }` för rader som ska stå kvar. Se [Fakturor](/api/referens/invoices#uppdatera-ett-utkast).
</Step>

<Step>
### Förhandsgranska (valfritt) [#förhandsgranska-valfritt]

`GET /3/invoices/{DocumentNumber}/preview` returnerar en PDF märkt `UTKAST` utan sidoeffekter. Fakturan utfärdas inte.

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

Använd **inte** `/print` för förhandsgranskning: den utfärdar och bokför utkastet.
</Step>

<Step>
### Utfärda och maila [#utfärda-och-maila]

`GET /3/invoices/{DocumentNumber}/email` utfärdar utkastet (nummer, OCR och verifikat) och mailar det till kundens e-postadress i samma anrop. Det är en `GET` med sidoeffekt, precis som hos Fortnox. Anropet tar ingen kropp.

<Tabs groupId="lang" persist items={['curl','TypeScript']}>
<Tab value="curl">
```bash
curl https://app.klirr.ai/api/v1/3/invoices/57/email \
  -H "Authorization: Bearer <access_token>"
```
</Tab>
<Tab value="TypeScript">
```ts
const sent = await fetch(`${BASE}/3/invoices/${documentNumber}/email`, { headers });
if (sent.status === 400) throw new Error('Kunden saknar e-postadress');
const { Invoice: issued } = await sent.json();
console.log(issued.Booked, issued.OCR); // true, "5700003"
```
</Tab>
</Tabs>

Svaret är `200` med `{"Invoice": {...}}`, läst om efter utskicket: `Booked: true`, `Sent: true` och ifyllda `OCR`, `VoucherNumber`, `VoucherSeries` och `VoucherYear`.

Levererar du fakturan själv i stället? Anropa `PUT /3/invoices/{DocumentNumber}/bookkeep` (eller `/externalprint`, som gör samma sak) och hämta PDF:en med `/print`. Ingenting mailas då.
</Step>

<Step>
### Hantera omförsök [#hantera-omförsök]

- `/email` på en redan bokförd faktura skickar bara mejlet igen. Inget nytt nummer och inget nytt verifikat skapas.
- Misslyckas utskicket av en bokförd faktura blir svaret `502`. Fakturan är oförändrad och anropet kan göras om.
- `/bookkeep` är idempotent och svarar `200` med resursen även om fakturan redan är bokförd.
</Step>
</Steps>

## Om något blev fel [#om-något-blev-fel]

| Läge | Gör så här |
|---|---|
| Utkast som inte ska skickas | `PUT /3/invoices/{DocumentNumber}/cancel` raderar utkastet. |
| Bokförd faktura med fel | `PUT /3/invoices/{DocumentNumber}/credit` krediterar hela fakturan. Skapa sedan en ny. `PUT` och `/cancel` på en bokförd faktura ger `409`. |

## Nästa steg [#nästa-steg]

- [Registrera en betalning](/api/guider/registrera-betalning) när kunden har betalat.
- [Fakturor](/api/referens/invoices) – alla fält, filter och åtgärder.
- [Felkoder](/api/felkoder).
