# POST /v1/geocode

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

operationId: `searchAddresses`. Search and autocomplete locations.
Tag: `addresses`.

Typo-tolerant search and autocomplete of Swedish addresses from the text a person types: street-level hits until a house number is typed, then address points. To check a whole address a person entered, use `POST /v1/addresses/validate`; to turn a coordinate into an address, `POST /v1/reverse-geocode`.

## Request

`POST https://api.kartpunkt.se/v1/geocode` 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
{
  "q": "Östra Ågatan, Uppsala"
}
```

JSON body:

- `q` (string, max 200 chars, required): Free text as typed, street first, e.g. 'Östra Ågatan 12B, Uppsala' or 'ostra agatan 12 b'. Typos, å/ä/ö without diacritics and abbreviations such as sthlm and gbg are handled. Only 8 distinct words are read, a postnummer as one; past them every hit is match_type 'partial'.
- `limit` (integer 1..20, optional, default 10): The most results to answer, best first.
- `near` (object, optional): A focus point: nearer same-named streets rank first, and every result gets distance_m.
  - `lat` (number -90..90, required): Latitude, WGS84 decimal degrees, -90 to 90.
  - `lon` (number -180..180, required): Longitude, WGS84 decimal degrees, -180 to 180.
- `municipality_codes` (array of string, pattern `^\d{4}$`, 1..10 items, optional): Kommunkoder, SCB's four-digit codes, e.g. ['0380']: only hits whose municipality_code is one of them are answered. They narrow before ranking, so a small kommun's street is found past same-named streets elsewhere. Only Sweden's 290 codes are accepted, a repeated one read once. A kommun with no address in the key's dataset answers results: []. Left out: all of Sweden.
- `types` (array of "address", at least 1, optional, default ["address"]): What to look for: addresses today, from Lantmäteriet's Belägenhetsadress or, for a kp_test_ key, the synthetic dataset. Place names and POIs join later.

## Response 200

Example:

```json
{
  "results": [
    {
      "id": "street:218126d23ec3b9e4df37b27ef664b288",
      "type": "street",
      "label": "Östra Ågatan, 757 97 Uppsala",
      "street": "Östra Ågatan",
      "number": null,
      "letter": null,
      "postcode": "75797",
      "locality": "Uppsala",
      "municipality_code": "0380",
      "municipality": "Uppsala",
      "county_code": "03",
      "county": "Uppsala län",
      "district_code": "903801",
      "district": "Uppsala norra",
      "point": {
        "lat": 59.922464897740404,
        "lon": 17.582517826500723
      },
      "position_type": null,
      "match_type": "exact",
      "score": 6.596714830317912
    }
  ],
  "provenance": {
    "synthetic": true,
    "sources": [
      {
        "id": "synthetic",
        "name": "Kartpunkt synthetic test addresses",
        "licence": "CC0-1.0",
        "attribution": "Syntetiska testadresser från Kartpunkt, inte verkliga adresser.",
        "url": "https://creativecommons.org/publicdomain/zero/1.0/",
        "updated": "2026-10-13"
      }
    ]
  }
}
```

- `results` (array of [Address](https://api.kartpunkt.se/docs/shapes/Address.md)): Best matches first; street-level hits until a house number is typed.
- `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.
- [`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.

## Limits

| Limit | Synchronous |
| --- | --- |
| `limit` (at most) | 20 |
| `municipality_codes` (items) | 10 |
| Request body | 1 MB |

## Metering

With a `kp_live_` key, one live call per request; each address in the answer counts toward the plan's daily address limit.
