# POST /v1/roads/nearby

> Index: https://kartpunkt.se/llms.txt

operationId: `listRoadsNearby`. Roads near a point, with facts.
Tag: `roads`.

The nearest stretches of drivable road to a point within radius_m, nearest first, each with its road reference, distance_m and the facts asked for. Use it to say which road a point lies on and what NVDB records there; to meet a point to a profile's network, use POST /v1/snap. It costs a request and no calculation.

## Request

`POST https://api.kartpunkt.se/v1/roads/nearby` with `Authorization: Bearer $KARTPUNKT_API_KEY` and `Content-Type: application/json`, from your backend (never browser code: the key would leak, and CORS is not enabled).

Example body:

```json
{
  "point": {
    "lat": 63.720632,
    "lon": 19.345215
  },
  "radius_m": 200,
  "limit": 3,
  "facts": [
    "speed_limit",
    "surface",
    "road_owner",
    "road_class"
  ]
}
```

JSON body:

- `point` ([Point](https://api.kartpunkt.se/docs/shapes/Point.md), required)
- `radius_m` (number <= 500, optional, default 50): The straight-line search bound round the point, in metres.
- `limit` (integer 1..20, optional, default 5): The most roads to answer.
- `facts` (array of "speed_limit" | "road_owner" | "surface" | "road_class" | "network" | "gcm_type" | "municipality" | "road_name" | "road_number" | "traffic_safety_class" | "built_up" | "lit" | "separated" | "ferry" | "motorway" | "fast_road" | "speed_limit_varies" | "unlit_outside_built_up" | "traffic_volume" | "crossings_without_refuge" | "crossings_unknown_refuge" | "level_crossings" | "max_weight" | "max_axle_load" | "max_height" | "max_width" | "max_length" | "bearing_class" | "hgv_banned" | "hazmat_banned" | "hazmat_route" | "timed_restriction" | "structure" | "barriers", 0..34 items, optional): The facts to report on each road: see GET /v1/facts. None by default.
- `geometry` ("geojson" | "polyline6" | "none", optional, default "geojson"): How lines are returned: GeoJSON, an encoded polyline at 6 decimals, or not at all.
- `network` ([NetworkSelector](https://api.kartpunkt.se/docs/shapes/NetworkSelector.md), optional)

## Response 200

Example:

```json
{
  "roads": [
    {
      "ref": "0:17733@0.000000-1.000000",
      "distance_m": 0.05,
      "name": "Skolvägen",
      "number": null,
      "length_m": 600,
      "facts": {
        "speed_limit": "40",
        "surface": "paved",
        "road_owner": "municipal",
        "road_class": "7"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            19.341985,
            63.72073
          ],
          [
            19.354096,
            63.720364
          ]
        ]
      }
    },
    {
      "ref": "0:17742@0.000000-1.000000",
      "distance_m": 128.03,
      "name": "Torggatan",
      "number": null,
      "length_m": 500,
      "facts": {
        "speed_limit": "40",
        "surface": "paved",
        "road_owner": "municipal",
        "road_class": "7"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            19.341985,
            63.72073
          ],
          [
            19.348591,
            63.724127
          ]
        ]
      }
    },
    {
      "ref": "0:17732@0.000000-1.000000",
      "distance_m": 160,
      "name": "Skolvägen",
      "number": null,
      "length_m": 300,
      "facts": {
        "speed_limit": "40",
        "surface": "paved",
        "road_owner": "municipal",
        "road_class": "7"
      },
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            19.335929,
            63.720913
          ],
          [
            19.341985,
            63.72073
          ]
        ]
      }
    }
  ],
  "provenance": {
    "synthetic": true,
    "network": {
      "id": "snap_01k7exampleexampleexample0",
      "dataset": "nvdb",
      "source_date": "2026-10-13",
      "built_at": "2026-10-13T07:00:00.000Z",
      "graph": "snap_01k7exampleexampleexample0"
    },
    "sources": [
      {
        "id": "nvdb",
        "name": "Trafikverket, NVDB",
        "licence": "CC0-1.0",
        "attribution": "Vägdata från NVDB, Trafikverket, CC0 1.0",
        "url": "https://creativecommons.org/publicdomain/zero/1.0/",
        "updated": "2026-10-13"
      }
    ]
  }
}
```

- `roads` (array of object): The roads found, nearest first; empty when none lies within radius_m.
  - `ref` ([RoadRef](https://api.kartpunkt.se/docs/shapes/RoadRef.md) | null): The stretch's road reference; null on a road with no NVDB link.
  - `distance_m` (number): Straight-line metres, spheroidal, from the point sent to the nearest point of the road.
  - `name` (string | null): The road's name in NVDB; null where it has none.
  - `number` (string | null): The road's number (vägnummer): 'E6' for a europaväg, else digits; null where it has none.
  - `length_m` (number): Metres of the stretch.
  - `facts` (object): Each fact asked for, by key, with its value on this stretch.
  - `geometry` (object | string, optional): The stretch's line, in the geometry format asked; left out with geometry 'none'.
    - `type` ("LineString")
    - `coordinates` (array of array of number)
- `provenance` ([Provenance](https://api.kartpunkt.se/docs/shapes/Provenance.md))

## Errors

Every error is `{ error, message, param?, doc_url }`; `message` says what to do next. All codes: [https://api.kartpunkt.se/errors](https://api.kartpunkt.se/errors). What to do on each, with retries: [https://api.kartpunkt.se/docs/recipes/errors-and-retries.md](https://api.kartpunkt.se/docs/recipes/errors-and-retries.md).

- [`invalid_request`](https://api.kartpunkt.se/errors/invalid_request) (400): The request does not match the API schema. Fix the fields named in this message; see /openapi.json.
- [`unauthorized`](https://api.kartpunkt.se/errors/unauthorized) (401): Missing or unknown API key. Send it as 'Authorization: Bearer <key>' (or 'x-api-key'), read from the KARTPUNKT_API_KEY environment variable. The user creates a kp_test_ key on their Kartpunkt account page (https://kartpunkt.se/konto) and puts it in KARTPUNKT_API_KEY themselves; never ask them to paste a key into chat.
- [`live_access_required`](https://api.kartpunkt.se/errors/live_access_required) (403): This account is not approved for live data: kp_live_ keys are for customers under contract. Use a kp_test_ key. To ask for live access, the account holder writes to hej@kartpunkt.se, or orders a plan at https://kartpunkt.se/konto#plan.
- [`use_not_permitted`](https://api.kartpunkt.se/errors/use_not_permitted) (403): This operation would use a data source in a way its licence or approval does not allow (see GET /v1/sources). It cannot be answered for this key.
- [`network_unavailable`](https://api.kartpunkt.se/errors/network_unavailable) (404): No network snapshot matches that id or as_of. List the snapshots with GET /v1/networks and send one of their ids, or leave network out for the active one.
- [`network_not_active`](https://api.kartpunkt.se/errors/network_not_active) (409): That network snapshot is not the one served now, and answers on another snapshot are computed as jobs. Send the same input to POST /v1/jobs with this operation, then read GET /v1/jobs/{id}.
- [`profile_unavailable`](https://api.kartpunkt.se/errors/profile_unavailable) (409): This profile cannot be answered on the network snapshot asked for: it was built without the data the profile needs (see GET /v1/profiles and the snapshot's manifest at GET /v1/networks/{id}). Use another profile or a newer snapshot.
- [`network_pruned`](https://api.kartpunkt.se/errors/network_pruned) (410): That network snapshot was pruned: its tables and graph are deleted, so nothing can be answered on it again, as a job or otherwise. Leave network out to answer on the active network, and store that answer's provenance.network.id; GET /v1/networks lists the snapshots that are not pruned.
- [`too_large`](https://api.kartpunkt.se/errors/too_large) (413): Too much for one synchronous call. Send the same input to POST /v1/jobs with this operation and read the result from GET /v1/jobs/{id}, or split it.
- [`quota_exceeded`](https://api.kartpunkt.se/errors/quota_exceeded) (429): Request limit or plan quota reached (per minute, per day, or the account plan's monthly quota). Wait the number of seconds in the Retry-After header, then retry; without Retry-After, no wait helps: tell the account holder what this message says.
- [`internal_error`](https://api.kartpunkt.se/errors/internal_error) (500): Something failed on our side. Retry after a few seconds; if it keeps failing, contact hej@kartpunkt.se.
- [`live_data_unavailable`](https://api.kartpunkt.se/errors/live_data_unavailable) (503): Live data is not available yet: it opens when Kartpunkt's import of Lantmäteriet's address register completes. Use a kp_test_ key until then.
- [`routing_unavailable`](https://api.kartpunkt.se/errors/routing_unavailable) (503): Road distances and routes are not available yet: Kartpunkt's road graph from Trafikverket's NVDB has not been built. Try again later.

## Limits

| Limit | Synchronous |
| --- | --- |
| `radius_m` (at most) | 500 |
| `limit` (at most) | 20 |
| `facts` (items) | 34 |
| Request body | 1 MB |

## Metering

A request only: no calculations, no live call, no address limit.
