accounted
← Blogg

Live runway och burn-rate direkt från bokföringen

En runway-dashboard som uppdateras i realtid kräver inte ett data warehouse. Två API-anrop mot huvudboken plus 80 rader Python räcker. Den här artikeln visar exakt hur: vilken formel, vilka konton, vilken cadence. Och varför nattliga batch-rapporter är fel verktyg för en metrik som ändras dagligen.

För ekonomi12 maj 2026Senast uppdaterad: 27 september 20265 min läsning

TL;DREn runway-dashboard som uppdateras i realtid kräver inte ett data warehouse. Två API-anrop mot huvudboken plus 80 rader Python räcker. Den här artikeln visar exakt hur: vilken formel, vilka konton, vilken cadence. Och varför nattliga batch-rapporter är fel verktyg för en metrik som ändras dagligen.

Det första någon med kassa borde göra i sitt företag är att bygga en runway-vy som inte är gjord en gång per kvartal i Excel. Inte för att Excel är fel, utan för att en siffra som ändras dagligen ska visas dagligen. Här är receptet.

Formeln

Klassisk runway:

runway = kassa / (trailing-90-dagars-burn / 90 * 30.4)

I praktiken:

  • Kassa = saldo på 1930 (bank) plus övriga bankkonton (1940) och likvida placeringar på t.ex. 1810
  • Burn = (rörelseutgifter under senaste 90 dagar) minus (rörelseintäkter under samma period)
  • Resultatet = antal månader

Vissa team räknar exklusive engångskostnader. Det är legitimt men du behöver vara konsekvent. Den enkla varianten är att räkna allt och vara medveten om att en hyresinbetalning kvartalsvis svänger siffran en månad.

Vad du behöver från huvudboken

Två API-anrop:

GET /api/v1/companies/{companyId}/reports/balance-sheet?period_id={period}

GET /api/v1/companies/{companyId}/reports/income-statement?period_id={period}

Balansräkningen ger dig kassan (1930 plus eventuella 1940- och 1810-saldon). Resultaträkningen ger dig intäkter och kostnader för fönstret, från vilka du beräknar burn. Det är allt.

Rapporterna hänger på räkenskapsperioden: period_id är obligatoriskt. Inom perioden väljer du fönster själv. Balansräkningen tar to_date (läget per ett visst datum), och resultaträkningen tar from_date och to_date, så ett rullande 90-dagarsfönster är ett enda anrop. Perioderna listar du med GET /fiscal-periods eller gnubok_list_fiscal_periods.

Vill du hellre ha färdiga siffror finns två genvägar. /reports/kpi ger kassan (cashPosition, summan av 19xx-kontona om du inte valt andra i nyckeltalsinställningarna) och en månadsserie med intäkter, kostnader och netto i samma svar. /reports/monthly-breakdown ger bara månadsserien.

I MCP-servern motsvarar anropen gnubok_get_balance_sheet och gnubok_get_income_statement. Båda är read-only, så en nyckel med bara reports:read räcker.

Tre nivåer av implementation

Nivå 1: Slack-bot på 30 minuter

Make eller n8n-flöde:

  1. Trigger: schemalagt varje vardag 08:00.
  2. HTTP mot accounted: hämta balansräkningen och resultaträkningen för de senaste 90 dagarna.
  3. Format: bygg ett Slack-block med kassa, burn, runway och en pil för riktning sedan i förrgår.
  4. Send: posta till #finance.

Total tid: en eftermiddag. Total kostnad: under 100 kr/månad eller gratis på n8n.

Nivå 2: Python-bot med trendjämförelse

Ungefär 80 rader Python. Skillnaden mot nivå 1 är att botten också:

  • Lagrar dagens snapshot i en SQLite-fil.
  • Jämför mot snapshot från 7, 30 och 90 dagar sedan.
  • Larmar i Slack om burn ändras med mer än 15 procent från trenden eller om runway sjunker under 6 månader.
import os, requests
from datetime import date, timedelta

API = "https://app.accounted.se/api/v1"
COMPANY = os.environ["GNUBOK_COMPANY_ID"]
PERIOD = os.environ["GNUBOK_PERIOD_ID"]   # gnubok_list_fiscal_periods
HEADERS = {"Authorization": f"Bearer {os.environ['GNUBOK_API_KEY']}"}

LIKVIDA = {"1930", "1940", "1810"}   # justera efter din kontoplan
IDAG = date.today()

def rapport(namn, **params):
    r = requests.get(f"{API}/companies/{COMPANY}/reports/{namn}",
                     params={"period_id": PERIOD, **params}, headers=HEADERS)
    r.raise_for_status()
    return r.json()["data"]

# Anrop 1: balansräkningen per i dag ger kassan och periodens start
bs = rapport("balance-sheet", to_date=IDAG.isoformat())
cash = sum(rad["amount"]
           for sektion in bs["asset_sections"]
           for rad in sektion["rows"]
           if rad["account_number"] in LIKVIDA)

# Anrop 2: resultaträkningen för de senaste 90 dagarna, inom räkenskapsåret
fran = max(date.fromisoformat(bs["period"]["start"]), IDAG - timedelta(days=90))
rs = rapport("income-statement", from_date=fran.isoformat(), to_date=IDAG.isoformat())
dagar = max((IDAG - fran).days, 1)
burn = (rs["total_expenses"] - rs["total_revenue"]) / dagar * 30.4

runway = cash / burn if burn > 0 else float("inf")

