⛽ Fuel Finder

API Reference

All endpoints return JSON. Base URL: /api/. No authentication required by default.

Sections

Price data Reference Admin / lookups

Price data

GET /api/summary
Dashboard headline numbers: average/min/max prices per fuel type, station count, last scrape time.
{
  "by_fuel_type": [
    { "fuel_type": "E10", "fuel_name": "Unleaded (E10)",
      "avg_price": 149.3, "min_price": 135.9, "max_price": 199.9, "station_count": 7277 }
  ],
  "total_stations": 7466,
  "total_prices": 24551,
  "last_scrape": "2026-03-25T14:00:00Z"
}
GET /api/prices/by-region
Average price by ONS region.
ParameterTypeDefaultDescription
fuel_typestringE10Fuel type code

Returns: [ { region, avg_price, min_price, max_price, station_count } ]

GET /api/prices/by-brand
Average price by canonical brand name (minimum 3 stations).
ParameterTypeDefaultDescription
fuel_typestringE10Fuel type code
limitint20Max brands (1–100)

Returns: [ { brand_name, forecourt_type, avg_price, min_price, max_price, station_count } ]

GET /api/prices/by-category
Average price by forecourt category (Supermarket, Major Oil, Motorway, etc.).
ParameterTypeDefaultDescription
fuel_typestringE10Fuel type code

Returns: [ { forecourt_type, avg_price, min_price, max_price, station_count } ]

GET /api/prices/history
Daily average price over time, optionally filtered by region.
ParameterTypeDefaultDescription
fuel_typestringE10Fuel type code
daysint30Days back (1–365)
regionstringOptional region filter

Returns: [ { day, avg_price, stations } ]

GET /api/prices/map
Current prices with coordinates for map display.
ParameterTypeDefaultDescription
fuel_typestringE10Fuel type code

Returns: array with node_id, trading_name, brand_name, city, postcode, price, fuel_name, forecourt_type, latitude, longitude

GET /api/prices/search
Flexible search/filter with pagination.
ParameterTypeDefaultDescription
fuel_typestringE10Fuel type code
postcodestringPostcode prefix (e.g. SW1)
brandstringBrand substring
citystringCity substring
min_pricefloatMin price (pence)
max_pricefloatMax price (pence)
categorystringForecourt type filter
sortstringpriceprice, brand, city, postcode
limitint50Results per page (1–500)
offsetint0Pagination offset

Returns: { results: [...], total, limit, offset }

GET /api/anomalies
Price records flagged by anomaly detection.
ParameterTypeDefaultDescription
limitint50Max records (1–500)

Flags: price_below_floor, price_above_ceiling, likely_decimal_error, large_price_jump

Reference

GET /api/fuel-types
List fuel types with human names and categories.

Returns: [ { fuel_type_code, fuel_name, fuel_category } ]

GET /api/regions
List available regions.

Returns: [ "London", "North West", "Scotland", ... ]

Admin / lookup tables

Changes to lookup tables are not reflected in the dashboard until you call POST /api/admin/refresh-view to rebuild the materialised view.

Brand aliases

Map raw API brand strings to canonical names (e.g. "TESCO PFS""Tesco").

GET /api/admin/brand-aliases
List all alias mappings.
POST /api/admin/brand-aliases
Create or update an alias. Upserts on raw_brand_name.
{ "raw_brand_name": "TESCO PFS", "canonical_brand": "Tesco" }
DEL /api/admin/brand-aliases/{raw_brand_name}
Delete an alias mapping.

Brand categories

Map canonical brands to forecourt types for category-level price comparison.

GET /api/admin/brand-categories
List all category mappings.
POST /api/admin/brand-categories
Create or update a category. Upserts on canonical_brand.
{ "canonical_brand": "Tesco", "forecourt_type": "Supermarket" }

Allowed types: Supermarket, Major Oil, Motorway Operator, Fuel Group, Convenience, Independent

DEL /api/admin/brand-categories/{canonical_brand}
Delete a category mapping (brand defaults to Independent).

Station overrides

Per-station brand overrides for edge cases (takes priority over aliases).

GET /api/admin/station-overrides
List all overrides with station details.
POST /api/admin/station-overrides
Create or update an override. Upserts on node_id.
{ "node_id": "abc123...", "canonical_brand": "Shell", "notes": "Branded Shell but API says independent" }
DEL /api/admin/station-overrides/{node_id}
Delete a station override.

Normalisation report

GET /api/admin/normalisation-report
Shows how each brand resolves through the normalisation pipeline.
ParameterTypeDefaultDescription
limitint100Max rows (1–1000)
typestringaliased, overridden, or unmapped
brandstringBrand substring filter

Returns: [ { raw_brand, alias_resolved, override_resolved, final_brand, forecourt_type, resolution_method, station_count } ]

resolution_method: raw (no transformation), alias (via brand_aliases), override (via station_brand_overrides)

Refresh view

POST /api/admin/refresh-view
Rebuilds the current_prices materialised view. Call after changing any lookup table.
{ "status": "ok", "message": "current_prices view refreshed" }