Documentación de la API - Endpoints y Ejemplos

Buscar códigos postales por estado

Country Data API proporciona información detallada sobre +200 países diferentes

Descripción general

El endpoint /v1/zipcodes/state devuelve todos los códigos postales de un estado o provincia específico. Es ideal para aplicaciones que necesitan poblar formularios de direcciones o validar códigos postales dentro de un estado específico.

Endpoint

GET https://api.countrydataapi.com/v1/zipcodes/state

Autenticación

Incluye tu clave API como parámetro de consulta:

?apikey=tu-clave-api

Tu clave API es como una contraseña, mantenla segura. Obtén tu clave desde el panel de cuenta.

Parámetros de consulta

Parámetro Tipo Requerido Descripción
apikey string Tu clave de autenticación API
state string Nombre del estado o ID del estado que se busca
lang string No Código de idioma para la respuesta (predeterminado: en)
limitToken number No Máximo de tokens a gastar en esta petición (predeterminado: 1000)

Idiomas soportados

  • en - Inglés (predeterminado)
  • es - Español
  • pt - Portugués
  • fr - Francés
  • de - Alemán
  • it - Italiano

Uso de tokens

Cada código postal devuelto costará 1 token.

Formato de respuesta

Respuesta exitosa

[
  {
    "id": "8dd25479-067a-43b0-ac4a-8e7faf2bcad",
    "name": "California",
    "postal_code": [
      "90001",
      "90002",
      "90003",
      "90004",
      "90005"
    ]
  }
]

Campos de respuesta

Campo Tipo Descripción
id string Identificador único del estado
name string Nombre del estado/provincia en el idioma solicitado
postal_code array Array de códigos postales para este estado

Respuesta de error

{
  "success": false,
  "error": {
    "code": "MISSING_PARAMETER",
    "message": "Required parameter 'state' is missing"
  }
}

Consulta la documentación de códigos de error para todos los códigos de error posibles.

Ejemplos de código

cURL

# Buscar por nombre de estado
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/state?apikey=tu-clave-api&state=California&lang=en"

# Buscar por ID de estado
curl -X GET "https://api.countrydataapi.com/v1/zipcodes/state?apikey=tu-clave-api&state=66c7a6cae4bda21f4ab11d1a&lang=en"

JavaScript (Fetch)

const API_KEY = 'tu-clave-api';
const BASE_URL = 'https://api.countrydataapi.com/v1';

async function getZipcodesByState(state, limitToken = 1000) {
  try {
    const params = new URLSearchParams({
      apikey: API_KEY,
      state: state,
      lang: 'en',
      limitToken: limitToken.toString()
    });

    const response = await fetch(`${BASE_URL}/zipcodes/state?${params}`);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error fetching zipcodes by state:', error);
    throw error;
  }
}

// Uso
const californiaZipcodes = await getZipcodesByState('California');
console.log(californiaZipcodes);

// O por ID de estado
const texasZipcodes = await getZipcodesByState('66c7a6cbe4bda21f4ab11f55');
console.log(texasZipcodes);

JavaScript (Axios)

import axios from 'axios';

const API_KEY = 'tu-clave-api';
const BASE_URL = 'https://api.countrydataapi.com/v1';

async function getZipcodesByState(state, limitToken = 1000) {
  try {
    const response = await axios.get(`${BASE_URL}/zipcodes/state`, {
      params: {
        apikey: API_KEY,
        state: state,
        lang: 'en',
        limitToken: limitToken
      }
    });

    return response.data;
  } catch (error) {
    if (error.response) {
      console.error('API Error:', error.response.data);
    } else {
      console.error('Network Error:', error.message);
    }
    throw error;
  }
}

// Uso
const zipcodes = await getZipcodesByState('California');
console.log(`Encontrados ${zipcodes[0]?.postal_code?.length || 0} códigos postales`);

React

import { useState, useEffect } from 'react';

const API_KEY = 'tu-clave-api';
const BASE_URL = 'https://api.countrydataapi.com/v1';

