JavaScript/Node-SDK exempel

Minimal client med fetch + TypeScript.

Uppdaterad 2026-05-19

Minimal client (TypeScript)

type LookupResult = {
  query: { type: string; postnr?: string; adress?: string };
  location: { ort?: string; latitude: number; longitude: number;
               kommun?: { kod: string; namn: string } };
  elomrade?: { code: string; name: string; source: string };
  natomrade?: { mga_code: string; svk_id?: string; name?: string };
  grid_owner?: { name: string; org_nr?: string; eic?: string; ediel_id?: string };
  energy_tax?: { year: number; rate_type: string; ore_per_kwh_excl_vat: number };
};

export class NatomradeClient {
  private base = "https://natomrade.airpipe.ai";
  private headers: HeadersInit;

  constructor(apiKey?: string) {
    this.headers = apiKey ? { "X-API-Key": apiKey } : {};
  }

  async lookupPostal(postnr: string): Promise<LookupResult> {
    const prefix = "X-API-Key" in this.headers ? "/api/v1" : "/web";
    const url = `${this.base}${prefix}/lookup/postal?code=${encodeURIComponent(postnr)}`;
    const r = await fetch(url, { headers: this.headers });
    if (!r.ok) throw new Error(`${r.status}: ${await r.text()}`);
    return r.json();
  }

  async spotPricesNow(): Promise<{ now: Array<{ area_code: string; sek_per_kwh: number; eur_per_kwh: number }> }> {
    const r = await fetch(`${this.base}/api/v1/prices/current`);
    return r.json();
  }

  async productionNow() {
    const r = await fetch(`${this.base}/api/v1/production/current`);
    return r.json();
  }
}

Användning (browser eller Node)

const client = new NatomradeClient("zk_din_nyckel");

const r = await client.lookupPostal("11151");
console.log(r.grid_owner.name);    // "Ellevio AB"
console.log(r.elomrade.code);      // "SE3"

const prices = await client.spotPricesNow();
prices.now.forEach(p => {
  console.log(`${p.area_code}: ${(p.sek_per_kwh * 100).toFixed(1)} öre/kWh`);
});

React-hook

import { useState, useEffect } from 'react';

export function useNatomradeSpotPrices() {
  const [prices, setPrices] = useState(null);
  useEffect(() => {
    fetch('https://natomrade.airpipe.ai/api/v1/prices/current')
      .then(r => r.json())
      .then(setPrices);
    const t = setInterval(() => {
      fetch('https://natomrade.airpipe.ai/api/v1/prices/current')
        .then(r => r.json()).then(setPrices);
    }, 5 * 60 * 1000); // refresh var 5 min
    return () => clearInterval(t);
  }, []);
  return prices;
}

Med rate-limit-hantering

async function callWithRetry(url, options, retries = 5) {
  for (let i = 0; i < retries; i++) {
    const r = await fetch(url, options);
    if (r.ok) return r.json();
    if (r.status === 429) {
      const d = await r.json();
      const wait = (d.throttle_minutes || 1) * 60 * 1000;
      await new Promise(s => setTimeout(s, wait));
      continue;
    }
    if (r.status >= 500) {
      await new Promise(s => setTimeout(s, Math.min(2 ** i * 1000, 30000)));
      continue;
    }
    throw new Error(`${r.status}`);
  }
  throw new Error('Max retries exceeded');
}