Skip to content

List every postal code in a Mexican estado or municipio

Some questions are not about one address. Which codes does this courier cover? Which fall inside that sales territory? What goes in the dropdown once the customer has picked Jalisco? Those are region queries, and calling a single-code lookup in a loop is the wrong shape for them.

Three ways to ask for a region

They differ in what you happen to be holding when you ask, which is usually the deciding factor.

  • You have names, from a form or a spreadsheet.

    The geographic search takes an estado, and optionally a municipio and a colonia, as text. It is the one to reach for when your input came from a human.

  • You have an identifier, from an earlier call.

    If you already walked the hierarchy and hold a state or municipio id, ask for its postal codes directly. No name matching, no ambiguity, and it pages cleanly.

  • You have the first few digits.

    Prefix search exists for the type-ahead case: somebody is part way through typing a code and you want the plausible completions.

Searching by estado, municipio and colonia

The estado is required; the rest narrow it. Matching is fuzzy by default, which is what you want when the text came from a person, and exact=true turns that off when it did not.

Request

curl
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.postalkit.mx/v1/postal-codes/search?state=Jalisco&municipality=Guadalajara&colonia=Centro"

Response

200 Success (paginated)
{
  "data": [
    {
      "id": 3,
      "code": "44100",
      "state": { "id": 14, "name": "Jalisco", "code": "14" },
      "municipality": { "id": 39, "name": "Guadalajara", "code": "039" },
      "city": { "id": 1, "name": "Guadalajara" },
      "settlements": [
        { "id": 5, "name": "Guadalajara Centro", "zone": "Urbano", "settlement_type": { "id": 1, "name": "Colonia" } }
      ]
    }
  ],
  "links": { "first": "...", "last": "...", "prev": null, "next": null },
  "meta": { "current_page": 1, "total": 1, "per_page": 20 }
}

Leave the estado off and you get a 422 rather than the whole country, which is deliberate: an unbounded scan of the catalog is never the query anyone meant to write.

Listing by identifier instead

When the region came from the catalog rather than from a person, address it by id. This is the call behind a cascading dropdown, and behind any job that walks the country a municipio at a time.

Request

curl
curl -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.postalkit.mx/v1/states/2/postal-codes

Response

200 Success (paginated)
{
  "data": [
    {
      "id": 1,
      "code": "20000",
      "state": { "id": 2, "name": "Aguascalientes", "code": "01" },
      "municipality": { "id": 1, "name": "Aguascalientes", "code": "001" },
      "city": { "id": 1, "name": "Aguascalientes" }
    }
  ],
  "links": { "first": "...", "last": "...", "prev": null, "next": "..." },
  "meta": { "current_page": 1, "total": 100, "per_page": 20 }
}

The same call exists one level down, at /v1/municipalities/{id}/postal-codes, for when a whole estado is more than you wanted.

Completing a half-typed code

Two digits or more, ordered by code, and it is the only one of the three that answers usefully while somebody is still typing.

Request

curl
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.postalkit.mx/v1/postal-codes?q=066&page=1"

Before you ship it

Region queries are where quota goes

  • Twenty rows a page, on every one of these.

    A large estado is a lot of pages, and every page is a request against your monthly allowance. Read meta.total first and decide whether you actually want all of it before you start the loop.

  • Pull a region once, not per visitor.

    The set of postal codes in a municipio does not change between two page loads. Fetch it on a schedule, store it, and serve your own dropdown from your own database.

  • Fuzzy matching is on unless you turn it off.

    That is right for a search box and wrong for a nightly import, where a near-miss quietly writes the wrong municipio onto a row. Pass exact=true for machine input.

  • Every response tells you what is left.

    X-RateLimit-Limit and X-RateLimit-Remaining carry your monthly allowance and what remains of it. A bulk job that watches them stops on its own terms rather than mid-import.

Pull a region and see how big it is.

100 requests a month, free, no card. Enough to size the job before you commit to a plan.

curl -s "https://api.postalkit.mx/v1/postal-codes/search?state=Jalisco" -H "Authorization: Bearer YOUR_API_KEY"