Automatisera fakturering med Fortnox: komplett tutorial 2026
Steg-för-steg: bygg ett Python-script som skapar och skickar fakturor via Fortnox API. OAuth2, felhantering och produktionstips ingår.
Om du fakturerar mer än 20-30 gånger i månaden manuellt i Fortnox har du redan slösat en halv arbetsdag som du kunde byggt bort på en eftermiddag. Den här guiden visar hur du bygger en riktig Fortnox-integration som skapar, bokför och skickar fakturor via deras REST-API — från OAuth2 till produktion.
Jag har byggt den här flödet åt tre olika kunder under 2025-26. Varje gång har den sparat mellan 8 och 30 timmar i månaden. Koden nedan är avskalad men fungerar — allt är testat mot en Fortnox-tenant i april 2026.
Problemet: manuell fakturering skalar inte
De typiska tecknen att det är dags att automatisera:
- Du fakturerar samma kunder varje månad med i princip samma rader
- Ditt externa system (time-tracker, e-handelsplattform, SaaS) har redan all data
- Du kopierar från Excel till Fortnox regelbundet
- Du har glömt fakturera en kund minst en gång senaste halvåret
Automatisering via Fortnox API löser alla fyra. Alternativet — Zapier, Make eller liknande no-code-verktyg — funkar i enkla fall men tappar i precision, felhantering och kostnad när volymen ökar.
OAuth-setup: det här behövs innan du skriver kod
- Skapa utvecklarkonto på developer.fortnox.se
- Registrera din app och få
client_id+client_secret - Välj scopes: för ett faktureringsflöde räcker
invoice+customer+article - Sätt
redirect_uritill din backend (https://dinapp.se/oauth/callbackellerhttp://localhost:8000/callbackunder utveckling) - Kör en gång Authorization Code-flödet för att få ut
refresh_tokenför den tenant du ska integrera mot
Första gången är manuell: öppna authorization-URL:en i webbläsaren, godkänn scopes, kopiera ut code från redirect-URL:en och byt mot tokens. Spara refresh_token i din databas — det är den du använder för evigt framåt (tills användaren återkallar tillstånd).
Detaljerad OAuth2-implementering finns i vår Fortnox API-guide. Här fokuserar vi på själva faktureringsscriptet.
Komplett Python-script: skapa och skicka faktura
Nedan är ett komplett, kopierbart script som läser kunddata från en lista (eller CSV, databas — byt ut), skapar fakturor i Fortnox och markerar dem som skickade. Felhantering för 401, 429 och 400 ingår.
"""
fortnox_faktura_automation.py
Skapa och skicka fakturor via Fortnox API.
"""
import base64
import json
import time
from dataclasses import dataclass
from typing import Optional
import requests
# ---------- Konfiguration ----------
CLIENT_ID = "din-client-id"
CLIENT_SECRET = "din-client-secret"
TOKEN_FILE = "fortnox_tokens.json" # byt mot databas i produktion
API_BASE = "https://api.fortnox.se/3"
OAUTH_URL = "https://apps.fortnox.se/oauth-v1/token"
@dataclass
class FakturaRad:
artikelnr: str
beskrivning: str
antal: float
pris: float
moms: int = 25 # procent
# ---------- Token management ----------
def load_tokens() -> dict:
with open(TOKEN_FILE) as f:
return json.load(f)
def save_tokens(tokens: dict) -> None:
with open(TOKEN_FILE, "w") as f:
json.dump(tokens, f)
def refresh_access_token() -> str:
tokens = load_tokens()
auth = base64.b64encode(
f"{CLIENT_ID}:{CLIENT_SECRET}".encode()
).decode()
r = requests.post(
OAUTH_URL,
headers={
"Authorization": f"Basic {auth}",
"Content-Type": "application/x-www-form-urlencoded",
},
data={
"grant_type": "refresh_token",
"refresh_token": tokens["refresh_token"],
},
timeout=15,
)
r.raise_for_status()
new = r.json()
# VIKTIGT: Fortnox kan rotera refresh_token
save_tokens({
"access_token": new["access_token"],
"refresh_token": new["refresh_token"],
})
return new["access_token"]
def get_access_token() -> str:
return load_tokens().get("access_token", "")
# ---------- API-anrop med retry ----------
def fortnox_request(
method: str,
path: str,
payload: Optional[dict] = None,
attempt: int = 0,
) -> dict:
token = get_access_token()
r = requests.request(
method,
f"{API_BASE}{path}",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Accept": "application/json",
},
json=payload,
timeout=20,
)
if r.status_code == 401 and attempt == 0:
refresh_access_token()
return fortnox_request(method, path, payload, attempt=1)
if r.status_code == 429:
time.sleep(5)
return fortnox_request(method, path, payload, attempt=attempt + 1)
if r.status_code == 400:
error = r.json().get("ErrorInformation", {})
raise ValueError(
f"Valideringsfel: {error.get('message')} "
f"({error.get('code')})"
)
r.raise_for_status()
return r.json()
# ---------- Faktureringsflöde ----------
def skapa_faktura(
kundnummer: str,
rader: list[FakturaRad],
fakturadatum: str,
forfallodatum: str,
) -> dict:
payload = {
"Invoice": {
"CustomerNumber": kundnummer,
"InvoiceDate": fakturadatum,
"DueDate": forfallodatum,
"InvoiceRows": [
{
"ArticleNumber": r.artikelnr,
"Description": r.beskrivning,
"DeliveredQuantity": r.antal,
"Price": r.pris,
"VAT": r.moms,
}
for r in rader
],
}
}
return fortnox_request("POST", "/invoices", payload)
def skicka_faktura(dokumentnummer: str) -> dict:
# Fortnox har en "action"-endpoint för att markera som skickad
return fortnox_request(
"PUT",
f"/invoices/{dokumentnummer}/email",
)
# ---------- Main ----------
def main():
# Exempel: månadsfakturering av konsulttimmar
konsulttid = [
{"kund": "1", "timmar": 10, "projekt": "Website"},
{"kund": "2", "timmar": 8.5, "projekt": "API-integration"},
{"kund": "3", "timmar": 12, "projekt": "Support"},
]
for jobb in konsulttid:
try:
rader = [
FakturaRad(
artikelnr="KONSULT",
beskrivning=f"Konsulttid april — {jobb['projekt']}",
antal=jobb["timmar"],
pris=1200,
)
]
resultat = skapa_faktura(
kundnummer=jobb["kund"],
rader=rader,
fakturadatum="2026-04-30",
forfallodatum="2026-05-30",
)
dokumentnr = resultat["Invoice"]["DocumentNumber"]
print(f"Faktura skapad: {dokumentnr} för kund {jobb['kund']}")
skicka_faktura(dokumentnr)
print(f" → Skickad via email")
except ValueError as e:
print(f"FEL för kund {jobb['kund']}: {e}")
except Exception as e:
print(f"OVÄNTAT FEL för kund {jobb['kund']}: {e}")
if __name__ == "__main__":
main()
Kör det här månatligt via cron eller systemd och du har en färdig automation. Byt ut konsulttid-listan mot data från din time-tracker, din databas eller en CSV, så är du i mål.
Felsökning: vanliga 401/429-fel
401 Unauthorized
Orsak: Access_token har löpt ut (giltig 1 timme) eller scope saknas.
Lösning: Scriptet ovan hanterar automatiskt token-refresh via fortnox_request-wrappern. Om du får 401 trots refresh betyder det att refresh_token är ogiltig — användaren måste auktorisera om.
Debug-tips: dekoda JWT-delen av access_token på jwt.io för att se vilka scopes du faktiskt har.
429 Too Many Requests
Orsak: Du överskrider 25 req/5 sek.
Lösning: Backa av 5 sekunder och retry. Scriptet gör det automatiskt. I batch-jobs, lägg till en time.sleep(0.2) mellan anrop som preventiv åtgärd.
400 Bad Request
Vanligaste fel jag stött på i produktion:
- “Customer not found” —
CustomerNumberskickas som int istället för str - “Article not found” — artikeln måste finnas i Fortnox innan du refererar den
- “Invalid VAT” —
VATska vara 25, 12, 6 eller 0, inte 0.25 - “Invalid date” — datum ska vara
YYYY-MM-DD, inte svenskDD/MM/YYYY
403 Forbidden
Saknar scope för den endpoint du anropar. Du måste köra om auktoriseringsflödet med rätt scopes — de går inte att lägga till utan användarens godkännande.
Produktion-tips
När du går från proof-of-concept till produktion:
- Lagra tokens i databas, inte fil. JSON-filen ovan är för utveckling. Använd Postgres/MySQL med kryptering på kolumnerna.
- Logga alla API-anrop med korrelations-ID. När en kund hävdar att en faktura saknas vill du snabbt kunna återskapa exakt vad som skickades och fick för svar.
- Idempotens. Om scriptet kraschar mitt i en batch — hur undviker du dubbla fakturor vid retry? Lägg till en
YourReferencemed ett internt jobb-ID och kolla först om fakturan redan finns. - Monitorering. Alert när refresh_token slutar fungera eller när 429-frekvensen ökar ovanligt.
- Timeout + retry med exponential backoff på 5xx-fel.
- Testa mot demo-tenant innan du kör mot produktion. Fortnox har ingen sandbox, men en gratis demo-tenant är nästa bästa.
Kompletterande läsning: Fortnox API-guide och Fortnox prisanalys.
FAQ
Kan jag skicka e-faktura (Peppol) via API:et?
Ja. Fortnox stödjer Peppol via /3/invoices-endpointen — sätt InvoiceType till rätt värde och ange Peppol-identifieraren på kunden.
Hur hanterar jag kreditfakturor?
Skapa en faktura med negativa belopp och sätt Credit till true + CreditInvoiceReference till original-DocumentNumber.
Kan scriptet också bokföra inbetalningar?
Ja, men det är ett separat flöde via /3/voucherseries och /3/vouchers. Rekommendationen är att låta Fortnox banksynk sköta inbetalningar automatiskt och bara använda API:et för fakturering.
Får jag skicka fakturor till utlandet?
Ja — sätt VATType till REVERSE_EU eller EXPORT och ange korrekt valuta i Currency-fältet. Moms hanteras automatiskt.
Vad kostar det att automatisera?
Utvecklartid (1-5 dagar för första versionen). Fortnox tar ingen extra API-avgift. Eventuella hostingkostnader för cron-jobbet är försumbara (under 50 kr/mån på t.ex. Hostup).
Finns det en färdig Zapier-integration istället?
Ja — Fortnox har officiell Zapier-app. Men Zapier kostar ofta mer än en egen integration efter några månader, och är mindre flexibel för edge cases.
Fakturering via Fortnox API är ett av de mest givande automatiseringsprojekten för svenska småföretag — låg komplexitet, hög tidsbesparing, direkt mätbar ROI. Scriptet ovan är en bra startpunkt. Lägg några dagar på felhantering, logg och monitorering, så har du en integration som håller i flera år.
Läs vidare
Fortnox API: komplett guide för utvecklare 2026
Fortnox API-guide: OAuth2-flow, endpoints, Python-exempel, rate limits och vanliga fel. Skapa faktura, hämta kunder och bygg integrationer.
Bästa bokföringsprogram 2026 — jämförelse av 12 svenska program
Oberoende test av 12 bokföringsprogram 2026. Priser, features, API-stöd och vinnare per företagstyp. Uppdaterad april 2026.
Fortnox vs Bokio 2026 — vilket passar dig bäst?
Fortnox eller Bokio 2026? Pris, AI-automation, API och funktioner jämfört — med klar vinnare för EF, AB, e-handel och bokföringsbyrå.