Recept
Bokför från ditt system
Dagskassan ur kassasystemet, avgiften ur betalväxeln, den upplupna kostnaden ur tidsystemet. Ett anrop, ett verifikat i huvudboken — genom exakt samma bokföringsfunktion som formuläret i programmet använder, med alla spärrar kvar.
Debet & Kredit kör på din egen server, så bas-URL:en är din — inte vår. Skriv in den här, så byts den ut i varje kodexempel i dokumentationen.
Därför bygger vi inga färdiga kopplingar
Det finns ingen Shopify-, Stripe- eller kassaadapter i programmet, och det är ett val. En adapter mot någon annans API är löpande drift förklädd till funktion: den går inte att bygga rätt utan ett riktigt konto att pröva mot, och den går sönder när den andra parten ändrar något — vilket de gör när de vill, inte när det passar din bokföring.
Ett nej av det slaget håller bara om någon annan kan bygga kopplingen. Den här rutten är det som gör det möjligt. Du bygger den en gång, mot ett format som inte byter ägare, och den är din: koden ligger hos dig, nyckeln utfärdas av dig och kan återkallas av dig med ett klick.
Anropet
Skapa en nyckel med behörigheterna Bokföra och Läsa under Inställningar → API-nycklar. Båda behövs: radernas konton slås upp i kontoplanen för att momsen ska kunna kontrolleras innan verifikatet skrivs, och den uppslagningen är en läsning.
curl -X POST "https://din-installation.se/api/v1/verifikat" \
-H "Authorization: Bearer dk_live_DIN_NYCKEL" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-2026-0042" \
-d '{
"seriesCode": "A",
"date": "2026-03-12",
"description": "Dagskassa 12 mars",
"counterparty": "Kortinlösen AB",
"rows": [
{
"account": 1930,
"debit": 12500,
"credit": 0,
"note": "Insättning"
},
{
"account": 3001,
"debit": 0,
"credit": 10000
},
{
"account": 2611,
"debit": 0,
"credit": 2500
}
]
}'Svaret bär numret och en länk till posten — verifikationsnumret är bara unikt inom sin serie och sitt år, så logga label och id ihop.
{
"id": "8f14e45f-ceea-467a-9a3a-1f2b3c4d5e6f",
"series": "A",
"number": 12,
"label": "A12",
"verification_date": "2026-03-12",
"url": "https://din-installation.se/verifikat/8f14e45f-ceea-467a-9a3a-1f2b3c4d5e6f"
}Idempotency-Key är inte valfritt, och skälet är att ett verifikat inte går att ta bort
Bokföringen är oföränderlig — det är hela poängen. En dubbelpost rättas därför med ett ändringsverifikat och syns för alltid i huvudboken. Och det normala felet är inte att anropet inte kommer fram, utan att svaret inte gör det: kassasystemet ser en timeout, försöker igen, och dagskassan står bokförd två gånger.
Skicka därför din egen externa referens som nyckel — ordernumret, körningens id, datumet för dagskassan. Då blir ”samma händelse” och ”samma verifikat” samma sak per konstruktion, utan att du behöver hålla reda på något extra.
Samma nyckel, samma kropp → samma verifikat
Du får det sparade svaret tillbaka, med svarshuvudet Idempotent-Replay: true. Inget nytt verifikat skapas. Huvudet finns för att du ska kunna skilja ”min omsändning togs emot igen” från ”den bokförde en gång till”.
Samma nyckel, samma kropp, men det första anropet är inte klart → 409 idempotency_in_progress
Det här är det normala fallet när nätet tappar svaret: din klient ser en timeout efter några sekunder och skickar om medan det första anropet fortfarande arbetar. Vänta någon sekund och skicka om exakt samma anrop — då får du det första svaret. Byt inte nyckel och skapa inte ett nytt anrop: det första kan mycket väl ha bokfört, och en ny nyckel gör det till två verifikat.
Samma nyckel, annan kropp → 409 idempotency_conflict
Det är det verkliga misstaget: en klient som återanvänder sitt ordernummer för en annan affärshändelse. Att tyst utföra den andra hade skapat två verifikat under ett löfte om att inte göra det; att tyst svara med det första hade svarat på en fråga ingen ställde.
Ett nekat anrop släpper nyckeln
Får du 400 eller 422 sparas ingenting. Rätta kroppen och skicka om med samma referens — du ska inte behöva hitta på ett nytt ordernummer för att din första begäran var felskriven.
Spärrarna gäller lika
Verifikatet skrivs genom motorns egen funktion, inte förbi den. Det betyder att allt som gäller när du bokför själv gäller också här — och det är avsiktligt: ett API som kan skriva om reglerna är inget bokföringsprogram.
| Spärren | Svar | Vad du gör |
|---|---|---|
| Debet ≠ kredit, eller alla rader noll | 400 invalid_request | Rätta beloppen. Prövningen rör ingen databas — samma svar varje gång. |
| Färre än två rader | 400 invalid_request | Dubbel bokföring: varje affärshändelse har minst två sidor. |
| Perioden är låst, eller momslåst | 422 period_locked | Bokför på ett senare datum. Ett momslås öppnas aldrig igen — varken i gränssnittet eller via API:t. |
| Räkenskapsåret är avslutat | 422 period_locked | Bokslutet är fastställt. Posten hör hemma i det nya året. |
| Kontot finns inte, eller är avaktiverat | 422 unprocessable | Lägg upp kontot under Kontoplan. Rutten skapar aldrig konton — se nedan. |
| Serien finns inte för året | 422 unprocessable | Skapa serien under Inställningar, eller använd en som finns. |
Skillnaden mellan 400 och 422 är värd att bygga in i din felhantering: ett 400 betyder att kroppen är fel och att ett omförsök med samma innehåll ger samma svar, medan ett 422 betyder att vi läste och förstod — det gick bara inte att bokföra just nu, eller just så.
Två saker rutten aldrig gör
Den skapar aldrig konton
Ett konto som saknas i kontoplanen ger 422 med kontonumret utskrivet. En kontoplan som fylls på av varje inkommande anrop är ingen kontoplan — och vilka konton som finns är ett beslut om hur bokföringen ska läsas, inte en detalj en integration ska få avgöra i förbifarten. Samma linje som kundfakturarutten håller om kunder.
Den låter dig aldrig välja källa
Fältet source sätts av programmet. Systemkällorna — bokslutet, momsredovisningen och de ingående balanserna — är de enda bokningar som får göras i en låst period, och de skapas av programmet självt efter att anspråket bevisats. Ett anrop som ber om en annan källa avvisas i klartext i stället för att tyst få sin begäran omskriven.
Vilken väg ska du välja?
Tre rutter kan sätta något i bokföringen, och de svarar på olika frågor:
- POST /api/v1/verifikat — du vet vilka konton posten ska ha. Vilken affärshändelse som helst, direkt i huvudboken.
- POST /api/v1/kundfakturor — en färdig faktura mot en känd kund, som ska kunna skickas, förfalla och betalas. Använd den när du vill ha en faktura, inte bara en bokförd intäkt.
- POST /api/inbound/order — en butiksorder som ska tolkas: kunden kanske inte finns, kontot ska härledas, momsen räknas baklänges ur ett bruttopris.
Tumregeln: har posten en motpart som ska få ett papper är det en faktura. Är det en händelse som bara ska stå rätt i böckerna är det ett verifikat.
Vidare
- Referens: POST /api/v1/verifikat — alla fält och statuskoder.
- Referens: GET /api/v1/verifikat — läs tillbaka det du bokfört, med raderna.
- Fel och statuskoder — vad 422 betyder och vad du gör åt det.