{
  "openapi": "3.1.0",
  "info": {
    "title": "elpriser.org API",
    "version": "1.0",
    "summary": "Live Danish electricity prices, schedules, forecasts and Tibber-compatible JSON.",
    "description": "Free, public API serving aktuelle elpriser (current electricity prices) for the Danish\nprice zones DK1 (Vestdanmark) and DK2 (Østdanmark). Data is sourced daily from Energi\nData Service (Energinet) and updated when Nord Pool publishes next-day prices.\n\n**No key, no rate limit, full CORS** (`Access-Control-Allow-Origin: *`). Responses are\nedge-cached at Cloudflare for 1–5 min so calling /api/now every minute from a Shelly\nor Home Assistant is free and fine.\n\nDesigned to be consumed by:\n- Browser apps (CORS-friendly JSON, no preflight needed for simple GETs)\n- Home automation (Shelly Plus/Pro scripts, Home Assistant REST sensors)\n- LLM agents (Tibber-compatible `/api/shelly/tariff` matches the schema Tibber publishes)\n- Smart-home aggregators (machine-readable spec at `/api/openapi.json`)",
    "contact": {
      "url": "https://elpriser.org/api"
    },
    "license": {
      "name": "Free for any use",
      "url": "https://elpriser.org/"
    }
  },
  "servers": [
    {
      "url": "https://elpriser.org",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "API documentation (Danish)",
    "url": "https://elpriser.org/api"
  },
  "paths": {
    "/api/now": {
      "get": {
        "operationId": "getCurrentPrice",
        "summary": "Current electricity price + on/off for a schedule",
        "description": "Returns the price for the current Danish-local hour and a boolean `on` indicating whether the chosen schedule strategy says the device should be ON right now.",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DK1",
                "DK2"
              ],
              "default": "DK1"
            },
            "description": "Danish price zone — DK1 (Vestdanmark) or DK2 (Østdanmark)."
          },
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "spot_ex",
                "spot_inkl",
                "inkl_alt",
                "inkl_alt_minus",
                "net_inkl_alt",
                "net_inkl_tarif"
              ],
              "default": "inkl_alt"
            },
            "description": "Price view: raw spot, spot incl. moms, or total incl. all tariffs."
          },
          {
            "name": "gln",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Net company GLN (13 digits). Required when mode is `net_inkl_alt` or `net_inkl_tarif`."
          },
          {
            "name": "strategy",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "cheapest_n",
                "cheapest_pct",
                "avoid_expensive_n",
                "avoid_expensive_pct",
                "avoid_peak",
                "night_cheap",
                "smart"
              ],
              "default": "cheapest_n"
            },
            "description": "Schedule strategy. See /automation for descriptions."
          },
          {
            "name": "hours",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 23,
              "default": 6
            },
            "description": "For strategies that take an hour count."
          },
          {
            "name": "pct",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "description": "For percentage-based strategies."
          },
          {
            "name": "max_off",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 12
            },
            "description": "For `strategy=smart`: max consecutive OFF hours."
          }
        ],
        "responses": {
          "200": {
            "description": "Current hour status.",
            "content": {
              "application/json": {
                "example": {
                  "on": true,
                  "price": 1.23,
                  "hour": 14,
                  "area": "DK1",
                  "mode": "inkl_alt",
                  "strategy": "cheapest_n"
                }
              }
            }
          }
        }
      }
    },
    "/api/prices": {
      "get": {
        "operationId": "getDailyPrices",
        "summary": "24 hourly prices for one date",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DK1",
                "DK2"
              ],
              "default": "DK1"
            },
            "description": "Danish price zone — DK1 (Vestdanmark) or DK2 (Østdanmark)."
          },
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "spot_ex",
                "spot_inkl",
                "inkl_alt",
                "inkl_alt_minus",
                "net_inkl_alt",
                "net_inkl_tarif"
              ],
              "default": "inkl_alt"
            },
            "description": "Price view: raw spot, spot incl. moms, or total incl. all tariffs."
          },
          {
            "name": "gln",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Net company GLN (13 digits). Required when mode is `net_inkl_alt` or `net_inkl_tarif`."
          },
          {
            "name": "date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD. Defaults to today (DK local)."
          }
        ],
        "responses": {
          "200": {
            "description": "24 hourly prices.",
            "content": {
              "application/json": {
                "example": {
                  "area": "DK1",
                  "mode": "inkl_alt",
                  "date": "2026-05-15",
                  "unit": "DKK/kWh",
                  "prices": [
                    {
                      "hour": 0,
                      "price": 0.84
                    },
                    {
                      "hour": 1,
                      "price": 0.79
                    }
                  ],
                  "current_hour": 14,
                  "current_price": 1.23
                }
              }
            }
          }
        }
      }
    },
    "/api/schedule": {
      "get": {
        "operationId": "getSchedule",
        "summary": "Full 24h on/off schedule for a strategy",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DK1",
                "DK2"
              ],
              "default": "DK1"
            },
            "description": "Danish price zone — DK1 (Vestdanmark) or DK2 (Østdanmark)."
          },
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "spot_ex",
                "spot_inkl",
                "inkl_alt",
                "inkl_alt_minus",
                "net_inkl_alt",
                "net_inkl_tarif"
              ],
              "default": "inkl_alt"
            },
            "description": "Price view: raw spot, spot incl. moms, or total incl. all tariffs."
          },
          {
            "name": "gln",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Net company GLN (13 digits). Required when mode is `net_inkl_alt` or `net_inkl_tarif`."
          },
          {
            "name": "strategy",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "cheapest_n",
                "cheapest_pct",
                "avoid_expensive_n",
                "avoid_expensive_pct",
                "avoid_peak",
                "night_cheap",
                "smart"
              ],
              "default": "cheapest_n"
            },
            "description": "Schedule strategy. See /automation for descriptions."
          },
          {
            "name": "hours",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 23,
              "default": 6
            },
            "description": "For strategies that take an hour count."
          },
          {
            "name": "pct",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "description": "For percentage-based strategies."
          },
          {
            "name": "max_off",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 12
            },
            "description": "For `strategy=smart`: max consecutive OFF hours."
          },
          {
            "name": "date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD. Defaults to today (DK local)."
          }
        ],
        "responses": {
          "200": {
            "description": "Hour-by-hour schedule.",
            "content": {
              "application/json": {
                "example": {
                  "area": "DK1",
                  "mode": "inkl_alt",
                  "strategy": "cheapest_n",
                  "param": 6,
                  "date": "2026-05-15",
                  "on_now": true,
                  "schedule": [
                    {
                      "hour": 0,
                      "price": 0.84,
                      "on": true
                    },
                    {
                      "hour": 1,
                      "price": 0.79,
                      "on": true
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/forecast": {
      "get": {
        "operationId": "getForecast",
        "summary": "7-day electricity price forecast",
        "description": "Combines actual day-ahead prices for today/tomorrow with a weather-corrected forecast for days 3-7 using EDS production forecasts + Open-Meteo wind/solar.",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DK1",
                "DK2"
              ],
              "default": "DK1"
            },
            "description": "Danish price zone — DK1 (Vestdanmark) or DK2 (Østdanmark)."
          },
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "spot_ex",
                "spot_inkl",
                "inkl_alt",
                "inkl_alt_minus",
                "net_inkl_alt",
                "net_inkl_tarif"
              ],
              "default": "inkl_alt"
            },
            "description": "Price view: raw spot, spot incl. moms, or total incl. all tariffs."
          }
        ],
        "responses": {
          "200": {
            "description": "7 days × 24 hours of forecasted prices.",
            "content": {
              "application/json": {
                "example": {
                  "area": "DK1",
                  "mode": "inkl_alt",
                  "generated": "2026-05-15T13:00:00Z",
                  "days": [
                    {
                      "date": "2026-05-15",
                      "type": "actual",
                      "weekday": 5,
                      "prices": [
                        {
                          "hour": 0,
                          "price": 0.84
                        }
                      ]
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/api/shelly/tariff": {
      "get": {
        "operationId": "getShellyTariff",
        "summary": "Tibber-compatible JSON for Shelly/HA",
        "description": "Returns today + tomorrow prices in the exact GraphQL response shape Tibber publishes, so any Tibber-aware integration works as a drop-in.",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DK1",
                "DK2"
              ],
              "default": "DK1"
            },
            "description": "Danish price zone — DK1 (Vestdanmark) or DK2 (Østdanmark)."
          },
          {
            "name": "mode",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "spot_ex",
                "spot_inkl",
                "inkl_alt",
                "inkl_alt_minus",
                "net_inkl_alt",
                "net_inkl_tarif"
              ],
              "default": "inkl_alt"
            },
            "description": "Price view: raw spot, spot incl. moms, or total incl. all tariffs."
          },
          {
            "name": "gln",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Net company GLN (13 digits). Required when mode is `net_inkl_alt` or `net_inkl_tarif`."
          }
        ],
        "responses": {
          "200": {
            "description": "Tibber-compatible response."
          }
        }
      }
    },
    "/api/raw/prices": {
      "get": {
        "operationId": "getRawPrices",
        "summary": "Raw DayAheadPrices records (passthrough)",
        "description": "CORS-proxied passthrough to Energi Data Service `DayAheadPrices`. Use when you want the un-processed records (TimeUTC, TimeDK, PriceArea, DayAheadPriceDKK, DayAheadPriceEUR).",
        "parameters": [
          {
            "name": "area",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "DK1",
                "DK2"
              ],
              "default": "DK1"
            },
            "description": "Danish price zone — DK1 (Vestdanmark) or DK2 (Østdanmark)."
          },
          {
            "name": "start",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD inclusive."
          },
          {
            "name": "end",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "YYYY-MM-DD exclusive."
          }
        ],
        "responses": {
          "200": {
            "description": "Records array."
          }
        }
      }
    },
    "/api/raw/encharges": {
      "get": {
        "operationId": "getRawEnCharges",
        "summary": "Energinet system/transmission/elafgift charges",
        "responses": {
          "200": {
            "description": "Records array."
          }
        }
      }
    },
    "/api/raw/tariff": {
      "get": {
        "operationId": "getRawNetTariff",
        "summary": "Single net company's Nettarif C (24 hourly values)",
        "parameters": [
          {
            "name": "gln",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Net company GLN (13 digits). Required when mode is `net_inkl_alt` or `net_inkl_tarif`.",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Records array."
          }
        }
      }
    },
    "/api/raw/tariffs": {
      "get": {
        "operationId": "getRawAllTariffs",
        "summary": "All Danish net companies' Nettarif C (used by /tariffer page)",
        "responses": {
          "200": {
            "description": "Records array — ~48 KB."
          }
        }
      }
    },
    "/api/supplierlookup": {
      "get": {
        "operationId": "lookupSupplier",
        "summary": "Lat/lng → DK address → net company",
        "description": "Reverse-geocodes coordinates via DAWA and looks up the netselskab via GreenPowerDenmark. Proxied here because GPD returns no CORS headers.",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Address + resolved net name.",
            "content": {
              "application/json": {
                "example": {
                  "address": "Hasle Ringvej 110B, 8200 Aarhus N",
                  "name": "KONSTANT Net A/S"
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "operationId": "getOpenApiSpec",
        "summary": "This document",
        "responses": {
          "200": {
            "description": "OpenAPI 3.1 spec."
          }
        }
      }
    }
  }
}