Skip to content

Mexico ZIP code API

Mexico does not have ZIP codes. It has códigos postales — five digits, issued by SEPOMEX, and one of them covers a delivery area rather than a neighbourhood. That difference is small enough to miss and large enough to produce an address nobody can deliver to, so it is worth two minutes before you wire anything up.

This is a REST API over the whole national catalog: give it a código postal and it answers with the estado, the municipio and every colonia inside that code.

What each field is called here

Four of these translate cleanly. The fifth is the one that costs a schema migration if you find it late.

You call it Mexico calls it In the API Worth knowing
ZIP code Código postal (CP) code Five digits, leading zero included. There is no ZIP+4 and no extension of any kind.
State Estado state.name 32 of them, each with a two-digit INEGI code returned alongside the name.
County Municipio municipality.name The level below the estado. Ciudad de México calls its own alcaldías; the API returns them in this same field.
City Ciudad city.name Optional, frequently null, and not a level of government. Display it; never join on it.
Neighborhood Colonia settlements[].name Required on every Mexican address, and the field with no equivalent in a US or European form. One postal code usually holds several.

The colonia is the row to read twice. It is not a free-text neighbourhood label — it is a value from a list, it belongs to a postal code, and a Mexican address without one is incomplete.

One request, start to finish

06600 is a real code in the middle of Mexico City. One GET, a bearer token, no SDK.

Request

Terminal
curl -s https://api.postalkit.mx/v1/postal-codes/06600 -H "Authorization: Bearer YOUR_API_KEY"

Response

200 Success
{
  "data": {
    "id": 384,
    "code": "06600",
    "state":        { "id": 1, "name": "Ciudad de México", "code": "09" },
    "municipality": { "id": 6, "name": "Cuauhtémoc", "code": "015" },
    "city":         { "id": 1, "name": "Ciudad de México" },
    "settlements": [
      {
        "id": 532,
        "name": "Juárez",
        "zone": "Urbano",
        "settlement_type": { "id": 1, "name": "Colonia" }
      }
    ]
  }
}

settlements is an array because it has to be. This code happens to hold one colonia; most hold several.

Three things an imported address form gets wrong

  • Treating the postal code as a neighbourhood.

    A ZIP+4 narrows to a block. A código postal does not narrow to anything below itself — most of them cover several colonias, and the customer has to pick one. That is the single most expensive assumption to carry into a Mexican checkout. The counted version of that, with the catalog behind it.

  • Storing the code as a number.

    Mexican postal codes start at 01000. An integer column drops the leading zero and turns a valid code into a four-digit one, and it fails on Mexico City first — which is exactly where the test data usually is not.

  • Matching estados by name.

    The catalog writes some estados out in full — the official name is not always the one on your dropdown. Match on the two-digit INEGI code that comes back beside the name, and the problem disappears.

The endpoints for this job

Four calls cover almost every address form. Parameters, fields and errors are in the reference.

  • GET /v1/postal-codes/{code}

    One postal code to its estado, municipio, ciudad and every colonia inside it.

  • GET /v1/postal-codes?q={prefix}

    Every code starting with those digits — a type-ahead over the national catalog.

  • GET /v1/postal-codes/{code}/settlements

    Just the colonias, for populating the field a form has no other way to fill.

  • GET /v1/settlements?q={name}

    The other direction: a colonia name to the postal codes it appears in.

Postal code endpoint reference — every parameter and every error, plus an honest note on the endpoints that have no data behind them yet.

Reading on

Every Mexican postal code, one endpoint.

Estados, municipios and colonias over the full national catalog. The free tier is 100 requests a month, no card required.

curl -s https://api.postalkit.mx/v1/postal-codes/06600 -H "Authorization: Bearer YOUR_API_KEY"