Open Application Platform Docs

Batch geocoding

Geocode many addresses in one call, billed per thousand points.

geo.batch Stable point_1k

How to call it

REST

POST /v1/geo/forward/batch

POST /v1/geo/reverse/batch

GraphQL

query openGeoBatch

MCP

open_geo_batch

Geocode many addresses in one call. Billed per thousand points on what was attempted, not on what matched — a miss still costs a provider lookup.

Request schema

Generated from the same validation rules the endpoint runs, so a field cannot be documented without being validated.

POST /v1/geo/forward/batch

{
    "type": "object",
    "properties": {
        "addresses": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
                "type": "object",
                "properties": {
                    "address1": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 255
                    },
                    "address2": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 255
                    },
                    "city": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 120
                    },
                    "country": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 120
                    },
                    "postcode": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 32
                    },
                    "province": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 120
                    }
                }
            }
        }
    },
    "additionalProperties": false,
    "required": [
        "addresses"
    ]
}

Request example

{
    "addresses": [
        {
            "address1": "1000 Rue De La Gauchetière O",
            "city": "Montreal",
            "country": "CA"
        },
        {
            "address1": "290 Bremner Blvd",
            "city": "Toronto",
            "country": "CA"
        }
    ]
}

POST /v1/geo/reverse/batch

{
    "type": "object",
    "properties": {
        "language": {
            "type": [
                "string",
                "null"
            ],
            "maxLength": 8
        },
        "points": {
            "type": "array",
            "minItems": 1,
            "maxItems": 1000,
            "items": {
                "type": "object",
                "properties": {
                    "lat": {
                        "type": "number",
                        "minimum": -90,
                        "maximum": 90
                    },
                    "lng": {
                        "type": "number",
                        "minimum": -180,
                        "maximum": 180
                    }
                },
                "required": [
                    "lat",
                    "lng"
                ]
            }
        }
    },
    "additionalProperties": false,
    "required": [
        "points"
    ]
}

Request example

{
    "points": [
        {
            "lat": 45.4985,
            "lng": -73.5664
        },
        {
            "lat": 43.6426,
            "lng": -79.3871
        }
    ]
}

Response

What a successful call returns: the schema of `data` and `meta`, with a description of each field, followed by an example response from a real call.

POST /v1/geo/forward/batch

Response schema

{
    "description": "One result per address, in request order. Billed per thousand addresses sent, matched or not.",
    "data": {
        "type": "object",
        "properties": {
            "results": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "index": {
                            "type": "integer",
                            "description": "Position of the address in the request, from 0."
                        },
                        "matched": {
                            "type": "boolean",
                            "description": "Whether a location was found. A miss is not an error and is still billed."
                        },
                        "reason": {
                            "type": "string",
                            "description": "Why nothing matched. Present only when `matched` is false."
                        },
                        "location": {
                            "type": "object",
                            "properties": {
                                "lat": {
                                    "type": "number",
                                    "description": "Latitude, WGS84."
                                },
                                "lng": {
                                    "type": "number",
                                    "description": "Longitude, WGS84."
                                }
                            },
                            "required": [
                                "lat",
                                "lng"
                            ]
                        },
                        "address": {
                            "type": "object",
                            "description": "The matched address as the provider parsed it. Only the parts the provider returned are present; may be empty.",
                            "properties": {
                                "number": {
                                    "type": "string",
                                    "description": "House number."
                                },
                                "street": {
                                    "type": "string",
                                    "description": "Street name, normalized."
                                },
                                "city": {
                                    "type": "string"
                                },
                                "province": {
                                    "type": "string",
                                    "description": "Province or state."
                                },
                                "country": {
                                    "type": "string",
                                    "description": "ISO 3166-1 alpha-2."
                                },
                                "postcode": {
                                    "type": "string"
                                },
                                "unit": {
                                    "type": "string",
                                    "description": "Unit, suite or apartment."
                                }
                            }
                        },
                        "confidence": {
                            "type": [
                                "number",
                                "null"
                            ],
                            "description": "0-1, as the provider reports it; null when the provider gives none."
                        },
                        "provider": {
                            "type": "string",
                            "description": "The provider that answered (see GET /v1/geo/coverage)."
                        }
                    }
                },
                "description": "One result per address, in request order."
            },
            "matched": {
                "type": "integer",
                "description": "Results with `matched: true`."
            },
            "total": {
                "type": "integer",
                "description": "Addresses sent."
            }
        }
    }
}

Response example

