Skip to the live demo

Fresh Mexican postal data

Mexican postal codes, as one API.

Every postal code, every colonia, all 32 estados, in one API. One Bearer token, clean JSON, no SDK to install.

postal codes
31,880
postal codes
colonias
159,019
colonias
municipios
2,478
municipios
estados
32
estados

5 digits, leading zeros included

Try

GET /v1/postal-codes/

200 OK · cached example example

Juárez

Cuauhtémoc · Ciudad de México

{
    "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"
                }
            }
        ]
    }
}

Live API, same data and shape as the keyed endpoint. No key needed to try.

One base URL. The whole catalog.

Every endpoint returns JSON, paginated where it makes sense, with Cache-Control headers so your client can cache freely.

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

    State, municipio, city, and every colonia for a 5-digit code

    06600 → Juárez · Cuauhtémoc, CDMX

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

    Autocomplete: codes that start with a numeric prefix

    067 → 06700, 06720, 06760 …

  • GET /v1/postal-codes/search

    Find codes by estado, municipio, and/or colonia name

    Jalisco · Guadalajara · Centro → 44100

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

    Just the colonias for a code, slim payload

    64000 → Monterrey Centro, La Finca …

  • GET /v1/states · /v1/states/{id}/municipalities

    The 32 estados and the municipios in each

    09 → Cuauhtémoc, Benito Juárez …

  • GET /v1/municipalities/{id}/settlements

    Every colonia inside a municipio, paginated

    Guadalajara → Guadalajara Centro, Americana …

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

    Look up colonias by name across the country

    Polanco → 11550, 11560 …

Full request and response details in the API reference.

One relational schema behind every endpoint.

Estados, municipios, colonias and postal codes live in one relational schema with stable IDs, re-verified against the official SEPOMEX catalog every month. Ask for a code and the whole address hierarchy comes back in a single response.

GET /v1/postal-codes/06600

That is the whole integration.

Diagram: PostalKit stores the SEPOMEX catalog as a relational schema of estados, municipios, colonias and postal codes, exposes it as REST endpoints, and a GET request to /v1/postal-codes/06600 returns the estado, the municipio and the colonias as JSON.
The same catalog, three ways: the schema PostalKit stores, the endpoints it exposes, and the JSON your client receives.

Pricing

Free to start. Paid plans in Mexican pesos. Cancel anytime.

Free

$0 / mo

100 requests / month

  • No credit card
  • Community support
Start free

Starter

$149 / mo

5,000 requests / month

  • Email support
  • Multiple API tokens
Get started

Pro

Popular

$499 / mo

50,000 requests / month

  • Priority support
  • Multiple API tokens
Get started

Business

$1,499 / mo

250,000 requests / month

  • Dedicated support
  • Multiple API tokens
Get started

Prices in Mexican pesos, IVA included, billed monthly.

What counts as a request, limits and billing →

Questions worth asking before you integrate

Where the data comes from, what it costs, and what happens when you hit a limit.

Where does the postal data come from?

From the official SEPOMEX catalog, normalized into a relational schema with stable IDs and re-verified every month, so you query estados, municipios, colonias and postal codes directly.

How often is the data updated?

We check the official catalog on the first of every month. If it has changed, the whole catalog is reimported; if it has not, nothing moves — so a change in the data always means the source actually changed. The GET /v1/account/db-version endpoint returns the date of the last update, so you can check it at any time.

Do I need a credit card to start?

No. The free plan includes 100 requests a month and only asks you to verify your email address. If you upgrade later, nothing changes in your code — the same API token keeps working against the same base URL.

What are the rate limits?

Two limits apply: a burst limit of 60 requests per minute, and your plan's monthly quota. Every response carries X-RateLimit-Limit and X-RateLimit-Remaining headers so you can track usage as you go, and we email you when you reach 80% of your monthly quota. Requests that fail with a server error are not counted against it.

How is billing handled, and can I cancel?

Paid plans are billed monthly in Mexican pesos through Stripe. You can change plan, update your card or cancel from the Stripe customer portal at any time — there is no contract and no cancellation fee.

What does the catalog cover?

The whole SEPOMEX catalog: 31,880 postal codes, 159,019 colonias and 2,478 municipios across the 32 estados, each colonia with its tipo de asentamiento. Localities, streets and coordinates are not in the catalog — the endpoints for those exist but answer empty, and the reference says which ones.

Every endpoint, parameter and error code is documented in the API reference.

Drop it into your stack

Authenticate with a Bearer token, parse the JSON. That is the integration.

curl -s https://api.postalkit.mx/v1/postal-codes/06600 \
  -H "Authorization: Bearer YOUR_API_KEY"
const res = await fetch(
  "https://api.postalkit.mx/v1/postal-codes/06600",
  { headers: { Authorization: "Bearer YOUR_API_KEY" } },
);
const { data } = await res.json();
// data.settlements -> [{ name: "Roma Norte", ... }, ...]
use Illuminate\Support\Facades\Http;

$data = Http::withToken('YOUR_API_KEY')
    ->get('https://api.postalkit.mx/v1/postal-codes/06600')
    ->json('data');
import requests

data = requests.get(
    "https://api.postalkit.mx/v1/postal-codes/06600",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
).json()["data"]

Integration tutorials · Full reference · OpenAPI spec · Postman collection

Make your first call in two minutes.

Sign up, verify your email, copy your key. 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_KEY"