print(f"Kassa: {cash:,.0f} kr | Burn: {burn:,.0f}/mån | Runway: {runway:.1f} mån")

Balansräkningen svarar med asset_sections[].rows[] (account_number, amount) och resultaträkningen med total_revenue och total_expenses. Kolla API-dokumentationen för hela formen innan du bygger vidare. Slack-integration och trendjämförelse är ytterligare ett fyrtiotal rader.

En sak att vara medveten om: from_date och to_date måste ligga inom samma räkenskapsår. De första 90 dagarna på ett nytt år blir fönstret därför kortare, vilket koden ovan hanterar genom att räkna per dag. Vill du ha fulla 90 dagar över årsskiftet hämtar du resten ur föregående period och lägger ihop.

Nivå 3: Inbäddat i hela rapporteringen

För större team ligger runway sida vid sida med ARR, bruttomarginal, NRR och CAC payback i ett ledningssystem. Här är accounted en av flera datakällor och du har ett verktyg som Lightdash, Metabase eller en custom-byggd Next.js-app som drar ihop allt.

Skillnaden mot nivå 2 är inte teknisk komplexitet utan organisatorisk: nu kräver det att flera personer äger samma siffra och att den används i veckans ledningsmöte.

Vanliga fallgropar

Att räkna burn på utbetalningar i stället för periodiserade kostnader. En årlig SaaS-prenumeration som betalas i januari är en utgift i januari men en kostnad fördelad över hela året. Bokföringen vet det. Bankkontot vet det inte. Räkna burn från resultaträkningen, inte från bankkontot.

Att blanda in engångskostnader. En investerarrunda, en stor refund, ett kvartal med dubbel hyra. Det är värt att ha en variant av runway som exkluderar engångar och en som inkluderar. Visa båda.

Att inte uppdatera kontoplanen. Om du har börjat använda ett nytt likviditetskonto (säg 1950 för ett bankcertifikat) och inte lägger till det i formeln blir kassan underskattad. Granska kontolistan kvartalsvis.

Att larma för ofta. En 15-procents-tröskel på en vardag är vettig. En 5-procents-tröskel kommer ge dig 30 larm per kvartal och du kommer sluta läsa dem.

Varför direktläsning slår nattlig batch

Den vanligaste invändningen mot att läsa huvudboken direkt är "det är bättre att ha en data-pipeline som transformerar och cache:ar". För historisk analys, ja. För en metrik som behöver vara aktuell, nej. Tre skäl:

  1. Latens. En nattlig batch visar gårdagens läge på morgonens möte. Allt som bokförts sedan dess, en synkad bankhändelse eller en attesterad leverantörsfaktura, saknas i snapshoten men finns redan i huvudboken.
  2. Komplexitet. En direkt läsning kräver två API-anrop. En batch-pipeline kräver Airflow, dbt, ett warehouse, transformations och datakvalitetstester. Värt det för 50 dashboards. Inte värt det för 5.
  3. Förtroende. Folk litar på siffran de ser för att de vet att den kommer från källan, inte från ett mellanlager som någon glömde bort att fixa.

När du har 10+ rapportbehov och behöver historisk djupanalys, lägg på ett warehouse. Innan dess är det overkill.

Vad du börjar med

Nivå 1: Slack-bot i Make eller n8n. En eftermiddag. När den har kört i två veckor, gå till nivå 2 om du behöver larm. Nivå 3 är när organisationen är så stor att flera ska titta samtidigt.

Hela arkitekturen bygger på principen i Bokföringen som tillväxtmotor: huvudboken är ett byggblock, inte en slutdestination. Och det är fundamentet i Bokföring i AI-eran. Den här artikeln är ett av de enklaste sätten att se principen i praktiken.

Den dåligaste tiden att bygga det här är när du upptäcker att runway är kort. Den bästa är nu.

Vanliga frågor

Vad är runway?
Hur många månader företaget kan fortsätta drivas med befintlig kassa, givet nuvarande burn rate. Formel: kassa delat på snittet av rörelseförluster senaste 90 dagarna. En siffra du som grundare borde veta exakt utan att tänka.
Är inte det här vad ett ekonomisystem ska visa per default?
Egentligen ja. I praktiken kräver de flesta att du klickar in i en rapport, väljer datumintervall, exporterar till Excel. Att exponera runway som en endpoint på din huvudbok tar bort alla steg och gör det åtkomligt för Slack, dashboards och agenter.
Varför inte använda Stripe/Brex/whatever för det här?
Stripe visar intäkter, inte resultat. Det företagskort du använder visar utgifter, inte allokering. Bara huvudboken har varje rörelse kopplad till rätt konto med rätt periodisering. Runway räknat på fel underlag blir runway räknat fel.
Behöver jag programmera för att bygga det här?
Lite. Den enklaste versionen är två API-anrop som Make eller n8n kan göra utan kod. Den något mer avancerade versionen (med trendjämförelser och larm) är 80 rader Python och en cron. Inget av det är komplicerat om du har rätt API.
Hur ofta uppdateras siffran?
Sekunden en transaktion bokförs, rapporterna räknas om vid varje anrop. Bankkopplingen (PSD2) hämtar nya transaktioner automatiskt ungefär en gång per dygn, och du kan trigga en synk när som helst. Det som avgör är hur fort du bokför: en runway som bygger på obokade bankrader är gårdagens runway, vilket spelar roll mer än det låter.
Nästa steg

Klar att testa själv?

Open är gratis. Open source, ingen bindningstid. Importera SIE4 i tio minuter.