# Locations

```bash
curl "https://api.cardog.app/v2/locations?lat=43.6532&lng=-79.3832&kind=fuel,charging&limit=1" \
  -H "x-api-key: $CARDOG_API_KEY"
```

The places a driver goes near a point, nearest first: gas stations,
charging sites, dealers' lots. Each place comes back once, with one ref,
`poi:dpz83errq8`, whatever it offers and however many listings describe
it. One credit a request.

> **Store the ref.** The ref is derived from the place's coordinates, so it
> is stable for as long as the place does not move. It carries no name and
> no upstream id: a station that changes brand keeps its ref. That makes it
> a safe key for favourites, trips and saved stops.

The `id` is the ref without `poi:`, a geohash: ten characters that
locate the place to within about a metre. `/v2/locations/dpz83errq8` is
the place. An id that is not a geohash is a `404`.

## Kinds

Each location lists what it is in `kinds`:

| kind | the place | detail |
| --- | --- | --- |
| `fuel` | sells fuel at the pump | [Fuel prices](https://cardog.app/docs/fuel) |
| `charging` | has public EV chargers | [Charging stations](https://cardog.app/docs/charging) |
| `seller` | a dealer's rooftop | every dealer that sells there |

One place can be several kinds. A travel centre with pumps and fast
chargers is one location with `kinds: ["fuel", "charging"]`, not two
records a metre apart. A dealer with a charger on the lot is
`["seller", "charging"]`. An auto mall is one `seller` location that
holds several dealers.

## Places near a point

The search above returns:

```json
{
  "total": 1,
  "asOf": "2026-10-25",
  "locations": [
    {
      "ref": "poi:dpz83errq8",
      "id": "dpz83errq8",
      "kinds": ["fuel"],
      "name": "Esso",
      "brand": "Esso",
      "address": {
        "street": "241 Church St",
        "city": "Toronto",
        "state": "ON",
        "postalCode": "M5B 1Z4",
        "country": "CA"
      },
      "location": { "latitude": 43.65679406, "longitude": -79.37697172 },
      "distanceKm": 0.64,
      "links": {
        "self": "/v2/locations/dpz83errq8",
        "fuel": "/v2/fuel/stations/dpz83errq8"
      }
    }
  ],
  "links": { "self": "/v2/locations" }
}
```

- **`radius_km`** defaults to 10 and caps at 100.
- **`limit`** defaults to 20 and caps at 100.
- **`kind`** is optional and takes one kind or a comma list. Without it
  you get every kind.
- **`links`** holds one path per kind the place is: `fuel` is its
  `/v2/fuel/stations/{id}`, and `charging`, when the place has chargers,
  is a `/v2/charging/stations/{id}` path. A search hit already knows where
  its prices and chargers live.

A place is listed when any kind you asked for is live there: fuel and
dealers seen in the last 7 days, counted from today's date rather than from
`asOf`, and chargers that are `Operational`. A place that closes drops
out within a week even if a snapshot is late.

## One location

```bash
curl "https://api.cardog.app/v2/locations/dpz9cxmmw0" \
  -H "x-api-key: $CARDOG_API_KEY"
```

```json
{
  "location": {
    "ref": "poi:dpz9cxmmw0",
    "id": "dpz9cxmmw0",
    "kinds": ["fuel"],
    "name": "BVD Travel Centre",
    "brand": "BVD Travel Centre",
    "address": {
      "street": "2210 Stouffville Rd",
      "city": "Whitchurch-Stouffville",
      "state": "ON",
      "postalCode": "L0H 1G0",
      "country": "CA"
    },
    "location": { "latitude": 43.94214, "longitude": -79.37973 },
    "fuel": {
      "fuels": ["regular", "midgrade", "premium", "diesel"],
      "prices": [
        {
          "fuel": "regular",
          "fuelType": "fuel-type:gasoline",
          "payment": "credit",
          "centsPerLitre": 158.9,
          "currency": "CAD",
          "postedAt": "2026-10-25T22:49:41.470Z",
          "reportedBy": "member"
        }
      ],
      "amenities": ["c_store", "pay_at_pump", "restrooms", "air"],
      "openingHours": "24/7"
    },
    "charging": null,
    "sellers": null,
    "links": {
      "self": "/v2/locations/dpz9cxmmw0",
      "fuel": "/v2/fuel/stations/dpz9cxmmw0"
    }
  },
  "asOf": "2026-10-25"
}
```

The record is the search hit without `distanceKm`, plus one block per kind:

- **`fuel`** holds the fuels sold, the current prices (the same price
  records `/v2/fuel` serves), amenities and opening hours.
- **`charging`** holds `stations`, every charger at the place, each a
  `/v2/charging` station record without `source`, and `attribution`. A site with several
  networks' chargers has several stations.
- **`sellers`** holds `dealers`, every dealer that sells at the place,
  each with its `org` ref and `name`. Most rooftops hold one; an auto
  mall holds several.

A kind the place is not is `null`, never an empty block, so
`location.charging === null` means "no chargers here", not "unknown".

> **Show the attribution with charging data.** The `charging` block
> always carries `attribution`: "Charging station data (c) Open Charge Map
> contributors, ODbL 1.0 (https://openchargemap.org)". The ODbL licence
> requires it wherever station data is displayed, so render it beside the
> chargers.

## Join a location to fuel prices and chargers

The location is the hub. Each kind's group is the detail.

- **Fuel at the place.** A `fuel` location's id is its fuel station's
  id: `/v2/locations/dpz9cxmmw0` and `/v2/fuel/stations/dpz9cxmmw0` are
  the same place, and the fuel station's `ref` is the location's ref.
- **Fuel in the area.** The first three characters of
  `address.postalCode` are the place's postal area (FSA). Pass them to
  `/v2/fuel/prices?area=L0H` for the area's daily median, or `area=CA-`
  plus `address.state` for the province. That tells you whether a
  station's price is cheap for where it is.
- **Chargers.** Every `/v2/charging` station gains a `poi` field: the
  full `poi:` ref of the place it stands at, or `null` when it has none
  yet. Group chargers by `poi` to get sites, or follow it to
  `/v2/locations/{id}` to see what else is there.
- **Vehicles.** Every fuel price names its `fuelType` with the same ref a
  vehicle's decode and spec sheet carry (`fuel-type:gasoline`), so a car
  and what it costs to fill join on one key.

> **Charging keeps its ref.** A `/v2/charging` station's own `ref`,
> `id` and every other field are unchanged. `poi` is added beside them,
> so an integration that stored charging refs keeps working as it is.

For what to build on this, see
[Build with locations](https://cardog.app/docs/build-with-locations).

---

Previous: [Safety ratings](https://cardog.app/docs/safety.md) (Recalls & safety)
Next: [Fuel prices](https://cardog.app/docs/fuel.md) (Locations)