{
    "request_id": "req_01k8zq3m5n7p9r1t3v5x7z9b2d",
    "capability": "geo.batch",
    "billing": {
        "unit": "point_1k",
        "quantity": 0.002,
        "counted": true
    },
    "data": {
        "results": [
            {
                "index": 0,
                "matched": true,
                "location": {
                    "lat": 45.4981126,
                    "lng": -73.56598129999999
                },
                "address": {},
                "confidence": null,
                "provider": "google"
            },
            {
                "index": 1,
                "matched": true,
                "location": {
                    "lat": 43.642596,
                    "lng": -79.387089
                },
                "address": {
                    "number": "290",
                    "street": "bremner blvd",
                    "city": "Toronto",
                    "country": "CA"
                },
                "confidence": 1,
                "provider": "internal"
            }
        ],
        "matched": 2,
        "total": 2
    }
}

POST /v1/geo/reverse/batch

Response schema

{
    "description": "One address per point, in request order. Billed per thousand points sent.",
    "data": {
        "type": "object",
        "properties": {
            "results": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "index": {
                            "type": "integer",
                            "description": "Position of the point in the request, from 0."
                        },
                        "matched": {
                            "type": "boolean",
                            "description": "Whether an address was found."
                        },
                        "reason": {
                            "type": "string",
                            "description": "Why nothing matched. Present only when `matched` is false."
                        },
                        "address": {
                            "type": "object",
                            "properties": {
                                "address_1": {
                                    "type": "string",
                                    "description": "Street address."
                                },
                                "address_2": {
                                    "type": "string",
                                    "description": "Unit, suite or floor; empty when none."
                                },
                                "city": {
                                    "type": "string"
                                },
                                "province": {
                                    "type": "string",
                                    "description": "Province or state, as the provider names it."
                                },
                                "country": {
                                    "type": "string",
                                    "description": "Country code, as the provider returns it."
                                },
                                "postcode": {
                                    "type": "string"
                                },
                                "full_address": {
                                    "type": "string",
                                    "description": "The whole address on one line."
                                },
                                "country_code": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The country as an ISO 3166-1 alpha-2 code, the form forward geocoding answers with. Null when the provider named no country that maps to a code."
                                },
                                "province_code": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The province or state as its short code (QC, ON, NY), the form forward geocoding answers with; upper-cased as given when the country has no list of codes. Null when the provider named none."
                                }
                            }
                        },
                        "provider": {
                            "type": "string",
                            "description": "The provider that answered."
                        }
                    }
                }
            },
            "matched": {
                "type": "integer",
                "description": "Results with `matched: true`."
            },
            "total": {
                "type": "integer",
                "description": "Points sent."
            }
        }
    }
}

Response example

{
    "request_id": "req_01k8zq3m5n7p9r1t3v5x7z9b2d",
    "capability": "geo.batch",
    "billing": {
        "unit": "point_1k",
        "quantity": 0.002,
        "counted": true
    },
    "data": {
        "results": [
            {
                "index": 0,
                "matched": true,
                "address": {
                    "address_1": "1000 Rue de La Gauchetière Ouest",
                    "address_2": "",
                    "city": "Montreal",
                    "province": "Quebec",
                    "country": "CAN",
                    "postcode": "H3B 4W5",
                    "full_address": "1000 Rue de La Gauchetière Ouest, Montreal, QC, Canada",
                    "country_code": "CA",
                    "province_code": "QC"
                },
                "provider": "internal"
            },
            {
                "index": 1,
                "matched": true,
                "address": {
                    "address_1": "290 Bremner Boulevard",
                    "address_2": "",
                    "city": "Toronto",
                    "province": "Ontario",
                    "country": "CAN",
                    "postcode": "M5V 3L9",
                    "full_address": "CN Tower, Toronto, ON, Canada",
                    "country_code": "CA",
                    "province_code": "ON"
                },
                "provider": "internal"
            }
        ],
        "matched": 2,
        "total": 2
    }
}

What it costs

Thousands of points, charged fractionally.

Every billable response carries a billing block with the unit, the quantity and how the quantity was derived.

Errors it can return

Status Code Description
401 TOKEN_INVALID Unknown or revoked API token.
401 TOKEN_MISSING No API token. Send Authorization: Bearer <your token>.
402 QUOTA_EXHAUSTED The included allowance for this capability is used up for the current period.
403 CAPABILITY_NOT_ENABLED This capability is not enabled for your account. See :doc to enable it.
403 CAPABILITY_NOT_GRANTED_TO_KEY Your account has this capability, but this API key was not granted it.
403 OPEN_API_DISABLED Open Platform access is not enabled for this account.
422 VALIDATION_FAILED The request failed validation. See details.
429 RATE_LIMITED Too many requests. Please retry after the indicated delay.
500 INTERNAL_ERROR An unexpected error occurred. Quote the request_id when contacting support.
502 ENGINE_UNAVAILABLE The routing engine is temporarily unreachable. Please retry.