Guide

Join your own data

Have a spreadsheet with a column of ward codes or council names? Joining it to boundaries usually fails quietly: a code from last year's boundaries or a name shared by two places leaves a hole in the map. This guide checks every row first, fixes the ones that don't match, then joins the rest.
  1. Check the column

    Send the column to the release you want to join to. A short column can go in the URL as repeated value parameters; POST anything longer, up to 250,000 values, as JSON or as CSV with a header naming the column area, code, name or value:

    curl -X POST "https://api.ukdataatlas.com/v1/areas:validate?geography=ward&release=2024-12-uk-bgc" \
      -H "Content-Type: application/json" \
      --data '{"values":["E05000650","Bristol Central"]}'

    Not sure which release your codes come from? Leave out geography and release, and the response names the likely one. Identify a column of codes walks through it.

  2. Read the results

    Each value comes back with a status, in the order you sent them. summary.joinable is true only when every value names exactly one area of the release.

    StatusWhat it means
    validThe release holds this code.
    superseded, not-yet-current, absent-from-releaseThe code is real, but this release doesn't hold it: only older releases do, only newer ones do, or releases on both sides do.
    other-geographyThe code belongs to a different kind of area, such as a council code in a ward column.
    unknown, malformed-codeNo release holds the code, or it isn't shaped like one.
    matchedA name matched exactly, through an alias such as a Welsh name, or with a title like “City of” set aside. Names never match by prefix or similarity.
    ambiguousThe name means more than one area, and they're all listed.
    unmatchedThe name isn't in this release. The result lists other releases where it is.
  3. Fix what didn't match

    A superseded code usually means the area was redrawn. An area's history shows what it replaced, what replaced it and which other releases use its code, so you can decide whether to update the code or convert your data. Here's Birmingham's:

    curl "https://api.ukdataatlas.com/v1/areas/localAuthority/2023-05-uk-bgc-v2/E08000025/history"
    Example response200
    {
      "apiVersion": "v1",
      "atlasRelease": "sha256:5c4aa4529cbfbd5e4c844c55cddba1ef04a7bf76f3eaa085a357fff401af6d0c",
      "data": {
        "id": "localAuthority/2023-05-uk-bgc-v2/E08000025",
        "geography": "localAuthority",
        "boundaryRelease": "2023-05-uk-bgc-v2",
        "code": "E08000025",
        "name": "Birmingham",
        "relationships": [
          {
            "relation": "predecessor",
            "counterpart": {
              "id": "localAuthority/2022-12-uk-bgc-v2/E08000025",
              "geography": "localAuthority",
              "boundaryRelease": "2022-12-uk-bgc-v2",
              "code": "E08000025",
              "labels": [
                "Birmingham"
              ]
            },
            "crosswalk": {
              "id": "local-authority-2022-12-uk-bgc-v2-to-2023-05-uk-bgc-v2-official-lookup",
              "method": "official-lookup",
              "quality": "publisher-supplied",
              "weighting": {
                "status": "not-provided"
              }
            }
          }
        ],
        "lineage": [
          {
            "relation": "predecessor",
            "depth": 1,
            "from": "localAuthority/2023-05-uk-bgc-v2/E08000025",
            "counterpart": {
              "id": "localAuthority/2022-12-uk-bgc-v2/E08000025"
            }
          }
        ],
        "sameCodeReleases": [
          {
            "id": "localAuthority/2016-12-gb-bgc/E08000025",
            "geography": "localAuthority",
            "boundaryRelease": "2016-12-gb-bgc",
            "code": "E08000025",
            "name": "Birmingham",
            "status": "same-code-continuity"
          }
        ],
        "note": "Lineage follows only published historical edges and never infers a connection from a reused code. equivalent-to is published only for extent continuity. Same-code continuity only reports that the identifier appears in another release; it does not assert unchanged geometry or an exact historical equivalent."
      },
      "meta": {
        "nextCursor": null
      }
    }

    For an ambiguous name, add a parent alongside it, such as the council's code or name. It resolves only when exactly one candidate sits inside that parent.

    A code that kept its value across releases isn't proof the area kept its shape. History lists the releases that share a code, but only a published lookup says what replaced what.

  4. Join the rows

    Send each area with its value. Rows are read exactly as the check reads them, and the answer numbers each joined area with the id the release's tiles use. Nothing is stored on the server.

    curl -X POST "https://api.ukdataatlas.com/v1/boundary-releases/ward/2024-12-uk-bgc:join" \
      -H "Content-Type: application/json" \
      --data '{"rows":[{"area":"E05000650","value":12.5},{"area":"Bristol Central","value":8}]}'

    Rows that couldn't be joined are listed in unjoined with their reason. Two rows naming the same area are both left out as duplicate-area, since only you know which value was meant.

  5. Draw it

    Set each value on the release's vector tiles by its id, as in Draw a map. For a one-off map, add format=geojson to the join instead, and each joined area comes back with its shape and value.

    curl "https://api.ukdataatlas.com/v1/map-resources/ward/2024-12-uk-bgc/tiles.json"
post/areas:validateValidate a whole columnget/areas/{geography}/{release}/{code}/historyGet an area's historypost/boundary-releases/{geography}/{release}:joinJoin your rows to a release