Custom Neighborhoods
Description
Our Custom Neighborhoods endpoints allow customers to queue up custom, private geographies for processing with Local Logic’s regular Neighborhood Updates to process and add new areas. This feature allows for Custom Geographies Requests to be completed at scale, and available privately. These polygons are also used to compute various Local Logic insights such as Demographics, Location Scores, Profile Text, and Market Stats (in the United States).
This feature requires specific permissions that must be enabled. If you are interested in this feature but do not have access to use it to queue up Custom Neighborhoods, please contact support@locallogic.co.
Throughout this document, each request is referred to as a “custom geography,” as this feature can be used to define custom city boundaries, custom regions, and more beyond the usual size and scale of a “neighborhood.”
Concepts
Custom Geographies Access
Custom geographies are tied to your unique account entity across Local Logic’s product suite. We can restrict access to manage and request new custom geographies to a single set of credentials, but once they are fully processed, the ability to load widgets for and query data concerning these neighborhoods or geographies is limited to all credentials tied to the same customer.
This means any other Local Logic accounts will not be able to see, load, or retrieve data for these neighborhoods–effectively making them private and visible only to all credentials associated with you, and to Local Logic’s team to help support your use of the products.
Request Lifecycle
The following processing statuses are returned by the POST & GET endpoints outlined below to allow for tracking the completion and publishing of the custom geography for availability via Local Logic APIs + IOReports.
| Processing Status | Explanation |
|---|---|
PUBLICATION_PENDING | The initial status of the request. This indicates that the request is pending the start of the next general update. |
PUBLICATION_PROCESSING | This indicates that the request is processing (the update is in progress). This generally happens a few days to a week prior to the data being published / available. |
PUBLISHED | This indicates that the request has been completed, and the geography / custom neighborhood has been published. This means general availability of the geography for the entire account across Local Logic products – such as NHWrap SDKs and Local Insights APIs. At this point, the custom geography will have a new (or updated) geog_id which can be used to configure community pages or access insights in Local Logic APIs. |
DEPRECATION_PENDING | This means the deprecation of the geography has been queued up, pending the next general neighborhood update. |
DEPRECATION_PROCESSING | This indicates that the request to deprecate the geography is processing (the update is in progress). This generally happens a few days to a week prior to the deprecation being completed. |
DEPRECATED | This indicates that the request has been completed, and the geography / custom neighborhood has been deprecated. In order to not break any community pages using the geography, it will continue to work in our Local Logic NHWrap SDKs and in our APIs when the geog_id is provided, but it will no longer be searchable or updated going forward. |
Local Logic Neighborhood Updates
Currently, Local Logic publishes a batch of the most recent neighborhoods once per month (with a goal of supporting this twice per month in the future). These neighborhood updates compute all neighborhood data over the course of a few days from our latest sources, and ensure all data is up-to-date for all of our geographies, including any pending requests for new geographies.
Once the neighborhood update is complete, the geography request (the “custom neighborhood”) is published and becomes available with all data that can be computed for this geography: Demographics data, Location Scores, generated Profile text, and Market Statistics.
After each neighborhood update is published, it will be possible to receive an email notification confirming the completion of the update, at which point geog_id’s can be retrieved for any requests included and then community pages can be implemented, or API calls to Local Logic will begin returning information for these areas.
Boundary Data
The following limitations will be applied to the polygons defined for custom geographies:
- The centroid of the custom geography needs to fall within accessible boundaries defined for the account (which could be within a specific state, province or territory; for customers with complete access to Local Logic data, that means the centroid needs to be within Canada or the United States).
- The maximum size allowed for definition is 20,000 km2 (7,722 square miles – an area larger than Connecticut, or 4x the size of Prince Edward’s Island, Canada).
- The minimum size allowed for definition is 0.1 km2 (0.039 square miles, or roughly 24 acres).
POST /v3/geographies/custom
POST /v3/geographies/custom
This endpoint is used to submit and queue up a custom neighborhood for processing. It returns (when successful) a generated ID that can be used to track the request and retrieve a geog_id for community page implementation once the neighborhood is published.
Header
This API uses JWT token based authentication. This JWT Bearer token is what is used to populate the
Authorization header below.
Instructions on how to retrieve this token can be found at Getting Started.
| Header | Status | Description |
|---|---|---|
| Authorization | required | Your bearer token retrieved from our authorization API, ex. Bearer eyJhbGci... |
| Accept | required | The datatype to request, this API will return application/json. |
Body Parameters
| Parameter | Status | Description |
|---|---|---|
| name_en | required | The name of the neighborhood or geography in English, which will be used for generated text and for displaying the geography in Local Logic products and APIs. |
| name_fr | optional | The name of the neighborhood or geography in French, which will be used for generating French profile text and French display in Canada. Default: When not supplied, the English name will be used for French text as well for geographies in Canada. |
| boundaries | required | The boundaries of the custom geography in WKT format. These polygon representations can be generated or verified manually with free tools such as WKT Map. These are assumed to be supplied in (SRID=4326)[https://en.wikipedia.org/wiki/Spatial_reference_system#Components] (longitude, latitude). The SRID does not need to be supplied. The free WKT Map tool above supports this system automatically, but some boundaries and polygons in GIS tools may require conversion to this reference system. The polygons representing the boundaries are subject to the limitations outlined in the Polygon Limitations section above. |
| type | required | A classification of the type of geography that is both leveraged in generated text and used to determine the geography level. Use the type description that feels appropriate to you, and we’ll handle the rest! The list of accepted types are: - NEIGHBORHOOD- COMMUNITY- CITY- TOWN- VILLAGE- NEIGHBOURHOOD- RESERVE- MUNICIPALITY- TOWNSHIP- RURAL_MUNICIPALITY- MUNICIPAL_DISTRICT- BOROUGH- SECTOR- REGION- POSTAL_CITY |
Usage examples
- Python
import requests
response = requests.post(
"https://api.locallogic.co/v3/geographies/custom",
headers={
"Accept": "application/json",
"Authorization": "Bearer eyJhbGciOiJ..."},
json={
"boundaries": "POLYGON ((-73.989176 40.716704, -73.992201 40.717672, -73.993435 40.715363, -73.993971 40.714289, -73.991235 40.714493, -73.991128 40.714712, -73.990248 40.714419, -73.990216 40.71468, -73.989176 40.716704))",
"name_en": "Dime Square",
"type": "NEIGHBORHOOD"
}
)
print(response.json())
Response example
The response will return a new ID (geo_entity_id) to track the request through to the data being published and a community page being available for the custom geography, which depends on the Local Logic’s Neighborhood Update cycle.
This ID can be used to make changes to the custom geography and to get a geog_id for community page and API requests for data after the data is available.
{
"geo_entity_id": "a98f6782-fbb1-4ba2-8f40-381424990637",
"processing_status": "PUBLICATION_PENDING"
}
PATCH /v3/geographies/custom/{geo_entity_id}
This endpoint is used to update a custom geography. Custom geographies can be updated with the geo_entity_id prior to publishing (where the data becomes available in Local Logic APIs, SDK widgets, and in IOReports), or after the geography is published.
When the geography has already been published, any updates submitted via PATCH do wait until the next Local Logic Neighborhood Update in order to be reflected in Local Logic products.
PATCH /v3/geographies/custom/{geo_entity_id}
Header
This API uses JWT token based authentication. This JWT Bearer token is what is used to populate the
Authorization header below.
Instructions on how to retrieve this token can be found at Getting Started.
| Header | Status | Description |
|---|---|---|
| Authorization | required | Your bearer token retrieved from our authorization API, ex. Bearer eyJhbGci... |
| Accept | required | The datatype to request, this API will return application/json. |
Body Parameters
To call this endpoint, the same header request parameters as the POST endpoint are required. Only those body parameters which are being updated need to be included in the JSON body with the new values.
Usage examples
- Python
import requests
response = requests.patch(
"https://api.locallogic.co/v3/geographies/custom/a98f6782-fbb1-4ba2-8f40-381424990637",
headers={
"Accept": "application/json",
"Authorization": "Bearer eyJhbGciOiJ..."},
json={
"name_en": "Dimes Square"
}
)
print(response.json())
Response example
{
"geo_entity_id": "a98f6782-fbb1-4ba2-8f40-381424990637",
"processing_status": "PUBLICATION_PENDING"
}
GET /v3/geographies/custom/{geo_entity_id}
This endpoint is used to retrieve the details around the custom geography request, using its initially-returned geo_entity_id. This endpoint returns the latest details for the most recent update to the custom geography, outlined below.
GET /v3/geographies/custom/{geo_entity_id}
Header
This API uses JWT token based authentication. This JWT Bearer token is what is used to populate the
Authorization header below.
Instructions on how to retrieve this token can be found at Getting Started.
| Header | Status | Description |
|---|---|---|
| Authorization | required | Your bearer token retrieved from our authorization API, ex. Bearer eyJhbGci... |
| Accept | required | The datatype to request, this API will return application/json. |
Response Fields
| Parameter | Description |
|---|---|
| geo_entity_id | The ID of the custom geographies request. |
| name_en | The name of the neighborhood or geography in English. |
| name_fr | The name of the neighborhood or geography in French. |
| boundaries | The boundaries of the custom geography in WKT format. |
| type | A classification of the type of geography. The list of enumerated types are provided in the V3 POST body parameters table above. |
| processing_status | The status of the latest geo_entity_id request that was made. Possible values for this status are given below: - PUBLICATION_PENDING- PUBLICATION_PROCESSING- PUBLISHED- DEPRECATION_PENDING- DEPRECATION_PROCESSING- DEPRECATED |
| geog_id | The geog_id that can be used as an API parameter or as the Local Logic SDK option for instatiating NeighborhoodWrap SDKs. This is only available when the latest custom geography request has been processed and is published to production. |
| published_at | The timestamp of when the geo_entity_id was published and made available in Local Logic products. |
| updated_at | The timestamp of the most recent update to the custom geography via the POST or PATCH endpoints in this document. |
Usage examples
- Python
import requests
response = requests.get(
"https://api.locallogic.co/v3/geographies/custom/a98f6782-fbb1-4ba2-8f40-381424990637",
headers={
"Accept": "application/json",
"Authorization": "Bearer eyJhbGciOiJ..."}
)
print(response.json())
Response example
{
"boundaries": "POLYGON ((-73.989176 40.716704, -73.992201 40.717672, -73.993435 40.715363, -73.993971 40.714289, -73.991235 40.714493, -73.991128 40.714712, -73.990248 40.714419, -73.990216 40.71468, -73.989176 40.716704))",
"geo_entity_id": "a98f6782-fbb1-4ba2-8f40-381424990637",
"geog_id": null,
"processing_status": "PUBLICATION_PENDING",
"published_at": null,
"name_en": "Dimes Square",
"name_fr": "Dimes Square",
"type": "NEIGHBOURHOOD",
"updated_at": "2026-07-09T15:47:34.433625Z"
}
GET /v3/geographies/custom
This endpoint is used to retrieve the details around all submitted custom geography requests for the entire account (as custom geographies are shared across credentials). The endpoint supports search and pagination as well. Boundaries are available when querying with a specific geo_entity_id, but are NULL query looking or retrieving multiple custom geographies.
GET /v3/geographies/custom
Header
This API uses JWT token based authentication. This JWT Bearer token is what is used to populate the
Authorization header below.
Instructions on how to retrieve this token can be found at Getting Started.
| Header | Status | Description |
|---|---|---|
| Authorization | required | Your bearer token retrieved from our authorization API, ex. Bearer eyJhbGci... |
| Accept | required | The datatype to request, this API will return application/json. |
Query Parameters
| Parameter | Status | Description |
|---|---|---|
| page | optional | Which page of the results to return. Default: 1 |
| page_size | optional | The number of results to return per page, up to 100. Default: 20 |
| search | optional | A string for searching for custom neighborhood requests by name. It looks for the search string (case insensitive) within all of the available requested neighborhoods' names. Max length: 200 |
Usage examples
- Python
import requests
response = requests.get(
"https://api.locallogic.co/v3/geographies/custom",
headers={
"Accept": "application/json",
"Authorization": "Bearer eyJhbGciOiJ..."}
)
print(response.json())
Response example
{
"items": [
{
"boundaries": null,
"geo_entity_id": "437b7340-f068-4f2a-8d07-1a7d23cfdf32",
"geog_id": null,
"processing_status": "PUBLICATION_PROCESSING",
"published_at": null,
"name_en": "Test 1",
"name_fr": "Test 1",
"type": "NEIGHBOURHOOD",
"updated_at": "2026-05-21T18:20:17.978013Z"
},
{
"boundaries": null,
"geo_entity_id": "6f2b10a0-18f1-4ade-8494-7fd2e27b2898",
"geog_id": null,
"processing_status": "PUBLICATION_PROCESSING",
"published_at": null,
"name_en": "Genesee Depot",
"name_fr": "Genesee Depot",
"type": "NEIGHBORHOOD",
"updated_at": "2026-04-15T14:16:34.677505Z"
},
{
"boundaries": null,
"geo_entity_id": "0475fb33-1ef8-4db8-ab9f-2ff259ef864d",
"geog_id": "g30_dpdgequz",
"processing_status": "PUBLISHED",
"published_at": "2026-02-06T20:01:43.613672Z",
"name_en": "Zeeland",
"name_fr": "Zeeland",
"type": "POSTAL_CITY",
"updated_at": "2026-01-15T19:39:39.237494Z"
},
{
"boundaries": null,
"geo_entity_id": "f6c25e55-8f2d-4fc6-b99d-31e0c8062e9b",
"geog_id": "g30_dpjeq4v3",
"processing_status": "PUBLISHED",
"published_at": "2026-02-06T20:01:43.613672Z",
"name_en": "Zanesville",
"name_fr": "Zanesville",
"type": "POSTAL_CITY",
"updated_at": "2026-01-15T19:39:39.074043Z"
},
{
"boundaries": null,
"geo_entity_id": "3f18d4a7-6314-4f66-996f-689fc9d5cf1b",
"geog_id": "g30_dr17qmp0",
"processing_status": "PUBLISHED",
"published_at": "2026-02-06T20:01:43.613672Z",
"name_en": "York",
"name_fr": "York",
"type": "POSTAL_CITY",
"updated_at": "2026-01-15T19:39:38.823534Z"
}
],
"total": 12071,
"page": 1,
"page_size": 5
}
DELETE /v3/geographies/custom/{geo_entity_id}
This endpoint is used to deprecate the custom geography, using its geo_entity_id. This endpoint marks the geography as no longer needed and will remove it from automatic responses and calls to /v3/geographies so that by default it is no longer available in Local Logic products after the next Local Logic Neighborhood Update.
DELETE /v3/geographies/custom/{geo_entity_id}
Header
This API uses JWT token based authentication. This JWT Bearer token is what is used to populate the
Authorization header below.
Instructions on how to retrieve this token can be found at Getting Started.
| Header | Status | Description |
|---|---|---|
| Authorization | required | Your bearer token retrieved from our authorization API, ex. Bearer eyJhbGci... |
| Accept | required | The datatype to request, this API will return application/json. |
Usage examples
- Python
import requests
response = requests.delete(
"https://api.locallogic.co/v3/geographies/custom/a98f6782-fbb1-4ba2-8f40-381424990637",
headers={
"Accept": "application/json",
"Authorization": "Bearer eyJhbGciOiJ..."}
)
print(response.json())
Response example
This endpoint will return a 204 response code if successful, with no payload.
Response codes
When calling Local Logic’s API, you may receive an HTTP response code indicating an error or no data. These errors are explained below.
In general, error codes starting with “4” are due to an invalid API call and can be fixed on your end, whereas error codes starting with “5” are due to server errors (that is, problems on our end). If you receive something not described here, please contact us at support@locallogic.co.
204 - No Content
This "error code" is not an error, and it happens when we don't have the requested data for a specific location. For example, if you send a lat/lng pair to fetch scores in uninhabited parts of northern Canada, we may return an empty 204 response as we recognize the location, but don't calculate scores that remotely so there is nothing to be returned.
400 - BadRequest
This error code happens when the request inputs are incorrect. Use the detail field of the response for clarification. Example:
{
"code": "LocalLogic.API.BadRequest",
"detail": "ValidationErrors: AroundEndpoint is invalid:\n\tinclude is invalid: \"bad_input\" is not an acceptable value: \"groceries\", \"restaurants\", \"nightlife\", \"cafes\", \"shopping\", \"daycares\", \"primary_schools\", \"high_schools\""
}
401 - Unauthorized
This error code happens when your API key cannot access specific resources or locations. For example, some API keys can only access certain countries / states / provinces. Feel free to contact us for more information.
{
"code": "LocalLogic.API.Unauthorized",
"detail": "Your API KEY doesn't support this region"
}
403 - Forbidden
This error code happens when you forgot to include security credentials with your request or you are requesting a parameter that you do not have access to.
{
"message": "Forbidden"
}
404 - NotFound
This error code happens when we don’t have data for the requested location. For example, if you send a lat/lng pair for a location in Antarctica, we will return this error as we don’t have data for Antarctica (yet!).
{
"code": "LocalLogic.API.NotFound",
"detail": "No Location Scores found for this location."
}
422 - Unprocessable Entity
This error code is returned when the correct parameters have been sent however, the data they contain is not valid. For example, if you send a lat/lng pair and the latitude is invalid (ie. not in the range [-90, 90]) and/or the longitude is invalid (ie. not in the range [-180, 180]). The message returned will explain the specific issue with your parameters that makes them invalid.
{
"message": "Latitude must be within [-90, 90], Longitude must be within [-180, 180], Requires at least lat/lng pair, or geography_ids. None supplied.",
"code": "LocalLogic.API.BadRequest",
"statusCode": 422
}
429 - Too Many Requests
This error code can be returned when you need to throttle your requests. Internally, we set limits that exceed all contractual limitations that could cause this error code to be returned. If you have questions or see this error, please contact us at support@locallogic.co.
500 - ServerError
This error code means that an error occurred on our end. Feel free to retry the same request to see if the problem persists. If you received a lot of these errors, please contact us at support@locallogic.co.
{
"message": "Unexpected internal server error.",
"type": "LocalLogic.API.ServerError",
"statusCode": 500
}
502 - BadGateway
This error code means that an error came from our cloud provider. Feel free to retry the same request to see if the problem persists.
{
"message": "Internal server error"
}