Rajapinta

Tili ja webhookit

Maksuton tili antaa kaksi asiaa, joita julkinen rajapinta ei voi: omat lukusi valmiiksi laskettuina ja viestin silloin kun jotain tapahtuu.

Oma dokumentti: /me

Asetussivulla annat marginaalisi ja siirtomaksusi ja luot avaimen. Sen jälkeen https://wattiplus.fi/api/v1/me?token=… palauttaa saman dokumentin kuin /homeassistant, mutta arvonlisäveron kanssa, jokainen total omilla kuluillasi, ja lisäksi lohkon account.notifications: jokainen päällä oleva sähköposti-ilmoitus samalla rajalla sensoriksi laskettuna. Avaimen voi antaa myös otsakkeena Authorization: Bearer ….

"account": {
  "email_verified": true,
  "notifications": {
    "low_price": {
      "label": "Hälytys halvasta sähköstä",
      "value": 5, "compares": "total",
      "below_now": false, "below_until": null,
      "next_below_at": "2026-09-07T00:00:00+00:00",
      "hours_below_today": 1, "hours_below_tomorrow": 3.5
    },
    "high_price": { "label": "Varoitus kalliista sähköstä", "value": 15, "above_now": false, "…": "…" },
    "window_reminder": { "label": "Muistutus juuri ennen halvinta jaksoa", "hours": 3, "active": false, "starts_in_minutes": 412 },
    "grid_alert": { "label": "Sähköpulavaroitus" }
  }
}

Home Assistantissa sama REST-sensori kuin julkisella osoitteella, avain otsakkeessa:

rest:
  - resource: https://wattiplus.fi/api/v1/me
    headers:
      Authorization: "Bearer AVAIMESI"
    scan_interval: 300
    sensor:
      - name: "Sähkön kokonaishinta nyt"
        value_template: "{{ value_json.total_now }}"
        unit_of_measurement: "snt/kWh"
    binary_sensor:
      - name: "Hinta alle oman rajan"
        value_template: "{{ value_json.account.notifications.low_price.below_now }}"

Dokumenttia ei välimuistiteta julkisesti. Avain on salasanaan verrattava; jos se vuotaa, luo uusi asetussivulta, jolloin vanha lakkaa toimimasta heti.

Webhook

Anna asetussivulla https-osoite, niin lähetämme siihen POST-pyynnön kolmessa tilanteessa. Osoitteen on oltava julkinen: Home Assistantissa se on Nabu Casan tai oman julkisen osoitteesi /api/webhook/<id>.

Tapahtumat
prices.published Heti kun huomisen (tai minkä tahansa päivän) hinnat ovat tallessa kokonaan. Rungossa päivän keskihinta, halvin ja kallein hetki sekä halvimmat 1, 3 ja 6 tunnin jaksot.
grid.alert Kun Fingridin sähköpulan tila muuttuu, myös takaisin normaaliksi. Rungossa taso 0:sta 3:een, otsikko ja selite.
webhook.test Asetussivun testinapista. Rungossa tämän päivän luvut.
POST https://oma-osoite/api/webhook/wattiplus
Content-Type: application/json
X-Wattiplus-Event: prices.published
X-Wattiplus-Signature: sha256=3f1c…

{
  "event": "prices.published",
  "sent_at": "2026-09-06T11:04:12+00:00",
  "data": {
    "date": "2026-09-07",
    "published": true,
    "unit": "c/kWh", "vat_included": true,
    "average": 6.41, "min": 1.26, "min_starts_at": "…", "max": 14.02, "max_starts_at": "…",
    "cheapest": {
      "1h": { "starts_at": "…", "ends_at": "…", "average": 1.26 },
      "3h": { "…": "…" }, "6h": { "…": "…" }
    },
    "url": "https://wattiplus.fi/huomenna"
  }
}

Home Assistant: webhook-liipaisin

automation:
  - alias: "Huomisen hinnat tulivat"
    trigger:
      - platform: webhook
        webhook_id: wattiplus
        allowed_methods: [POST]
        local_only: false
    condition:
      - condition: template
        value_template: "{{ trigger.json.event == 'prices.published' }}"
    action:
      - service: notify.mobile_app_puhelin
        data:
          message: >
            Huomenna keskihinta {{ trigger.json.data.average }} snt/kWh,
            halvin 3 h alkaa {{ as_timestamp(trigger.json.data.cheapest['3h'].starts_at) | timestamp_custom('%H:%M') }}.

Allekirjoituksen tarkistus

Otsake on sha256= ja HMAC-SHA256 pyynnön rungosta salaisuudellasi, joka näkyy asetussivulla. Home Assistantin oma webhook ei tarkista allekirjoitusta; pidä silloin webhook_id arvaamattomana. Node-RED:ssä tai omassa palvelussa:

const crypto = require("crypto");
const expected = "sha256=" + crypto
  .createHmac("sha256", SALAISUUS)
  .update(rawBody)
  .digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-wattiplus-signature"]));

Epäonnistunut toimitus yritetään uudelleen kolmesti kasvavin välein. Viimeisin tulos näkyy asetussivulla.

Tarvitset maksuttoman tilin

Tili tuo myös sähköposti-ilmoitukset huomisen hinnoista. Ei maksuja, ei mainoksia sähköpostiin.

Luo tili