FuelWatch API
API reference

Service stations

GET /v1 returns one resource per station with all selected fuel prices.

GET /v1

GET
/v1

Returns a complete validated collection for one selected Perth date. Omit product for all seven supported fuels. No pagination is applied.

Request headers

application/vnd.api+json
optional
Recommended. Omission or a compatible wildcard is also accepted.
string
optional
Optional ETag from a previously stored response to the same selection.

Query parameters

optional
Comma-separated product codes. Defaults to all seven.
integer[]
optional
Comma-separated known FuelWatch brand codes. Code 0 is response-only and is rejected as a filter.
integer[]
optional
Comma-separated region codes. Uses source-side selection.
string[]
optional
Comma-separated suburb names. Pair with surrounding=no for exact suburbs.
string
optional
yesterday, today, tomorrow or DD/MM/YYYY within those three Perth dates.
Default: today
string
optional
Omission uses source behavior; no gives exact suburb matching.
Possible enum values
yes
no
string[]
optional
brand, siteFeatures, restrictions or all. Omitted references are codes.

All six filters also accept filter[...] names. Query parsing, aliases and combination limits are described in Filtering.

The example uses brand 32, suburb PERTH AIRPORT and surrounding=no to obtain a small, complete response. No station records or attributes were removed. Omitting product selects all seven fuels; Costco Perth Airport returned prices for products 1, 6 and 11 in this capture.

Expanded response with enrichment

The same selection with expand=all includes named reference objects, opening hours and Google Maps provenance. enrichment.fields identifies the provider's contribution; the phone number and opening hours are also present, but were supplied by FuelWatch in this example. See source priority and attribution.

All references expanded, with enrichment

Captured 2026-09-30T11:42:42.891+08:00 (AWST) · HTTP 200. Historical snapshot; repeat the request for current data.

Request
curl 'https://fuelwatch.oss.bhodges.me/v1?brand=32&suburb=PERTH%20AIRPORT&surrounding=no&expand=all' \
  -H 'Accept: application/vnd.api+json'
Example response
{
  "jsonapi": {
    "version": "1.1"
  },
  "meta": {
    "source": "fuelwatch.wa.gov.au",
    "products": [
      1,
      2,
      4,
      5,
      6,
      10,
      11
    ],
    "sourceDate": "2026-09-30",
    "fetchedAt": "2026-09-30T11:00:52.278+08:00",
    "validFrom": "2026-09-30T06:00:00.000+08:00",
    "validUntil": "2026-10-01T06:00:00.000+08:00",
    "publicationStatus": "available",
    "copyright": "Copyright 2025 Department of Local Government, Industry Regulation and Safety (source data); Copyright 2026 Bradley Hodges (api). All rights reserved.",
    "documentation": "https://docs.fuelwatch.oss.bhodges.me",
    "issues": "https://github.com/bradleyhodges/fuelwatch-api/issues",
    "version": "4.30.1"
  },
  "data": [
    {
      "type": "serviceStation",
      "id": "2026-09-30:dca78516464d85042c12eab0fd45d71665adc32b578908bc8444f29201d02ba7",
      "attributes": {
        "name": "Costco Perth Airport",
        "tradingName": "Costco Perth Airport",
        "brand": {
          "code": 32,
          "name": "Costco",
          "logo": "/static/image/brand/costco.svg"
        },
        "price": {
          "asAt": "2026-09-30T06:00:00.000+08:00",
          "products": {
            "1": 218.7,
            "6": 242.7,
            "11": 264.7
          }
        },
        "address": {
          "street": "142 Dunreath Dr",
          "suburb": "PERTH AIRPORT",
          "state": "WA",
          "postcode": "6105"
        },
        "is24Hours": false,
        "phone": "+61893114700",
        "latitude": -31.940377,
        "longitude": 115.951869,
        "siteFeatures": [
          {
            "code": 8,
            "name": "EFTPOS"
          },
          {
            "code": 1,
            "name": "Credit Cards"
          },
          {
            "code": 2,
            "name": "Debit Cards"
          }
        ],
        "restrictions": [
          {
            "code": 3,
            "name": "Membership Required"
          }
        ],
        "enrichment": {
          "provider": "Google Maps",
          "placeId": "ChIJw1UkrSm5MioRiEMGrwrsOUI",
          "fetchedAt": "2026-09-29T18:36:18.295+08:00",
          "stale": false,
          "fields": [
            "address.postcode",
            "siteFeatures"
          ],
          "googleMapsUri": "https://www.google.com/maps/search/?api=1&query=Costco%20Perth%20Airport&query_place_id=ChIJw1UkrSm5MioRiEMGrwrsOUI",
          "attributions": []
        },
        "openHours": {
          "Monday": "06:00-21:30",
          "Tuesday": "06:00-21:30",
          "Wednesday": "06:00-21:30",
          "Thursday": "06:00-21:30",
          "Friday": "06:00-21:30",
          "Saturday": "06:00-19:30",
          "Sunday": "07:00-19:00"
        }
      }
    }
  ]
}

Collection behavior

The response contains jsonapi, meta and data. A station selling multiple selected fuels appears once. price.products contains only its available selected products. A single-product query uses the same grouped shape.

Resource type is always serviceStation. The id combines sourceDate with a SHA-256 digest of normalized station identity. It is stable across product selections, expansion, price corrections and enrichment changes, but not across source dates. Treat it as opaque; there is no /v1/{id} endpoint. A moved or otherwise reidentified station can receive a different identity.

Ordering is deterministic for a selection but is not a global cheapest-station ranking across fuels. Sort locally for the product you are comparing. Do not persist row indexes as station identifiers.

Completeness and bounds

Every required source request must validate before the API publishes success. Conflicting quotes, invalid dates/prices/coordinates, unsafe XML and excessive input reject the selection. Individual source responses are bounded to 4 MiB and 5,000 stations; combined selections are limited to 10,000 input quotes. Source-filtered combined input is also bounded to 16 MiB.

An empty data array is a valid 200 result. A missing product at a station is unavailable, not zero-priced. Unknown phone/postcode/schedule values remain null or omitted as specified.

HEAD and OPTIONS

HEAD /v1 uses the same query, validation, status, ETag and cache semantics as GET, then omits the body. A matching If-None-Match gives 304. OPTIONS /v1 provides public CORS preflight; it does not read prices.

See HTTP behavior, caching and the error catalogue.

On this page