function useStateZipcodes(stateName) {
  const [zipcodes, setZipcodes] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    if (!stateName) {
      setZipcodes([]);
      return;
    }

    async function fetchZipcodes() {
      try {
        setLoading(true);
        setError(null);

        const params = new URLSearchParams({
          apikey: API_KEY,
          state: stateName,
          lang: 'en'
        });

        const response = await fetch(`${BASE_URL}/zipcodes/state?${params}`);

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        const data = await response.json();
        setZipcodes(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchZipcodes();
  }, [stateName]);

  return { zipcodes, loading, error };
}

// Ejemplo de componente
function StateZipcodeSearch() {
  const [selectedState, setSelectedState] = useState('');
  const { zipcodes, loading, error } = useStateZipcodes(selectedState);

  const states = ['California', 'Texas', 'New York', 'Florida'];

  return (
    <div>
      <h2>Buscar Códigos Postales por Estado</h2>

      <select
        value={selectedState}
        onChange={(e) => setSelectedState(e.target.value)}
      >
        <option value="">Selecciona un estado...</option>
        {states.map(state => (
          <option key={state} value={state}>{state}</option>
        ))}
      </select>

      {loading && <p>Cargando códigos postales...</p>}
      {error && <p style={{ color: 'red' }}>Error: {error}</p>}

      {zipcodes.length > 0 && (
        <div>
          <h3>{zipcodes[0].name}</h3>
          <p>Total de códigos postales: {zipcodes[0].postal_code.length}</p>
          <div style={{ maxHeight: '200px', overflow: 'auto' }}>
            {zipcodes[0].postal_code.slice(0, 100).map(code => (
              <span key={code} style={{ margin: '2px', display: 'inline-block' }}>
                {code}
              </span>
            ))}
            {zipcodes[0].postal_code.length > 100 && (
              <span>...y {zipcodes[0].postal_code.length - 100} más</span>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

export default StateZipcodeSearch;

Vue 3

<script setup>
import { ref, watch, computed } from 'vue';

const API_KEY = 'tu-clave-api';
const BASE_URL = 'https://api.countrydataapi.com/v1';

const selectedState = ref('');
const zipcodes = ref([]);
const loading = ref(false);
const error = ref(null);

const states = ['California', 'Texas', 'New York', 'Florida'];

const postalCodes = computed(() => {
  return zipcodes.value[0]?.postal_code || [];
});

watch(selectedState, async (newState) => {
  if (!newState) {
    zipcodes.value = [];
    return;
  }

  try {
    loading.value = true;
    error.value = null;

    const params = new URLSearchParams({
      apikey: API_KEY,
      state: newState,
      lang: 'en'
    });

    const response = await fetch(`${BASE_URL}/zipcodes/state?${params}`);

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    zipcodes.value = await response.json();
  } catch (err) {
    error.value = err.message;
  } finally {
    loading.value = false;
  }
});
</script>

<template>
  <div>
    <h2>Buscar Códigos Postales por Estado</h2>

    <select v-model="selectedState">
      <option value="">Selecciona un estado...</option>
      <option v-for="state in states" :key="state" :value="state">
        {{ state }}
      </option>
    </select>

    <div v-if="loading">Cargando códigos postales...</div>
    <div v-else-if="error" style="color: red;">Error: {{ error }}</div>

    <div v-else-if="postalCodes.length > 0">
      <h3>{{ zipcodes[0].name }}</h3>
      <p>Total de códigos postales: {{ postalCodes.length }}</p>
      <div style="max-height: 200px; overflow: auto;">
        <span
          v-for="code in postalCodes.slice(0, 100)"
          :key="code"
          style="margin: 2px; display: inline-block;"
        >
          {{ code }}
        </span>
        <span v-if="postalCodes.length > 100">
          ...y {{ postalCodes.length - 100 }} más
        </span>
      </div>
    </div>
  </div>
</template>

Angular

// zipcode.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';

interface StateZipcode {
  id: string;
  name: string;
  postal_code: string[];
}

@Injectable({
  providedIn: 'root'
})
export class ZipcodeService {
  private readonly API_KEY = 'tu-clave-api';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1';

  constructor(private http: HttpClient) {}

  getZipcodesByState(
    state: string,
    limitToken: number = 1000
  ): Observable<StateZipcode[]> {
    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('state', state)
      .set('lang', 'en')
      .set('limitToken', limitToken.toString());

    return this.http.get<StateZipcode[]>(
      `${this.BASE_URL}/zipcodes/state`,
      { params }
    );
  }
}

// state-zipcode-search.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ZipcodeService } from './zipcode.service';

@Component({
  selector: 'app-state-zipcode-search',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div>
      <h2>Buscar Códigos Postales por Estado</h2>

      <select [(ngModel)]="selectedState" (ngModelChange)="onStateChange()">
        <option value="">Selecciona un estado...</option>
        <option *ngFor="let state of states" [value]="state">
          {{ state }}
        </option>
      </select>

      <div *ngIf="loading">Cargando códigos postales...</div>
      <div *ngIf="error" style="color: red;">Error: {{ error }}</div>

      <div *ngIf="zipcodes.length > 0 && !loading">
        <h3>{{ zipcodes[0].name }}</h3>
        <p>Total de códigos postales: {{ zipcodes[0].postal_code.length }}</p>
        <div style="max-height: 200px; overflow: auto;">
          <span
            *ngFor="let code of zipcodes[0].postal_code.slice(0, 100)"
            style="margin: 2px; display: inline-block;"
          >
            {{ code }}
          </span>
          <span *ngIf="zipcodes[0].postal_code.length > 100">
            ...y {{ zipcodes[0].postal_code.length - 100 }} más
          </span>
        </div>
      </div>
    </div>
  `
})
export class StateZipcodeSearchComponent {
  states = ['California', 'Texas', 'New York', 'Florida'];
  selectedState = '';
  zipcodes: any[] = [];
  loading = false;
  error: string | null = null;

  constructor(private zipcodeService: ZipcodeService) {}

  onStateChange() {
    if (!this.selectedState) {
      this.zipcodes = [];
      return;
    }

    this.loading = true;
    this.error = null;

    this.zipcodeService.getZipcodesByState(this.selectedState).subscribe({
      next: (data) => {
        this.zipcodes = data;
        this.loading = false;
      },
      error: (err) => {
        this.error = err.message;
        this.loading = false;
      }
    });
  }
}

PHP

<?php
$apiKey = 'tu-clave-api';
$state = 'California'; // Puede ser nombre de estado o ID
$url = "https://api.countrydataapi.com/v1/zipcodes/state?" . http_build_query([
    'apikey' => $apiKey,
    'state' => $state,
    'lang' => 'en',
    'limitToken' => 1000
]);

// Usando cURL
$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => [
        'Accept: application/json'
    ]
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);

if ($curlError) {
    die("cURL Error: {$curlError}");
}

if ($httpCode === 200) {
    $data = json_decode($response, true);

    if (!empty($data)) {
        $stateData = $data[0];
        echo "Estado: " . $stateData['name'] . "\n";
        echo "Total de Códigos Postales: " . count($stateData['postal_code']) . "\n";
        echo "Muestra: " . implode(', ', array_slice($stateData['postal_code'], 0, 10)) . "...\n";
    } else {
        echo "No se encontraron códigos postales para el estado: {$state}\n";
    }
} else {
    echo "Error: HTTP {$httpCode}\n";
    $error = json_decode($response, true);
    echo "Mensaje: " . ($error['error']['message'] ?? 'Error desconocido') . "\n";
}

// Función reutilizable
function getZipcodesByState($apiKey, $state, $lang = 'en', $limitToken = 1000) {
    $url = "https://api.countrydataapi.com/v1/zipcodes/state?" . http_build_query([
        'apikey' => $apiKey,
        'state' => $state,
        'lang' => $lang,
        'limitToken' => $limitToken
    ]);

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode !== 200) {
        throw new Exception("API Error: HTTP {$httpCode}");
    }

    return json_decode($response, true);
}

// Uso
try {
    $zipcodes = getZipcodesByState($apiKey, 'Texas');
    print_r($zipcodes);
} catch (Exception $e) {
    echo $e->getMessage();
}
?>

Python

import requests
from typing import List, Dict, Any, Optional

API_KEY = 'tu-clave-api'
BASE_URL = 'https://api.countrydataapi.com/v1'

def get_zipcodes_by_state(
    state: str,
    lang: str = 'en',
    limit_token: int = 1000
) -> List[Dict[str, Any]]:
    """
    Obtener códigos postales de un estado específico.

    Args:
        state: Nombre o ID del estado
        lang: Código de idioma para la respuesta
        limit_token: Máximo de tokens a gastar en esta petición

    Returns:
        Lista conteniendo datos del estado con códigos postales
    """
    try:
        response = requests.get(
            f'{BASE_URL}/zipcodes/state',
            params={
                'apikey': API_KEY,
                'state': state,
                'lang': lang,
                'limitToken': limit_token
            },
            timeout=30
        )
        response.raise_for_status()
        return response.json()
    except requests.exceptions.HTTPError as e:
        print(f'HTTP Error: {e.response.status_code}')
        print(f'Response: {e.response.text}')
        raise
    except requests.exceptions.RequestException as e:
        print(f'Request Error: {e}')
        raise

# Ejemplos de uso
if __name__ == '__main__':
    # Buscar por nombre de estado
    california_data = get_zipcodes_by_state('California')
    if california_data:
        state = california_data[0]
        print(f"Estado: {state['name']}")
        print(f"Total de códigos postales: {len(state['postal_code'])}")
        print(f"Muestra: {', '.join(state['postal_code'][:10])}...")

    # Buscar por ID de estado
    texas_data = get_zipcodes_by_state('66c7a6cbe4bda21f4ab11f55')
    if texas_data:
        print(f"\nTexas tiene {len(texas_data[0]['postal_code'])} códigos postales")

# Versión asíncrona usando aiohttp
import aiohttp
import asyncio

async def get_zipcodes_by_state_async(
    state: str,
    lang: str = 'en'
) -> List[Dict[str, Any]]:
    """Versión asíncrona usando aiohttp"""
    async with aiohttp.ClientSession() as session:
        async with session.get(
            f'{BASE_URL}/zipcodes/state',
            params={
                'apikey': API_KEY,
                'state': state,
                'lang': lang
            }
        ) as response:
            if response.status != 200:
                text = await response.text()
                raise Exception(f'API Error: {response.status} - {text}')
            return await response.json()

# Ejecutar async
# data = asyncio.run(get_zipcodes_by_state_async('California'))

Manejo de errores

Siempre implementa un manejo de errores adecuado:

async function getZipcodesWithErrorHandling(state) {
  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/zipcodes/state?apikey=tu-clave-api&state=${encodeURIComponent(state)}`
    );

    if (!response.ok) {
      const errorData = await response.json().catch(() => ({}));

      switch (response.status) {
        case 400:
          throw new Error(errorData.error?.message || 'Parámetros de petición inválidos');
        case 401:
          throw new Error('Clave API inválida');
        case 402:
          throw new Error('Tokens insuficientes. Por favor actualiza tu plan.');
        case 404:
          throw new Error(`Estado "${state}" no encontrado`);
        case 429:
          throw new Error('Límite de tasa excedido. Por favor intenta más tarde.');
        default:
          throw new Error(`HTTP error! status: ${response.status}`);
      }
    }

    const data = await response.json();

    if (!Array.isArray(data) || data.length === 0) {
      console.warn(`No se encontraron códigos postales para el estado: ${state}`);
      return [];
    }

    return data;
  } catch (error) {
    console.error('Error al obtener códigos postales del estado:', error.message);
    throw error;
  }
}

Códigos de error comunes

Código de Error Descripción Solución
INVALID_API_KEY La clave API es inválida Verifica tu clave API en el panel de cuenta
MISSING_PARAMETER Falta el parámetro state Incluye nombre o ID del estado en la petición
STATE_NOT_FOUND El estado no existe Verifica el nombre del estado o usa un ID válido
QUOTA_EXCEEDED Límite diario de tokens alcanzado Actualiza tu plan o espera el reinicio

Casos de uso

1. Validación de formulario de dirección

async function validateZipcode(state, zipcode) {
  const data = await getZipcodesByState(state);

  if (data.length === 0) {
    return { valid: false, message: 'Estado no encontrado' };
  }

  const validZipcodes = data[0].postal_code;
  const isValid = validZipcodes.includes(zipcode);

  return {
    valid: isValid,
    message: isValid ? 'Código postal válido' : 'Código postal inválido para este estado'
  };
}

// Uso
const result = await validateZipcode('California', '90210');
console.log(result); // { valid: true, message: 'Código postal válido' }

2. Dropdown con autocompletado

async function getZipcodeAutocomplete(state, query) {
  const data = await getZipcodesByState(state);

  if (data.length === 0) return [];

  return data[0].postal_code.filter(code =>
    code.startsWith(query)
  ).slice(0, 10);
}

// Uso
const suggestions = await getZipcodeAutocomplete('California', '902');
console.log(suggestions); // ['90201', '90202', '90210', ...]

Consejos de rendimiento

  1. Cachea por estado: Almacena códigos postales por estado para reducir llamadas a la API
  2. Carga perezosa: Solo obtén los datos cuando el usuario seleccione un estado
  3. Implementa debounce: Cuando uses búsqueda/autocompletado
  4. Usa limitToken: Controla el tamaño de datos para estados grandes

Límites de tasa

  • Tier gratuito: 100 peticiones/día
  • Tier básico: 1,000 peticiones/día
  • Tier pro: 10,000 peticiones/día
  • Tier empresarial: Ilimitado

Consulta nuestra página de precios para más detalles.

Endpoints relacionados

¿Necesitas ayuda?