Hitta Bolån API – Dokumentation

Detta API används för att beräkna och presentera bolåneerbjudanden, samt exponera marknadsräntor (list- och snitträntor) per bindningstid. Dokumentet beskriver autentisering, endpoints, request/response-format samt centrala affärsregler (inklusive rule_deviation).

Base URL: https://api.hittabolan.se
Auth: x-api-key
Format: JSON

Översikt

Alla API-svar returneras som JSON. API:t är skyddat med API-nyckel via HTTP-header. Rekommenderad användning är att klienten hämtar marknadsräntor (rates-endpoints) separat från individuella beräkningar (calculate).

Observera: Endpoints under /api kräver giltig x-api-key.

Autentisering

Ange API-nyckeln i headern x-api-key. Om nyckeln saknas eller är felaktig returneras 401 Unauthorized.

HEADER x-api-key: <DIN_NYCKEL>
API-nyckel måste skickas i varje anrop till /data/*.

Exempel (curl)

curl -X GET "/data/rates/list" \
  -H "x-api-key: DIN_API_KEY"

Vanliga statuskoder

200OK
400Felaktig input (t.ex. calculate)
401Unauthorized (saknad/fel API-key)
500Internt fel

Felhantering

API:t returnerar fel som JSON med error-fält (och ibland extra detaljer). Klienten bör hantera 4xx som användar-/inputfel och 5xx som tillfälliga serverfel.

ERROR Exempel: 401 / 400 / 500
Standardiserad felrespons.

Felrespons (exempel)

{
  "error": "Unauthorized"
}

Rekommenderad klientlogik

401 Verifiera att x-api-key skickas korrekt.
400 Visa valideringsfel. (Ex: saknade fält eller ogiltiga värden.)
500 Visa generellt fel och tillåt “försök igen”. Logga request-id om tillgängligt.

GET /data/form/questions

Returnerar konfigurerade formulärfrågor (t.ex. rabatter) som används för att bygga ett dynamiskt UI. Användarens val skickas vidare till /data/calculate via fältet selected_discounts.

GET /data/form/questions
Formulärmetadata (frågor, typer, grupper, sortering, options).

Exempel (curl)

curl -X GET "/data/form/questions" \
  -H "x-api-key: DIN_API_KEY"

Response

{
  "questions": [
    {
      "id": 1,
      "key": "IKEA_Family",
      "label": "Jag är IKEA Family medlem.",
      "tooltip": "Som IKEA Family medlem får du extra bolånerabatt hos Ikano Bank.",
      "type": "checkbox",
      "group": "discounts",
      "options": null,
      "active": true,
      "sortOrder": 3
    },
    {
      "id": 2,
      "key": "TCO_Saco_HSB_SPP",
      "label": "Välj ett alternativ",
      "tooltip": "Vissa organisationer och samarbeten kan ge dig extra bolånerabatt.",
      "type": "select",
      "group": "discounts",
      "options": [
        { "value": "", "label": "Inget av alternativet gälle" },
        { "value": "TCO", "label": "Mitt fackförbund är anslutet till TCO" },
        { "value": "Saco", "label": "Mitt fackförbund är anslutet till Saco" },
        { "value": "HSB", "label": "Jag bosparar hos HSB" },
        { "value": "SPP", "label": "Jag är kund/anställd hos SPP" }
      ],
      "active": true,
      "sortOrder": 7
    },
    {
      "id": 3,
      "key": "ICA_Stammis",
      "label": "Hur mycket handlar du för på ICA varje månad?",
      "tooltip": "Du får extra bolånerabatt hos ICA Banken baserat på hur mycket du spenderar per månad som ICA Stammis.",
      "type": "select",
      "group": "discounts",
      "options": [
        { "value": 0, "label": "Jag är inte ICA Stammis medlem" },
        { "value": 500, "label": "1 – 999 kr" },
        { "value": 1500, "label": "1 000 – 1 999 kr" },
        { "value": 3000, "label": "2 000 – 3 999 kr" },
        { "value": 5000, "label": "4 000 – 5 999 kr" },
        { "value": 7000, "label": "6 000 – 7 999 kr" },
        { "value": 8500, "label": "Mer än 8 000 kr" }
      ],
      "active": true,
      "sortOrder": 5
    }
  ]
}
questions array Lista med frågeobjekt. Rendera endast active=true.
questions[].key string Unik nyckel som identifierar rabatten.
questions[].label string Text som visas i UI.
questions[].tooltip string | null Förklarande tooltip-text (valfri).
questions[].type string checkbox, select, radio, number.
questions[].options array | null Alternativ för select/radio. Varje alternativ är ett objekt: { value, label }.
questions[].group string UI-gruppering, t.ex. discounts.
questions[].sortOrder number Sorteringsordning inom grupp.
Rendering (rekommenderat)
  • Filtrera: questions.filter(q => q.active)
  • Sortera: sort((a,b) => a.sortOrder - b.sortOrder)
  • Gruppera på group
  • Bygg UI baserat på type: checkbox, select, radio
  • Samla alla val i selected_discounts
Payload till /data/calculate
{
  "selected_discounts": [
    { "key": "IKEA_Family" },
    { "key": "TCO" },
    { "key": "ICA_Stammis", "value": 5000 }
  ]
}
Viktigt Alla rabatter skickas via selected_discounts. Om en rabatt kräver ett värde (t.ex. ICA), ska detta skickas tillsammans med dess key.

Backend normaliserar detta internt för beräkning.

Discount reference (selected_discounts)

selected_discounts används i POST /data/calculate för att aktivera rabatter. Varje rabatt identifieras av ett stabilt key.

API-kontrakt: Dessa key-värden är stabila och kan användas direkt mot /data/calculate även om klienten inte använder /data/form/questions.
INPUT selected_discounts
Lista med aktiva rabatter som påverkar ränteberäkningen.

Format

{
  "selected_discounts": [
    { "key": "IKEA_Family" },
    { "key": "TCO" },
    { "key": "ICA_Stammis", "value": 5000 }
  ]
}

Tillgängliga discounts

key Kräver value Typ Beskrivning
IKEA_Family Nej boolean IKEA Family-medlemskap (Ikano Bank).
TCO Nej boolean Fackförbund anslutet till TCO.
Saco Nej boolean Fackförbund anslutet till Saco.
HSB Nej boolean Bosparande eller medlemskap i HSB.
SPP Nej boolean Kund eller anställd hos SPP.
ICA_Stammis Ja number Månatlig handel hos ICA (kr/mån).

Regler

  • Skicka endast rabatter som användaren uppfyller.
  • Boolean-rabatter skickas utan value.
  • Rabatter med nivåer kräver value.
  • Okända key-värden ignoreras av backend.

Koppling till /data/form/questions

/data/form/questions returnerar samma key-värden tillsammans med UI-metadata (label, tooltip, sortOrder).

Backend matchar alltid rabatter baserat på key – inte label.

POST /data/calculate

Beräknar fram räntan man kan få för en specifik förfrågan baserat på lånebeloppets storlek, belåningsgrad, bindningstid, övriga rabatter och bankregler. Responsen sorterar alltid lägsta ränta överst och banker med rule_deviation längst ner.

POST /data/calculate
Personlig jämförelse: räntor, kostnader, amortering, ev. besparing samt rule_deviation.

Request

{
  "loan_amount": 2700000,
  "property_value": 4500000,
  "property_type": "Bostadsratt",
  "term": "ThreeMonth",
  "current_rate": 0,
  "selected_discounts": ["IKEA_Family"],
  "energy_class": "Vet ej"
}
loan_amount number Ja Lånebelopp i kronor.
property_value number Ja Bostadens uppskattade marknadsvärde.
property_type string Ja Bostadstyp.
term string Ja Bindningstid.
current_rate number Villkor Nuvarande bolåneränta"
selected_discounts string[] Nej Valda rabatter
energy_class string Nej Bostadens energiklass

Exempel (curl)

curl -X POST "/data/calculate" \
  -H "Content-Type: application/json" \
  -H "x-api-key: DIN_API_KEY" \
  -d '{
    "loan_amount": 2700000,
    "property_value": 4500000,
    "property_type": "Bostadsratt",
    "term": "ThreeMonth",
    "current_rate": 0,
    "selected_discounts": "selected_discounts": [
      { "key": "IKEA_Family" },
      { "key": "TCO" },
      { "key": "ICA_Stammis", "value": 5000 }
    ],
    "energy_class": "Vet ej"
  }'

Response (exempel)

{
  "results": [
    {
      "bankId": 1,
      "bankName": "Exempelbank",
      "logo": "...",
      "utm_link_move": "https://...",

      "fixed_rate": 3.95,
      "average_rate": 3.80,
      "personal_rate": 3.65,
      "total_discount": -0.30,
      "effective_rate": 3.72,

      "monthly_interest_cost": 8200,
      "monthly_amortization": 4500,
      "amortization_percentage": 1,

      "total_monthly_cost_before_tax": 12700,
      "monthly_tax_deduction": 2050,
      "total_monthly_cost_after_tax_deduction": 10650,

      "loan_amount": 2700000,
      "property_value": 4500000,
      "ltv": 60,
      "down_payment": 1800000,

      "current_rate": null,
      "monthly_savings_before_tax": null,
      "monthly_savings_after_tax": null,

      "green_mortgage": false,
      "rule_deviation": null,

      "open_price_model": true,
      "agreement": "..."
    }
  ]
}

Fält (urval)

personal_ratePersonlig ränta efter tillämpliga rabatter (om möjligt). number|null
average_rateBankens snittränta (kan vara fallback). number|null
fixed_rateBankens listränta / grundränta. number|null
rule_deviationMeddelande-lista om banken inte kan ge korrekt erbjudande (visas utan räntedata). string[]|null
total_monthly_cost_before_taxTotal månadskostnad före skatteavdrag. number|null

GET /data/rates/list

Returnerar listräntor (Fixed) per bank, grupperat per bindningstid (term). Banker sorteras med lägsta listränta först inom varje term.

GET /data/rates/list
Listränta per bank och term. (Stabelo exkluderas från Fixed enligt affärsregel.)

Exempel (curl)

curl -X GET "/data/rates/list" \
  -H "x-api-key: DIN_API_KEY"

Response

{
  "terms": {
    "ThreeMonth": [
      { "bankId": 2, "bankName": "Bank A", "fixed_rate": 3.95, utm_link_move: "https://LINK/flytta-bolan"  },
      { "bankId": 7, "bankName": "Bank B", "fixed_rate": 4.05, utm_link_move: "https://LINK/flytta-bolan"  }
    ],
    "OneYear": [
      { "bankId": 7, "bankName": "Bank B", "fixed_rate": 3.85, utm_link_move: "https://LINK/flytta-bolan"  }
    ]
  }
}
terms object Nyckel per term (bindningstid).
terms[].bankId number Unikt bank-ID.
terms[].bankName string Bankens namn.
terms[].fixed_rate number Listränta (Fixed) i procent. Sorterad lägst först per term.
terms[].utm_link_move String En spårbar länk till bankens sida för att flytta bolån.
terms[].last_updated Date/String Senast ändrade listränta hos banken.

GET /data/rates/average

Returnerar snittränta per term (aggregerat över banker som har giltig Average-ränta för termen). Detta är en marknadsindikator – ingen banklista i denna endpoint.

GET /data/rates/average
Snittränta per bindningstid (term), baserat på bankers Average-rader.

Exempel (curl)

curl -X GET "/data/rates/average" \
  -H "x-api-key: DIN_API_KEY"

Response

{
  "terms": {
    "ThreeMonth": { "average_rate": 2.65, "banks": 13 },
    "OneYear":    { "average_rate": 2.80, "banks": 13 },
    "FiveYear":   { "average_rate": 2.20, "banks": 13 }
  }
}
terms object Nyckel per term.
terms[].average_rate number Snittränta (Average) i procent, avrundad till två decimaler.
terms[].banks number Antal banker som ingår i snittet för termen.

GET /data/rates/average

Returnerar snittränta (Average) per bank och term, grupperat per bindningstid. Banker sorteras med lägsta snittränta först inom varje term.

GET /data/rates/average
Snittränta per bank och term (Average). Används för per-bank tabeller/grafer.

Exempel (curl)

curl -X GET "/data/rates/average" \
  -H "x-api-key: DIN_API_KEY"

Response

{
  "terms": {
    "ThreeMonth": [
      { "bankId": 2, "bankName": "Bank A", "average_rate": 2.35, "month" : "Maj 2026", utm_link_move: "https://LINK/flytta-bolan" },
      { "bankId": 7, "bankName": "Bank B", "average_rate": 2.55, "month" : "Maj 2026", utm_link_move: "https://LINK/flytta-bolan" }
    ],
    "OneYear": [
      { "bankId": 7, "bankName": "Bank B", "average_rate": 2.75, "month" : "Maj 2026", utm_link_move: "https://LINK/flytta-bolan" }
    ]
  }
}
terms object Nyckel per term (bindningstid).
terms[].bankId number Unikt bank-ID.
terms[].bankName string Bankens namn.
terms[].average_rate number Bankens snittränta (Average) i procent.
terms[].utm_link_move string En spårbar länk till bankens sida för att flytta bolån.
terms[].month string Senaste uppdaterad ränta (månad).

rule_deviation

rule_deviation används när en bank inte kan ge ett korrekt prissatt erbjudande för indata (t.ex. otillåten bostadstyp, belåningsgrad utanför regelverk, eller bank kräver manuell kontakt). När rule_deviation finns ska klienten visa meddelandet och inte visa räntedata för banken.

Frontend-rekommendation: Om rule_deviation är en array med minst ett element, visa endast första meddelandet som och dölja räntor/kostnader.

Sortering

Calculate-resultat sorteras av API:t: banker utan rule_deviation först, sedan lägsta ränta (personal → average → fixed). Banker med rule_deviation returneras sist.

Rates-endpoints: inom varje term sorteras banklistor stigande på respektive ränta (lägst först).

Affärsregler (urval)

Nedan regler påverkar datat:

Fritidshus Vissa banker kan exkludera Fritidshus via regler och då sätts rule_deviation i calculate.
Rabatter Rabatter drivs via selected_discounts, energy_class (green mortgage).
Amortering Baseras på belåningsgrad (LTV): >70% = 2%, >50% = 1%, annars 0% (i beräkningslogik).