"use strict";(globalThis.webpackChunkdocs_split_developer=globalThis.webpackChunkdocs_split_developer||[]).push([[7443],{3588:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>t,metadata:()=>s,toc:()=>o});const s=JSON.parse('{"id":"api-reference","title":"API Reference","description":"Documentation of the Tibber GraphQL API used by this integration.","source":"@site/docs/api-reference.md","sourceDirName":".","slug":"/api-reference","permalink":"/hass.tibber_prices/developer/api-reference","draft":false,"unlisted":false,"editUrl":"https://github.com/jpawlowski/hass.tibber_prices/tree/main/docs/developer/docs/api-reference.md","tags":[],"version":"current","lastUpdatedAt":1764985026000,"frontMatter":{"comments":false},"sidebar":"tutorialSidebar","previous":{"title":"Caching Strategy","permalink":"/hass.tibber_prices/developer/caching-strategy"},"next":{"title":"Development Setup","permalink":"/hass.tibber_prices/developer/setup"}}');var i=r(4848),l=r(8453);const t={comments:!1},d="API Reference",c={},o=[{value:"GraphQL Endpoint",id:"graphql-endpoint",level:2},{value:"Queries Used",id:"queries-used",level:2},{value:"User Data Query",id:"user-data-query",level:3},{value:"Price Data Query",id:"price-data-query",level:3},{value:"Rate Limits",id:"rate-limits",level:2},{value:"Response Format",id:"response-format",level:2},{value:"Price Node Structure",id:"price-node-structure",level:3},{value:"Currency Information",id:"currency-information",level:3},{value:"Error Handling",id:"error-handling",level:2},{value:"Common Error Responses",id:"common-error-responses",level:3},{value:"Data Transformation",id:"data-transformation",level:2}];function a(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"api-reference",children:"API Reference"})}),"\n",(0,i.jsx)(n.p,{children:"Documentation of the Tibber GraphQL API used by this integration."}),"\n",(0,i.jsx)(n.h2,{id:"graphql-endpoint",children:"GraphQL Endpoint"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"https://api.tibber.com/v1-beta/gql\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Authentication:"})," Bearer token in ",(0,i.jsx)(n.code,{children:"Authorization"})," header"]}),"\n",(0,i.jsx)(n.h2,{id:"queries-used",children:"Queries Used"}),"\n",(0,i.jsx)(n.h3,{id:"user-data-query",children:"User Data Query"}),"\n",(0,i.jsx)(n.p,{children:"Fetches home information and metadata:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-graphql",children:"query {\n viewer {\n homes {\n id\n appNickname\n address {\n address1\n postalCode\n city\n country\n }\n timeZone\n currentSubscription {\n priceInfo {\n current {\n currency\n }\n }\n }\n meteringPointData {\n consumptionEan\n gridAreaCode\n }\n }\n }\n}\n"})}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Cached for:"})," 24 hours"]}),"\n",(0,i.jsx)(n.h3,{id:"price-data-query",children:"Price Data Query"}),"\n",(0,i.jsx)(n.p,{children:"Fetches quarter-hourly prices:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-graphql",children:"query($homeId: ID!) {\n viewer {\n home(id: $homeId) {\n currentSubscription {\n priceInfo {\n range(resolution: QUARTER_HOURLY, first: 384) {\n nodes {\n total\n startsAt\n level\n }\n }\n }\n }\n }\n }\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Parameters:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"homeId"}),": Tibber home identifier"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"resolution"}),": Always ",(0,i.jsx)(n.code,{children:"QUARTER_HOURLY"})]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"first"}),": 384 intervals (4 days of data)"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Cached until:"})," Midnight local time"]}),"\n",(0,i.jsx)(n.h2,{id:"rate-limits",children:"Rate Limits"}),"\n",(0,i.jsx)(n.p,{children:"Tibber API rate limits (as of 2024):"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"5000 requests per hour"})," per token"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Burst limit:"})," 100 requests per minute"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Integration stays well below these limits:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Polls every 15 minutes = 96 requests/day"}),"\n",(0,i.jsx)(n.li,{children:"User data cached for 24h = 1 request/day"}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Total:"})," ~100 requests/day per home"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"response-format",children:"Response Format"}),"\n",(0,i.jsx)(n.h3,{id:"price-node-structure",children:"Price Node Structure"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "total": 0.2456,\n "startsAt": "2024-12-06T14:00:00.000+01:00",\n "level": "NORMAL"\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Fields:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"total"}),": Price including VAT and fees (currency's major unit, e.g., EUR)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"startsAt"}),": ISO 8601 timestamp with timezone"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"level"}),": Tibber's own classification (VERY_CHEAP, CHEAP, NORMAL, EXPENSIVE, VERY_EXPENSIVE)"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"currency-information",children:"Currency Information"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "currency": "EUR"\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Supported currencies:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"EUR"})," (Euro) - displayed as ct/kWh"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"NOK"})," (Norwegian Krone) - displayed as \xf8re/kWh"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"SEK"})," (Swedish Krona) - displayed as \xf6re/kWh"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"error-handling",children:"Error Handling"}),"\n",(0,i.jsx)(n.h3,{id:"common-error-responses",children:"Common Error Responses"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Invalid Token:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "errors": [{\n "message": "Unauthorized",\n "extensions": {\n "code": "UNAUTHENTICATED"\n }\n }]\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Rate Limit Exceeded:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "errors": [{\n "message": "Too Many Requests",\n "extensions": {\n "code": "RATE_LIMIT_EXCEEDED"\n }\n }]\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Home Not Found:"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "errors": [{\n "message": "Home not found",\n "extensions": {\n "code": "NOT_FOUND"\n }\n }]\n}\n'})}),"\n",(0,i.jsx)(n.p,{children:"Integration handles these with:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Exponential backoff retry (3 attempts)"}),"\n",(0,i.jsx)(n.li,{children:"ConfigEntryAuthFailed for auth errors"}),"\n",(0,i.jsx)(n.li,{children:"ConfigEntryNotReady for temporary failures"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"data-transformation",children:"Data Transformation"}),"\n",(0,i.jsx)(n.p,{children:"Raw API data is enriched with:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Trailing 24h average"})," - Calculated from previous intervals"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Leading 24h average"})," - Calculated from future intervals"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Price difference %"})," - Deviation from average"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Custom rating"})," - Based on user thresholds (different from Tibber's ",(0,i.jsx)(n.code,{children:"level"}),")"]}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["See ",(0,i.jsx)(n.code,{children:"utils/price.py"})," for enrichment logic."]}),"\n",(0,i.jsx)(n.hr,{}),"\n",(0,i.jsxs)(n.p,{children:["\ud83d\udca1 ",(0,i.jsx)(n.strong,{children:"External Resources:"})]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://developer.tibber.com/docs/overview",children:"Tibber API Documentation"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://developer.tibber.com/explorer",children:"GraphQL Explorer"})}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://developer.tibber.com/settings/access-token",children:"Get API Token"})}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}}}]);