Offendersearch
Map API Reference

Clusters & markers

Field tables for every object in a response, plus the GeoJSON form.

Base URL https://api.offendersearch.app

What a view can contain

ArrayObjectWhen
clustersA cluster: a count for a grid cell.Zoom 3–12, and closer views that are too dense for pins.
markersA pin: one person at one address.Zoom 13–14, with no name.
markersA named pin.Zoom 15+.
markersA many-people pin: several people at one address.From zoom 13.
areasAn approximate-area pin: people known only to an area.From zoom 13.

Cluster

FieldMeaning
idAn id for the cluster. Use it as a key when you redraw.
lat, lngWhere to draw it.
countPeople in the cluster.
bboxwest,south,east,north: the extent of the people in the cluster.
expansionZoomFit the map to bbox at this zoom and the cluster comes apart: into smaller clusters, pins, or one many-people pin.
breakdownThe same four numbers as the view’s breakdown, for this cluster.

A cluster never traps the user. People who share one address never split, so at its expansionZoom such a cluster becomes one pin with a count and a groupId.

Pin

At zoom 13–14 a pin is a position and nothing that identifies anyone.

mode: pins
"mode": "pins",
"markers": [
  {
    "id": "mk_Qa8…",
    "lat": 39.96123, "lng": -82.99881,
    "precision": "street",
    "addressType": "home"
  }
]
FieldMeaning
idThe marker id, mk_…. Pass it to the records route.
lat, lngThe registered address.
precisionstreet for an exact street address.
addressTypehome, work, school or other.
distanceMilesOnly with a radius request: the distance from the centre.

A person with two mapped addresses, such as home and work, has two pins. total counts that person once.

Named pin

From zoom 15 each pin also carries a label and basic fields.

mode: markers
"mode": "markers",
"markers": [
  {
    "id": "mk_Zb3…",
    "lat": 39.96123, "lng": -82.99881,
    "precision": "street",
    "addressType": "home",
    "label": "Sample J. Tester",
    "housingStatus": "housed",
    "hasPhoto": true,
    "registryState": "OH"
  },
  {
    "id": null,
    "lat": 39.9678, "lng": -83.0042,
    "precision": "street",
    "count": 12,
    "groupId": "mg_8Uo…",
    "members": [
      {
        "id": "mk_…",
        "addressType": "home",
        "label": "Sample S. Demo",
        "housingStatus": null,
        "hasPhoto": false
      }
    ]
  }
],
"areas": [
  {
    "lat": 39.969, "lng": -83.0114,
    "count": 9,
    "precision": "zip",
    "label": "43215",
    "groupId": "mg_X1G…"
  }
]
FieldMeaning
labelThe first initial and last name, such as “J. Smith”.
housingStatushoused, homeless or incarcerated. null when the registry does not say. null does not mean housed.
hasPhototrue when the record has a photo.
registryStateThe state whose registry lists the person.

These fields are enough for a popup. They cost nothing beyond the map request that returned them.

Many-people pin

Several people at one address are one pin. It has id: null, a count and a groupId.

FieldMeaning
idAlways null. There is no single record behind this pin.
countPeople at the address.
groupIdThe group id, mg_…. Pass it to the groups route.
membersThe people, inline, when there are 10 or fewer and the zoom is 15 or closer. Otherwise use the groups route.

Approximate-area pin

Some people are known only to the middle of a ZIP, a city or a county. People in custody and people without a fixed address are here too. They come back in areas, never in markers, so they are never drawn as an exact pin.

FieldMeaning
lat, lngThe middle of the area.
countPeople in it.
precisionzip, city or county.
labelThe name of the area, such as a ZIP code.
groupIdPass it to the groups route for the people.

Draw an area pin so it does not look like an address: a dashed circle, a different colour, and the word “approximate”.

The groups route

GET /v1/map/groups/{groupId} lists the people behind a many-people pin or an approximate-area pin. Each page is one map request.

GET /v1/map/groups/{groupId}
curl "https://api.offendersearch.app/v1/map/groups/mg_8Uo…?page=1&perPage=50" \
  -H "X-API-Key: $OFFENDERSEARCH_KEY"
200 OK
{
  "total": 12,
  "page": 1,
  "perPage": 50,
  "totalPages": 1,
  "kind": "address",
  "named": true,
  "members": [
    {
      "id": "mk_…",
      "addressType": "home",
      "label": "Sample S. Demo",
      "housingStatus": null,
      "hasPhoto": false
    }
  ],
  "notice": "A pin shows a registered address, not a person's current location."
}
FieldMeaning
page, perPageQuery parameters. page starts at 1. perPage is 1 to 100; the default is 50.
total, totalPagesPeople in the group, and pages at this perPage.
kindaddress for a many-people pin, area for an approximate-area pin.
namedtrue when the group id came from a view at zoom 15 or closer. Members carry label only then.
members[].idA marker id. Pass it to the records route.

The breakdown

breakdown is on the view and on every cluster. Its four numbers are not a split of the total: one person can count in two of them.

FieldCounts
streetPeople with an exact street address.
housedPeople the registry lists as housed.
homelessPeople the registry lists as homeless.
incarceratedPeople the registry lists as in custody.

People whose registry does not state a housing status are in total and in none of the three housing numbers.

Unplaced people

unplaced counts people in the states the view touches who have no mappable address. They are on a registry, and they are not on the map.

unplaced
"unplaced": {"count": 96, "states": ["OH"]}

Say so next to the map, so a short list of pins is not read as the whole list. For example: “96 more people are registered in Ohio with no mappable address. Search by name to find them.” The count is for whole states, not for the box.

GeoJSON

With format=geojson the answer is a FeatureCollection of points, with content type application/geo+json. It can go straight into a map library’s GeoJSON source.

format=geojson
{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {"type": "Point", "coordinates": [-82.9988, 39.9612]},
      "properties": {
        "cluster": true,
        "cluster_id": "c10_1103_1551",
        "point_count": 412,
        "point_count_abbreviated": "412",
        "expansion_zoom": 11,
        "bbox": [-83.06, 39.91, -82.97, 39.98],
        "breakdown_street": 412,
        "breakdown_housed": 201,
        "breakdown_homeless": 77,
        "breakdown_incarcerated": 0
      }
    }
  ],
  "meta": {"mode": "clusters", "zoom": 10, "total": 508}
}
FeatureProperties
Clustercluster: true, cluster_id, point_count, point_count_abbreviated, expansion_zoom, bbox, and breakdown_street, breakdown_housed, breakdown_homeless, breakdown_incarcerated.
PinThe pin’s fields, plus kind: "marker".
Many-people pinThe pin’s fields, plus kind: "group".
Approximate areaThe area’s fields, plus kind: "area".

Everything that is not a feature, such as mode, zoom, total, unplaced and notice, is under meta. For a heat map, use the cluster features with point_count as the weight.

Product overview