POST /geo/resolve
Finds the Lowest Common Ancestor (LCA) of a list of place names — the most specific geographic region that contains all of them.
Costs 1 credit per request.
Request
Section titled “Request”POST /geo/resolveAuthorization: Bearer gaz_<api-key>Content-Type: text/plainX-Min-Score: 0.6 (optional)Body: newline-separated list of place names (plain text).
CuiabáSinopRondonópolisHeaders
Section titled “Headers”| Header | Type | Default | Description |
|---|---|---|---|
Authorization | string | required | Bearer gaz_<api-key> |
X-Min-Score | float | 0.6 | Minimum similarity score (0.0–1.0) for a name to be considered resolved. Names below this threshold are skipped and counted in unresolved. |
Response
Section titled “Response”{ "region": "Mato Grosso", "type": "state", "region_id": 3457419, "unresolved": 0, "outliers": 2, "total": 3, "locationIds": [ { "name": "Cuiabá", "id": 3664728 }, { "name": "Sinop", "id": 3449581 }, { "name": "Rondonópolis", "id": 3451638 } ]}Fields
Section titled “Fields”| Field | Type | Description |
|---|---|---|
region | string | Name of the common ancestor region |
type | string | world | country | state | city |
region_id | integer | Place ID — use with GET /geo/place/{id} |
unresolved | integer | Number of input names that couldn’t be matched above X-Min-Score |
outliers | integer | Count of resolved inputs whose best match fell outside the resolved region. These are excluded from the LCA using the 85% coverage rule. Non-zero values indicate possible data gaps; interpret their locationIds entries with care. |
total | integer | Total number of input names sent |
locationIds | array | Each resolved input mapped to its best-matching place within the common region. Each entry is { name, id } where name is the canonical place name and id is the place ID. Inputs that didn’t match above X-Min-Score are omitted. When multiple places match an input, the nearest descendant of the common region is preferred. |
Unresolved responses
Section titled “Unresolved responses”At least 90% of the input names must resolve (match above X-Min-Score) before an LCA is computed — an LCA over a small resolved subset isn’t trustworthy. If fewer resolve, the endpoint returns 200 with an explicit unresolved object instead of a region:
{ "region": null, "resolved": false, "resolvedCount": 7, "total": 10, "requiredRatio": 0.9, "message": "Too few places resolved"}| Field | Type | Description |
|---|---|---|
region | null | Always null here — no LCA was computed |
resolved | boolean | false — check this field to detect the unresolved case |
resolvedCount | integer | How many inputs matched above X-Min-Score |
total | integer | Total number of input names sent |
requiredRatio | float | The minimum resolvedCount / total required (default 0.9) |
Context-aware disambiguation
Section titled “Context-aware disambiguation”When a name is ambiguous (e.g. SC matches both South Carolina and Santa Catarina with an identical score), the resolver breaks the tie using the context of the other inputs. It first finds the most specific region that the batch as a whole agrees on, then prefers the candidate that falls inside it.
So a batch of US state codes:
ohndokorpariscresolves to the United States — pa and sc are pulled toward Pennsylvania and South Carolina by the surrounding context, rather than matching Pará and Santa Catarina and forcing the result up to world. The same batch of Brazilian state codes (sc, pa, mt, go) resolves to Brazil for the mirror-image reason.
A candidate only contributes to the shared context if the place is substantial (a real city, state, or country) — so a coincidental same-named hamlet can’t hijack the result. A genuinely global batch like Berlin, Paris, London still resolves to its true common ancestor (Europe / world) instead of over-narrowing.
Outlier tolerance
Section titled “Outlier tolerance”The resolver uses up to 3 passes. Inputs whose best match is ambiguous are re-ranked on each pass to prefer candidates inside the emerging region. If ≥85% of inputs agree on a region, the remaining ≤15% are treated as outliers — they don’t prevent the LCA from resolving, but their locationIds entries may be id: -1.
Error Responses
Section titled “Error Responses”| Status | Description |
|---|---|
401 | Missing or invalid API key |
402 | Insufficient credits |
404 | No common region found (all inputs resolved to places with no common ancestor, or all unresolved) |
422 | Empty request body |
429 | Rate limit exceeded |
404 body
Section titled “404 body”{ "detail": { "message": "No common region found", "unresolved": 1, "total": 3 }}Examples
Section titled “Examples”Basic usage
Section titled “Basic usage”curl -X POST https://api.hlgsws.xyz/geo/resolve \ -H "Authorization: Bearer gaz_..." \ -H "Content-Type: text/plain" \ --data "ParisLyonMarseille"{ "region": "France", "type": "country", "region_id": 3017382, "unresolved": 0, "total": 3, "locationIds": [ { "name": "Paris", "id": 2988507 }, { "name": "Lyon", "id": 2996944 }, { "name": "Marseille", "id": 2995469 } ]}With a stricter similarity threshold
Section titled “With a stricter similarity threshold”Raise X-Min-Score to reject ambiguous matches:
curl -X POST https://api.hlgsws.xyz/geo/resolve \ -H "Authorization: Bearer gaz_..." \ -H "X-Min-Score: 0.8" \ -H "Content-Type: text/plain" \ --data "São PauloCampinas"Interpreting unresolved
Section titled “Interpreting unresolved”A non-zero unresolved count means some inputs were skipped. The LCA was computed only over the resolved subset. If confidence matters, check:
confidence = (total - unresolved) / total