{
  "openapi": "3.0.3",
  "info": {
    "title": "fuel-prices.eu Data API",
    "version": "1.0.0",
    "description": "Read-only JSON API over European fuel prices. Weekly national history from the European Commission Weekly Oil Bulletin (29 countries, since 2005) and live station-level prices collected from official national sources across 21 markets, plus tolls, a GeoJSON map layer and a natural-language endpoint for AI agents.\n\nAll prices are EUR per litre, tax inclusive; local currencies are converted at the daily central-bank rate. Timestamps are UTC.\n\nNo authentication is enforced today: every operation below is open. Plan quotas (Free 1,000 / Pro 50,000 / Business 500,000 requests a month) are contractual and are opened by e-mail until card payment and API keys go live. See https://www.fuel-prices.eu/api/pricing/.\n\nEvery endpoint sends `Access-Control-Allow-Origin: *` except `/live/board_now.php`. Apache appends a second, longer `Cache-Control: max-age=3600` after the value PHP sets; treat the shorter one as authoritative.",
    "termsOfService": "https://www.fuel-prices.eu/a/terms.php",
    "contact": {
      "name": "fuel-prices.eu",
      "email": "hi@fuel-prices.eu",
      "url": "https://www.fuel-prices.eu/api/pricing/"
    },
    "license": {
      "name": "CC BY 4.0 (weekly Commission series); see licence FAQ for live station data",
      "url": "https://www.fuel-prices.eu/api/pricing/#faq"
    }
  },
  "externalDocs": {
    "description": "Endpoint reference with real captured responses",
    "url": "https://www.fuel-prices.eu/api/docs/"
  },
  "servers": [
    {
      "url": "https://www.fuel-prices.eu",
      "description": "Production"
    }
  ],
  "tags": [
    {
      "name": "live",
      "description": "Live prices from official national sources"
    },
    {
      "name": "history",
      "description": "Weekly national series from the EC Weekly Oil Bulletin"
    },
    {
      "name": "geo",
      "description": "Map-ready geometry"
    },
    {
      "name": "agents",
      "description": "Natural-language access for AI agents"
    },
    {
      "name": "roads",
      "description": "Toll and barrier infrastructure"
    }
  ],
  "paths": {
    "/live/api.php": {
      "get": {
        "tags": [
          "live"
        ],
        "operationId": "liveApi",
        "summary": "Live prices: summary, brands, stations or pipeline stats",
        "description": "One endpoint, four actions selected by the `action` parameter. `summary` and `stats` need nothing else; `brands` needs `country`; `stations` needs `country`, `lat` and `lng`.",
        "parameters": [
          {
            "name": "action",
            "in": "query",
            "required": true,
            "description": "Which view to return.",
            "schema": {
              "type": "string",
              "enum": [
                "summary",
                "brands",
                "stations",
                "stats"
              ],
              "default": "summary"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "ISO 3166-1 alpha-2 code. Required for `brands` and `stations`.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            },
            "example": "GB"
          },
          {
            "name": "fuel",
            "in": "query",
            "required": false,
            "description": "Fuel code. Defaults to `diesel` on `brands`.",
            "schema": {
              "type": "string",
              "enum": [
                "diesel",
                "sp95",
                "sp98",
                "e10",
                "e5",
                "e85",
                "gpl",
                "cng",
                "lng",
                "hvo"
              ]
            }
          },
          {
            "name": "lat",
            "in": "query",
            "required": false,
            "description": "Latitude, WGS 84. Required for `stations`; must be non-zero.",
            "schema": {
              "type": "number",
              "format": "double"
            },
            "example": 48.85
          },
          {
            "name": "lng",
            "in": "query",
            "required": false,
            "description": "Longitude, WGS 84. Required for `stations`; must be non-zero.",
            "schema": {
              "type": "number",
              "format": "double"
            },
            "example": 2.35
          },
          {
            "name": "radius",
            "in": "query",
            "required": false,
            "description": "Search radius in km for `stations`. Silently capped at 50.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 10
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum stations returned. Silently capped at 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success. The shape of `data` depends on `action`.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=300",
                "schema": {
                  "type": "string"
                }
              },
              "Access-Control-Allow-Origin": {
                "description": "*",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/SummaryEnvelope"
                    },
                    {
                      "$ref": "#/components/schemas/BrandsEnvelope"
                    },
                    {
                      "$ref": "#/components/schemas/StationsEnvelope"
                    },
                    {
                      "$ref": "#/components/schemas/StatsEnvelope"
                    }
                  ]
                },
                "examples": {
                  "summary": {
                    "summary": "action=summary (2 of 21 markets)",
                    "value": {
                      "ok": true,
                      "data": {
                        "countries": [
                          {
                            "country_code": "AD",
                            "fuels": {
                              "diesel": {
                                "stations": 54,
                                "min": 1.619,
                                "max": 1.64,
                                "avg": 1.629
                              },
                              "sp95": {
                                "stations": 54,
                                "min": 1.609,
                                "max": 1.628,
                                "avg": 1.616
                              }
                            },
                            "last_fetched": "2026-09-07 21:07:07",
                            "total_stations": 54
                          },
                          {
                            "country_code": "AT",
                            "fuels": {
                              "diesel": {
                                "stations": 1722,
                                "min": 1.799,
                                "max": 2.449,
                                "avg": 2.092
                              },
                              "sp95": {
                                "stations": 1592,
                                "min": 1.689,
                                "max": 2.199,
                                "avg": 1.889
                              }
                            },
                            "last_fetched": "2026-09-07 18:40:55",
                            "total_stations": 2378
                          }
                        ]
                      }
                    }
                  },
                  "brands": {
                    "summary": "action=brands&country=GB&fuel=diesel",
                    "value": {
                      "ok": true,
                      "data": {
                        "country": "GB",
                        "fuel": "diesel",
                        "brands": [
                          {
                            "brand_name": "Go",
                            "logo_file": null,
                            "station_count": 6,
                            "price_min": "1.966",
                            "price_max": "2.083",
                            "price_avg": "2.043"
                          },
                          {
                            "brand_name": "Costco Wholesale",
                            "logo_file": null,
                            "station_count": 18,
                            "price_min": "2.013",
                            "price_max": "2.129",
                            "price_avg": "2.060"
                          }
                        ]
                      }
                    }
                  },
                  "stations": {
                    "summary": "action=stations&country=FR&lat=48.85&lng=2.35&radius=10&limit=1",
                    "value": {
                      "ok": true,
                      "data": {
                        "country": "FR",
                        "center": {
                          "lat": 48.85,
                          "lng": 2.35
                        },
                        "radius": 10,
                        "stations": [
                          {
                            "id": 6808,
                            "name": "Station PARIS",
                            "brand": null,
                            "logo": null,
                            "address": "8,10,10bis Rue Bailleul",
                            "city": "PARIS",
                            "postal_code": "75001",
                            "lat": 48.861,
                            "lng": 2.341,
                            "is_open": true,
                            "distance_km": 1.4,
                            "prices": {
                              "diesel": {
                                "price": 2.68,
                                "updated": "2026-09-04 21:30:24"
                              },
                              "sp95": {
                                "price": 2.49,
                                "updated": "2026-09-04 21:30:24"
                              }
                            }
                          }
                        ]
                      }
                    }
                  },
                  "stats": {
                    "summary": "action=stats",
                    "value": {
                      "ok": true,
                      "data": {
                        "station_counts": {
                          "AD": 54,
                          "AT": 2378,
                          "FR": 10109,
                          "IT": 22423
                        },
                        "price_counts": {
                          "AD": 163,
                          "AT": 4227,
                          "FR": 35572,
                          "IT": 51733
                        },
                        "recent_fetches": [
                          {
                            "country_code": "AD",
                            "source": "govern_ad",
                            "fetch_started_at": "2026-09-08 00:07:01",
                            "fetch_ended_at": "2026-09-08 00:07:07",
                            "stations_processed": 54,
                            "prices_updated": 163,
                            "status": "success",
                            "execution_time_sec": "6.00"
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Missing required parameter or unknown action.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveError"
                },
                "examples": {
                  "missingCountry": {
                    "value": {
                      "ok": false,
                      "error": "country parameter required"
                    }
                  },
                  "unknownAction": {
                    "value": {
                      "ok": false,
                      "error": "Unknown action: nope"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Database or upstream failure.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LiveError"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/live/board_now.php": {
      "get": {
        "tags": [
          "live"
        ],
        "operationId": "boardNow",
        "summary": "National petrol and diesel averages in one flat object",
        "description": "The smallest call on the service, under 500 bytes. `ts` is a Unix epoch in seconds. Note: this is the only endpoint that does NOT send `Access-Control-Allow-Origin`, so it cannot be fetched from a browser on another origin — call it server-side, or use `/live/api.php?action=summary` instead.",
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Board"
                },
                "example": {
                  "ok": true,
                  "ts": 1788814863,
                  "petrol": {
                    "AD": 1.616,
                    "AT": 1.889,
                    "FR": 2.166,
                    "GB": 1.935,
                    "IT": 2.056
                  },
                  "diesel": {
                    "AD": 1.629,
                    "AT": 2.092,
                    "FR": 1.996,
                    "GB": 2.043,
                    "IT": 1.987
                  }
                }
              }
            },
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=120",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "500": {
            "description": "Database or upstream failure."
          }
        },
        "security": []
      }
    },
    "/live/geojson.php": {
      "get": {
        "tags": [
          "geo",
          "live"
        ],
        "operationId": "liveGeojson",
        "summary": "Stations with prices as a GeoJSON FeatureCollection",
        "description": "Drop straight into Leaflet or Mapbox. Always pass `bounds`: the default box is centred on western Europe, so a country outside it returns zero features rather than an error.",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$",
              "default": "FR"
            }
          },
          {
            "name": "fuel",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "default": "diesel"
            }
          },
          {
            "name": "bounds",
            "in": "query",
            "required": false,
            "description": "Bounding box as `south,west,north,east` in decimal degrees.",
            "schema": {
              "type": "string"
            },
            "example": "45.4,13.3,46.9,16.6"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 10,
              "maximum": 5000,
              "default": 1500
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Price order.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ],
              "default": "asc"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A FeatureCollection. Note: the `oh` (opening hours) property is enriched from OpenStreetMap on some records and carries ODbL 1.0 share-alike terms.",
            "content": {
              "application/geo+json": {
                "schema": {
                  "$ref": "#/components/schemas/FeatureCollection"
                },
                "example": {
                  "type": "FeatureCollection",
                  "features": [
                    {
                      "type": "Feature",
                      "geometry": {
                        "type": "Point",
                        "coordinates": [
                          16.0513559,
                          46.3896077
                        ]
                      },
                      "properties": {
                        "id": 10075914,
                        "name": "West Oil BS Zavrč",
                        "brand": "West oil",
                        "address": "Zavrč 8c",
                        "city": "Zavrč",
                        "postal_code": "2283",
                        "price": 1.463,
                        "fuel": "diesel",
                        "is_open": true,
                        "updated": "2026-09-07 14:05:51",
                        "oh": "Mo-Fr 08:00-18:00; Sa-Su off",
                        "open": "closed",
                        "next": "08:00"
                      }
                    }
                  ],
                  "meta": {
                    "country": "SI",
                    "fuel": "diesel",
                    "returned": 3,
                    "limited": false
                  }
                }
              }
            },
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=120",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "400": {
            "description": "Malformed `bounds` or an unusable parameter."
          }
        },
        "security": []
      }
    },
    "/lang/api/country-history.php": {
      "get": {
        "tags": [
          "history"
        ],
        "operationId": "countryHistory",
        "summary": "Five years of weekly Euro 95 and diesel prices for one country",
        "description": "Three index-aligned arrays. Source: European Commission Weekly Oil Bulletin, so the series is comparable between countries. A week with no reading for a fuel carries `0`, not `null`. The database holds the full series back to 2005; this endpoint exposes the last five years.",
        "parameters": [
          {
            "name": "cc",
            "in": "query",
            "required": true,
            "description": "ISO 3166-1 alpha-2, case-insensitive. `EL` and `GR` both return Greece.",
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z]{2}$"
            },
            "example": "DE"
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=3600",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/History"
                },
                "example": {
                  "cc": "DE",
                  "labels": [
                    "2021-09-13",
                    "2021-09-20",
                    "2026-08-31"
                  ],
                  "e95": [
                    1.629,
                    1.636,
                    2.236
                  ],
                  "diesel": [
                    1.401,
                    1.42,
                    2.232
                  ],
                  "count": 258
                }
              }
            }
          },
          "400": {
            "description": "Country code is not two letters.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "example": {
                  "error": "Invalid country code"
                }
              }
            }
          },
          "500": {
            "description": "Database unavailable.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlainError"
                },
                "example": {
                  "error": "Database unavailable"
                }
              }
            }
          }
        },
        "security": []
      }
    },
    "/api/natural-language/": {
      "get": {
        "tags": [
          "agents"
        ],
        "operationId": "naturalLanguageQuery",
        "summary": "Ask a question in English, get structured data with provenance",
        "description": "Built for AI agents. Returns the parsed intent, a confidence score and a metadata block naming the source and its update cadence. Enforces 60 requests a minute per IP.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "The question.",
            "schema": {
              "type": "string"
            },
            "example": "cheapest diesel in Germany"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "`csv` returns text/csv with a commented provenance header.",
            "schema": {
              "type": "string",
              "enum": [
                "full",
                "compact",
                "csv"
              ],
              "default": "full"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NlAnswer"
                },
                "example": {
                  "status": "ok",
                  "query": "cheapest diesel in Germany",
                  "intent": "cheapest_ranking",
                  "confidence": 0.95,
                  "parsed": {
                    "countries": [
                      "DE"
                    ],
                    "fuel_type": "diesel",
                    "time_range_weeks": 12
                  },
                  "metadata": {
                    "generated_at": "2026-09-07T21:07:36+00:00",
                    "data_date": "2026-08-31",
                    "source": "European Commission Weekly Oil Bulletin",
                    "currency": "EUR",
                    "unit": "per liter, tax-inclusive",
                    "update_frequency": "weekly (Thursday after 15:00 EET)"
                  },
                  "message": "EU countries ranked by diesel price, cheapest first (2026-08-31). #1: Malta."
                }
              },
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=900",
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests in a minute from one IP."
          }
        },
        "security": []
      },
      "post": {
        "tags": [
          "agents"
        ],
        "operationId": "naturalLanguageBatch",
        "summary": "Ask one or several questions in a single call",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "required": [
                      "query"
                    ],
                    "properties": {
                      "query": {
                        "type": "string"
                      }
                    }
                  },
                  {
                    "type": "object",
                    "required": [
                      "queries"
                    ],
                    "properties": {
                      "queries": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        }
                      }
                    }
                  }
                ]
              },
              "example": {
                "queries": [
                  "price in Poland",
                  "price in Germany"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "One answer, or an array of answers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "429": {
            "description": "More than 60 requests in a minute from one IP."
          }
        },
        "security": []
      }
    },
    "/api/toll/get_json.php": {
      "get": {
        "tags": [
          "roads"
        ],
        "operationId": "tollDataset",
        "summary": "Every tracked toll tunnel, bridge, pass and mainline barrier",
        "description": "No parameters: the whole dataset comes back (about 210 KB) and you filter client-side. Cached for a day.",
        "responses": {
          "200": {
            "description": "Success.",
            "headers": {
              "Cache-Control": {
                "description": "public, max-age=86400",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TollSet"
                },
                "example": {
                  "count": 546,
                  "data": [
                    {
                      "id": 1445,
                      "country_code": "AD",
                      "type": "tunnel",
                      "barrier_type": "mainline",
                      "name": "Tunel d'Envalira",
                      "price_eur": 7.9,
                      "price_local": 7.9,
                      "currency": "EUR",
                      "info": "Connects Pas de la Casa (FR border)",
                      "lat": 42.545,
                      "lng": 1.715
                    }
                  ]
                }
              }
            }
          },
          "500": {
            "description": "Database connection failed."
          },
          "400": {
            "description": "Unusable request."
          }
        },
        "security": []
      }
    },
    "/api/waitlist.php": {
      "post": {
        "tags": [
          "agents"
        ],
        "operationId": "requestAccess",
        "summary": "Request access to a paid plan",
        "description": "Backs the form on /api/pricing/. Sends `application/json` in `Accept` to get JSON back; a plain browser form POST is answered with a 303 redirect to the pricing page. One request per minute per IP.",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "name",
                  "email",
                  "plan",
                  "use_case"
                ],
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 120
                  },
                  "company": {
                    "type": "string",
                    "maxLength": 160
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 190
                  },
                  "plan": {
                    "type": "string",
                    "enum": [
                      "free",
                      "pro",
                      "business"
                    ]
                  },
                  "use_case": {
                    "type": "string",
                    "maxLength": 2000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Stored.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean"
                    },
                    "id": {
                      "type": "integer"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "success": true,
                  "id": 1,
                  "message": "Thanks — your request is in. We reply from hi@fuel-prices.eu, usually within two working days."
                }
              }
            }
          },
          "400": {
            "description": "A field failed validation; `fields` names which."
          },
          "405": {
            "description": "Anything other than POST."
          },
          "429": {
            "description": "More than one request a minute from one IP."
          },
          "500": {
            "description": "Could not store the request."
          }
        },
        "security": []
      }
    }
  },
  "components": {
    "schemas": {
      "FuelStats": {
        "type": "object",
        "description": "Aggregates for one fuel type in one market.",
        "properties": {
          "stations": {
            "type": "integer",
            "description": "Stations contributing a usable price."
          },
          "min": {
            "type": "number",
            "format": "double"
          },
          "max": {
            "type": "number",
            "format": "double"
          },
          "avg": {
            "type": "number",
            "format": "double"
          }
        }
      },
      "CountrySummary": {
        "type": "object",
        "properties": {
          "country_code": {
            "type": "string"
          },
          "fuels": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/FuelStats"
            }
          },
          "last_fetched": {
            "type": "string",
            "description": "UTC, `YYYY-MM-DD HH:MM:SS`.",
            "nullable": true
          },
          "total_stations": {
            "type": "integer"
          }
        }
      },
      "SummaryEnvelope": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "countries": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/CountrySummary"
                }
              }
            },
            "required": [
              "countries"
            ]
          }
        },
        "required": [
          "ok",
          "data"
        ]
      },
      "Brand": {
        "type": "object",
        "description": "Aggregates are returned as decimal strings, not numbers.",
        "properties": {
          "brand_name": {
            "type": "string"
          },
          "logo_file": {
            "type": "string",
            "nullable": true
          },
          "station_count": {
            "type": "integer"
          },
          "price_min": {
            "type": "string"
          },
          "price_max": {
            "type": "string"
          },
          "price_avg": {
            "type": "string"
          }
        }
      },
      "BrandsEnvelope": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "country": {
                "type": "string"
              },
              "fuel": {
                "type": "string"
              },
              "brands": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Brand"
                }
              }
            },
            "required": [
              "brands"
            ]
          }
        },
        "required": [
          "ok",
          "data"
        ]
      },
      "StationPrice": {
        "type": "object",
        "properties": {
          "price": {
            "type": "number",
            "format": "double"
          },
          "updated": {
            "type": "string",
            "nullable": true,
            "description": "When the source last moved this price."
          }
        }
      },
      "Station": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "brand": {
            "type": "string",
            "nullable": true
          },
          "logo": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "postal_code": {
            "type": "string",
            "nullable": true
          },
          "lat": {
            "type": "number",
            "format": "double"
          },
          "lng": {
            "type": "number",
            "format": "double"
          },
          "is_open": {
            "type": "boolean"
          },
          "distance_km": {
            "type": "number",
            "format": "double"
          },
          "prices": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/StationPrice"
            }
          }
        }
      },
      "StationsEnvelope": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "country": {
                "type": "string"
              },
              "center": {
                "type": "object",
                "properties": {
                  "lat": {
                    "type": "number"
                  },
                  "lng": {
                    "type": "number"
                  }
                }
              },
              "radius": {
                "type": "integer"
              },
              "stations": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Station"
                }
              }
            },
            "required": [
              "stations"
            ]
          }
        },
        "required": [
          "ok",
          "data"
        ]
      },
      "FetchLogEntry": {
        "type": "object",
        "properties": {
          "country_code": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "fetch_started_at": {
            "type": "string"
          },
          "fetch_ended_at": {
            "type": "string",
            "nullable": true
          },
          "stations_processed": {
            "type": "integer",
            "nullable": true
          },
          "prices_updated": {
            "type": "integer",
            "nullable": true
          },
          "status": {
            "type": "string"
          },
          "execution_time_sec": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "StatsEnvelope": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "data": {
            "type": "object",
            "properties": {
              "station_counts": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "price_counts": {
                "type": "object",
                "additionalProperties": {
                  "type": "integer"
                }
              },
              "recent_fetches": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/FetchLogEntry"
                }
              }
            },
            "required": [
              "station_counts"
            ]
          }
        },
        "required": [
          "ok",
          "data"
        ]
      },
      "Board": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "ts": {
            "type": "integer",
            "format": "int64",
            "description": "Unix epoch, seconds."
          },
          "petrol": {
            "type": "object",
            "additionalProperties": {
              "type": "number",
              "format": "double"
            }
          },
          "diesel": {
            "type": "object",
            "additionalProperties": {
              "type": "number",
              "format": "double"
            }
          }
        }
      },
      "Feature": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "Feature"
            ]
          },
          "geometry": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "Point"
                ]
              },
              "coordinates": {
                "type": "array",
                "items": {
                  "type": "number"
                },
                "minItems": 2,
                "maxItems": 2,
                "description": "[longitude, latitude]"
              }
            }
          },
          "properties": {
            "type": "object",
            "properties": {
              "id": {
                "type": "integer"
              },
              "name": {
                "type": "string",
                "nullable": true
              },
              "brand": {
                "type": "string",
                "nullable": true
              },
              "address": {
                "type": "string",
                "nullable": true
              },
              "city": {
                "type": "string",
                "nullable": true
              },
              "postal_code": {
                "type": "string",
                "nullable": true
              },
              "price": {
                "type": "number",
                "format": "double"
              },
              "fuel": {
                "type": "string"
              },
              "is_open": {
                "type": "boolean"
              },
              "updated": {
                "type": "string",
                "nullable": true
              },
              "oh": {
                "type": "string",
                "nullable": true,
                "description": "Opening hours. Enriched from OpenStreetMap on some records: ODbL 1.0 share-alike applies to this field."
              },
              "open": {
                "type": "string",
                "nullable": true
              },
              "next": {
                "type": "string",
                "nullable": true
              }
            }
          }
        }
      },
      "FeatureCollection": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "FeatureCollection"
            ]
          },
          "features": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Feature"
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "country": {
                "type": "string"
              },
              "fuel": {
                "type": "string"
              },
              "bounds": {
                "type": "array",
                "items": {
                  "type": "number"
                }
              },
              "returned": {
                "type": "integer"
              },
              "total_in_view": {
                "type": "integer"
              },
              "price_min": {
                "type": "number"
              },
              "price_max": {
                "type": "number"
              },
              "price_avg": {
                "type": "number"
              },
              "limited": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "History": {
        "type": "object",
        "properties": {
          "cc": {
            "type": "string"
          },
          "labels": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "date"
            }
          },
          "e95": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "diesel": {
            "type": "array",
            "items": {
              "type": "number",
              "format": "double"
            }
          },
          "count": {
            "type": "integer"
          }
        }
      },
      "NlAnswer": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "query": {
            "type": "string"
          },
          "intent": {
            "type": "string"
          },
          "confidence": {
            "type": "number",
            "format": "float"
          },
          "parsed": {
            "type": "object"
          },
          "metadata": {
            "type": "object"
          },
          "message": {
            "type": "string"
          },
          "data": {
            "type": "object"
          }
        }
      },
      "Toll": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer"
          },
          "country_code": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "barrier_type": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string"
          },
          "price_eur": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "price_local": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "currency": {
            "type": "string",
            "nullable": true
          },
          "info": {
            "type": "string",
            "nullable": true
          },
          "lat": {
            "type": "number",
            "format": "double",
            "nullable": true
          },
          "lng": {
            "type": "number",
            "format": "double",
            "nullable": true
          }
        }
      },
      "TollSet": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Toll"
            }
          }
        }
      },
      "LiveError": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "string"
          }
        }
      },
      "PlainError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string"
          }
        }
      }
    }
  },
  "security": []
}
