API Referanse
REST API for bygningsenergisimulering med Bemify
Bemify Simulation API lar deg laste opp en SIMIEN Pro-modell (.sxi) og få tilbake energiresultater, energimerke (A–G) og TEK17-samsvarskontroll. API-et bruker en asynkron jobbkø — du sender inn en simulering og poller for resultater.
Base URL: https://api.bemify.no
Hurtigstart
# Kjør en simulering med klimadata fra server
curl -X POST https://api.bemify.no/simulate \
-H "Authorization: Bearer bmf_YOUR_TOKEN" \
-F "model=@building.sxi" \
-F "klimasted=Oslo"
# Poll for resultater
curl https://api.bemify.no/job/job_123456_1 \
-H "Authorization: Bearer bmf_YOUR_TOKEN"Autentisering
Alle simuleringsendepunkter krever en Bearer-token i Authorization-headeren:
Authorization: Bearer bmf_YOUR_TOKENKontakt erlend@bemify.no for API-tilgang.
Endepunkter
POST /simulate
Start en ny simulering. Returnerer en jobb-ID for polling.
Content-Type: multipart/form-data
| Parameter | Type | Påkrevd | Beskrivelse |
|---|---|---|---|
model | fil | Ja | SIMIEN Pro prosjektfil (.sxi) |
climate | fil | Betinget | EnergyPlus værfil (.epw). Gjensidig eksklusiv med klimasted. Ikke tillatt for tek17 og energimerke. |
klimasted | streng | Betinget | Kommunenavn (f.eks. Oslo). Alternativ til climate. Ikke tillatt for tek17. |
simuleringstype | streng | Nei | aarssimulering (standard), energimerke, eller tek17 |
Regler for klimadata
- Oppgi enten
klimastedellerclimate-fil, ikke begge - For
tek17: Klimadata hentes alltid automatisk (TEK17-referanseklima). Oppgi ikkeklimastedellerclimate— forespørselen avvises med 400. - For
energimerke: Kunklimastedgodtas — EPW-filer avvises med 400. Energimerking krever en standard norsk klimasone for klimakorreksjonsfaktoren. - Bruk
GET /klimastederfor å se gyldige kommunenavn.
Respons (202):
{
"jobId": "job_1712832645123_1",
"position": 1,
"message": "Simulering lagt i kø (posisjon 1). Poll /job/job_1712832645123_1 for status."
}GET /job/:jobId
Sjekk jobbstatus og hent resultater. Krever autentisering. Brukere kan kun se egne jobber.
Statuser: queued | running | completed | error
Respons ved fullført (200):
{
"jobId": "job_1712832645123_1",
"status": "completed",
"queuedAt": "2026-04-11T10:30:45.123Z",
"startedAt": "2026-04-11T10:30:50.456Z",
"completedAt": "2026-04-11T10:32:15.789Z",
"result": {
"beregningspunkter": { "netto": { ... }, "brutto": { ... }, "tilfort": { ... }, "levert": { ... } },
"zones": [{ "id": "sone-1", "navn": "Sone 1", "area": 150.0 }],
"energimerke": { ... },
"tek17": { ... }
}
}Respons ved feil (200):
{
"jobId": "job_1712832645123_1",
"status": "error",
"completedAt": "2026-04-11T10:32:15.789Z",
"error": "Feilmelding"
}Merk: Resultater beholdes i opptil 30 minutter etter fullføring, men kan slettes tidligere dersom kapasitetsgrensen nås.
GET /klimasteder
Liste over alle tilgjengelige klimasteder. Ingen autentisering påkrevd.
{
"locations": ["TEK17 Referanseklima", "Oslo", "Bergen", "Trondheim", ...],
"count": 51
}GET /health
Helsesjekk for serveren. Ingen autentisering påkrevd.
{
"status": "ok",
"timestamp": "2026-04-11T10:30:45.123Z",
"queue": { "length": 0, "processing": false }
}GET /queue
Køstatus. Ingen autentisering påkrevd.
{ "queueLength": 0, "isProcessing": false }Simuleringstyper
| Verdi | Beskrivelse | Klimadata | Ekstra resultatfelt |
|---|---|---|---|
aarssimulering | Helårssimulering (standard) | klimasted eller EPW | energimerke |
energimerke | Energimerking | Kun klimasted | energimerke |
tek17 | TEK17-samsvarskontroll | Automatisk (referanseklima) | energimerke, tek17 |
Resultatformat
Beregningspunkter (result.beregningspunkter)
Resultatene grupperes i fire beregningspunkter iht. NS 3031:
| Punkt | Nøkkel | Beskrivelse |
|---|---|---|
| A | netto | Netto energibehov (bygningens behov) |
| B | brutto | Brutto energibehov (inkl. systemtap) |
| C | tilfort | Tilført energi (fra energikilder) |
| D | levert | Levert energi (fra nett/energibærere) |
Hvert beregningspunkt inneholder energyResults med årstotaler per energipost (romoppvarming, ventilasjonsvarme, varmtvann, kjøling, belysning, utstyr m.m.).
Energimerke (result.energimerke)
Beregnes automatisk når prosjektet har gyldig kommune og bygningskategori.
{
"energimerke": "B",
"totalArea": 250.0,
"korreksjonsfaktor": 1.05,
"klimakorrigertVektetSpesifikk": 92.3,
"sumVektetSpesifikk": 96.9,
"sumLevertEnergi": 24075,
"sumSpesifikk": 96.3,
"vektetKlimaavhengig": 42.1,
"vektetIkkeKlimaavhengig": 54.8,
"items": [
{
"kilde": "1 Levert elektrisitet",
"levertEnergi_kWh": 21500,
"spesifikk_kWhm2": 86.0,
"vektingsfaktor": 1.0,
"vektetSpesifikk_kWhm2": 86.0
}
]
}| Felt | Enhet | Beskrivelse |
|---|---|---|
energimerke | A–G | Energikarakter |
klimakorrigertVektetSpesifikk | kWh/(m²·år) | Klimakorrigert vektet spesifikk levert energi (bestemmer karakteren) |
sumVektetSpesifikk | kWh/(m²·år) | Vektet spesifikk levert energi (før klimakorreksjon) |
sumLevertEnergi | kWh/år | Total levert energi |
korreksjonsfaktor | – | Klimakorreksjonsfaktor for kommune/bygningstype |
items | array | Fordeling per energibærer |
TEK17-validering (result.tek17)
Kun tilgjengelig når simuleringstype=tek17.
{
"erSamsvarsende": true,
"energiramme": {
"poster": [
{ "post": "1a", "beskrivelse": "Romoppvarming", "spesifikk_kWhm2": 12.3 }
],
"totalBeregnet": 105.2,
"forskriftskrav": 115.0,
"status": "oppfylt",
"bygningskategori": "Kontorbygning"
},
"minstekrav": {
"rader": [
{ "bygningsdel": "U-verdi yttervegger", "faktiskVerdi": 0.18, "kravVerdi": 0.22, "status": "oppfylt" }
],
"samletStatus": "oppfylt"
},
"luftmengder": {
"rader": [
{ "beskrivelse": "Spesifikk vifteeffekt (SFP)", "faktiskVerdi": 1.50, "kravVerdi": 2.00, "status": "oppfylt" }
],
"samletStatus": "oppfylt"
},
"energiforsyning": {
"brukerFossilBrensel": false,
"fossilKilder": [],
"punkt2Gjelder": true,
"harSentralVarmesentral": true,
"sentralAndelProsent": 85.2,
"status": "oppfylt"
},
"oppsummering": {
"antallOppfylt": 4,
"antallIkkeOppfylt": 0,
"antallIkkeRelevant": 0
}
}Mulige status-verdier: "oppfylt", "ikke_oppfylt", "ikke_relevant".
Feilkoder
| Kode | Betydning | Eksempel |
|---|---|---|
| 400 | Ugyldig forespørsel | Manglende modellfil, ugyldig simuleringstype, både klimasted og climate oppgitt |
| 401 | Ikke autorisert | Manglende Authorization-header |
| 403 | Forbudt | Ugyldig eller deaktivert API-nøkkel |
| 404 | Ikke funnet | Jobb ikke funnet eller utløpt |
| 413 | For stor | Fil overstiger 10 MB-grensen |
| 429 | For mange forespørsler | Global eller per-nøkkel rate-grense nådd, eller for mange aktive jobber |
| 502 | Bad gateway | Kunne ikke hente klimadata fra oppstrømstjeneste |
| 503 | Kø full | Maks 20 samtidige jobber |
Begrensninger
| Grense | Verdi |
|---|---|
| Global rate-grense | 30 forespørsler per minutt |
Per-nøkkel POST /simulate | 6 forespørsler per minutt |
Per-nøkkel GET /job/:jobId | 120 forespørsler per minutt |
| Maks aktive jobber per nøkkel | 3 |
| Maks filstørrelse | 10 MB per fil |
| Maks kødybde | 20 jobber |
| Simuleringstimeout | 10 minutter |
| Resultat-TTL | 30 minutter |
Eksempler
curl
# Standard simulering med kommuneklima
curl -X POST https://api.bemify.no/simulate \
-H "Authorization: Bearer bmf_YOUR_TOKEN" \
-F "model=@building.sxi" \
-F "klimasted=Oslo"
# Energimerkesimulering
curl -X POST https://api.bemify.no/simulate \
-H "Authorization: Bearer bmf_YOUR_TOKEN" \
-F "model=@building.sxi" \
-F "klimasted=Oslo" \
-F "simuleringstype=energimerke"
# TEK17-samsvarskontroll (klimadata hentes automatisk)
curl -X POST https://api.bemify.no/simulate \
-H "Authorization: Bearer bmf_YOUR_TOKEN" \
-F "model=@building.sxi" \
-F "simuleringstype=tek17"
# Simulering med egen EPW-fil
curl -X POST https://api.bemify.no/simulate \
-H "Authorization: Bearer bmf_YOUR_TOKEN" \
-F "model=@building.sxi" \
-F "climate=@oslo.epw"
# Poll for resultater
curl https://api.bemify.no/job/job_123456_1 \
-H "Authorization: Bearer bmf_YOUR_TOKEN"Python
import requests
import time
API_URL = "https://api.bemify.no"
TOKEN = "bmf_YOUR_TOKEN"
headers = {"Authorization": f"Bearer {TOKEN}"}
# Start simulering
with open("building.sxi", "rb") as model:
resp = requests.post(
f"{API_URL}/simulate",
headers=headers,
files={"model": model},
data={"klimasted": "Oslo", "simuleringstype": "energimerke"},
)
job_id = resp.json()["jobId"]
print(f"Jobb startet: {job_id}")
# Poll for resultater
while True:
status = requests.get(f"{API_URL}/job/{job_id}", headers=headers).json()
if status["status"] in ("completed", "error"):
break
print(f"Status: {status['status']}...")
time.sleep(2)
if status["status"] == "completed":
result = status["result"]
# Energimerke
if "energimerke" in result:
em = result["energimerke"]
print(f"Energimerke: {em['energimerke']}")
print(f"Vektet spesifikk: {em['klimakorrigertVektetSpesifikk']:.1f} kWh/(m²·år)")
# TEK17 (kun for simuleringstype=tek17)
if "tek17" in result:
tek = result["tek17"]
print(f"TEK17-samsvar: {tek['erSamsvarsende']}")
else:
print(f"Feil: {status['error']}")