Documentación de la API - Endpoints y Ejemplos

Buscar estados por código postal

Descripcion general

Este endpoint te permite encontrar estados basados en un código postal (ZIP code). Es particularmente útil para validación de direcciones, cálculos de envío y servicios basados en ubicación. Ten en cuenta que el mismo código postal puede existir en diferentes países, por lo que pueden devolverse múltiples resultados.

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

Autenticación

Todas las solicitudes a la API requieren autenticación mediante una clave API. Incluye tu clave API como parámetro de consulta en cada solicitud:

?apikey=TU_CLAVE_API

Puedes obtener una clave API registrándote en CountryDataAPI.


Petición

HTTP GET

https://api.countrydataapi.com/v1/states/zipCode

Retorna una lista de todos los estados según su código postal

Información relevante

Ten en cuenta que hay muchos estados de diferentes países que tienen códigos postales iguales

Según los campos solicitados, habrá 3 tipos de peticiones:

  • BASIC: Retorna los campos id, state_name, lang Cada estado costará 1 token

  • NORMAL: Retorna el campo state_cities [Todos los IDs y nombres de ciudades del estado] Cada ciudad costará 1 token

  • ADVANCED: Retorna el campo state_zip_codes [Todos los códigos postales de la ciudad] Cada código postal cuesta 1 token

Parámetros de consulta


Parámetro Tipo Descripción
apikey requerido, token Clave de autenticación de la cuenta
zipcode requerido, string Código postal del estado que se desea
limitToken opcional, number 1000 (predeterminado). Número máximo de tokens que quieres gastar en esta petición
fields opcional, string id,lang,state_name (predeterminado). Campos esperados en la respuesta
lang opcional, lang en (predeterminado). Idioma esperado de la respuesta

Respuesta

Ejemplo de respuesta

[
  {
    "id": "8dd25479-067a-43b0-ac4a-8e7faf2bcafb",
    "state_name": "Takhar",
    "lang": "en",
    "state_cities": [
      {
        "id": "8dd25476-067a-43b0-ac4b-8e7faf2bcbfb",
        "city_name": "City"
      }
    ],
    "state_zip_codes": [
      "00000",
      "00001"
    ]
  }
]

Ejemplos de código

JavaScript (Fetch)

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';

async function getStateByZipCode(zipCode) {
  try {
    const params = new URLSearchParams({
      apikey: API_KEY,
      zipcode: zipCode,
      lang: 'en',
      fields: 'id,state_name,lang'
    });

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

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

    const states = await response.json();
    console.log(`Estados con código postal "${zipCode}":`, states);
    return states;
  } catch (error) {
    console.error('Error fetching state by zip code:', error);
    throw error;
  }
}

// Uso
getStateByZipCode('90210');  // Beverly Hills, California
getStateByZipCode('10001');  // New York
getStateByZipCode('28001');  // Madrid, España

JavaScript (Axios)

import axios from 'axios';

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';

async function getStateByZipCode(zipCode) {
  try {
    const response = await axios.get(BASE_URL, {
      params: {
        apikey: API_KEY,
        zipcode: zipCode,
        lang: 'en',
        fields: 'id,state_name,lang'
      }
    });

    console.log(`Estados con código postal "${zipCode}":`, response.data);
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error('API Error:', error.response?.data || error.message);
    }
    throw error;
  }
}

// Validar código postal y obtener estado
async function validateZipCode(zipCode) {
  const states = await getStateByZipCode(zipCode);

  if (states.length === 0) {
    return { valid: false, message: 'Código postal inválido' };
  }

  if (states.length === 1) {
    return {
      valid: true,
      state: states[0].state_name,
      message: `El código postal pertenece a ${states[0].state_name}`
    };
  }

  return {
    valid: true,
    states: states.map(s => s.state_name),
    message: `El código postal existe en múltiples ubicaciones`
  };
}

// Uso
validateZipCode('33101');  // Miami, Florida

React

import { useState, useEffect, useCallback } from 'react';

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';

function StateByZipCode({ zipCode }) {
  const [states, setStates] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchStateByZipCode = async () => {
      if (!zipCode) {
        setStates([]);
        return;
      }

      try {
        setLoading(true);
        setError(null);

        const params = new URLSearchParams({
          apikey: API_KEY,
          zipcode: zipCode,
          lang: 'en',
          fields: 'id,state_name,lang'
        });

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

        if (!response.ok) {
          throw new Error('Failed to fetch state');
        }

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

    fetchStateByZipCode();
  }, [zipCode]);

  if (loading) return <div>Buscando código postal...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <h2>Estados con código postal "{zipCode}"</h2>
      {states.length === 0 ? (
        <p>No se encontraron estados para este código postal</p>
      ) : (
        <>
          <p>Se encontraron {states.length} resultado(s)</p>
          <ul>
            {states.map((state) => (
              <li key={state.id}>{state.state_name}</li>
            ))}
          </ul>
        </>
      )}
    </div>
  );
}

// Componente de búsqueda de código postal con input y debounce
function ZipCodeLookup() {
  const [zipInput, setZipInput] = useState('');
  const [searchZip, setSearchZip] = useState('');
  const [debouncedZip, setDebouncedZip] = useState('');

  // Debounce de la búsqueda
  useEffect(() => {
    const timer = setTimeout(() => {
      if (zipInput.length >= 3) {
        setDebouncedZip(zipInput);
      }
    }, 500);

    return () => clearTimeout(timer);
  }, [zipInput]);

  const handleSearch = (e) => {
    e.preventDefault();
    setSearchZip(zipInput);
  };

  return (
    <div>
      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={zipInput}
          onChange={(e) => setZipInput(e.target.value)}
          placeholder="Ingresa el código postal..."
          pattern="[0-9]*"
        />
        <button type="submit">Buscar</button>
      </form>

      {(searchZip || debouncedZip) && (
        <StateByZipCode zipCode={searchZip || debouncedZip} />
      )}
    </div>
  );
}

export default ZipCodeLookup;

Vue 3

<template>
  <div>
    <div v-if="loading">Buscando código postal...</div>
    <div v-else-if="error">Error: {{ error }}</div>
    <div v-else>
      <h2>Estados con código postal "{{ zipCode }}"</h2>
      <p v-if="states.length === 0">No se encontraron estados para este código postal</p>
      <div v-else>
        <p>Se encontraron {{ states.length }} resultado(s)</p>
        <ul>
          <li v-for="state in states" :key="state.id">
            {{ state.state_name }}
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

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

const props = defineProps({
  zipCode: {
    type: String,
    required: true
  }
});

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';

const states = ref([]);
const loading = ref(false);
const error = ref(null);

const fetchStateByZipCode = async () => {
  if (!props.zipCode) {
    states.value = [];
    return;
  }

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

    const params = new URLSearchParams({
      apikey: API_KEY,
      zipcode: props.zipCode,
      lang: 'en',
      fields: 'id,state_name,lang'
    });

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

    if (!response.ok) {
      throw new Error('Failed to fetch state');
    }

    states.value = await response.json();
  } catch (err) {
    error.value = err.message;
  } finally {
    loading.value = false;
  }
};

watch(() => props.zipCode, fetchStateByZipCode);
onMounted(fetchStateByZipCode);
</script>

Angular

import { Component, Input, OnInit, OnChanges } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Subject, debounceTime, distinctUntilChanged } from 'rxjs';

interface State {
  id: string;
  state_name: string;
  lang: string;
  state_cities?: Array<{ id: string; city_name: string }>;
  state_zip_codes?: string[];
}

@Component({
  selector: 'app-state-by-zipcode',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div>
      <div *ngIf="loading">Buscando código postal...</div>
      <div *ngIf="error">Error: {{ error }}</div>
      <div *ngIf="!loading && !error">
        <h2>Estados con código postal "{{ zipCode }}"</h2>
        <p *ngIf="states.length === 0">No se encontraron estados para este código postal</p>
        <div *ngIf="states.length > 0">
          <p>Se encontraron {{ states.length }} resultado(s)</p>
          <ul>
            <li *ngFor="let state of states">{{ state.state_name }}</li>
          </ul>
        </div>
      </div>
    </div>
  `
})
export class StateByZipCodeComponent implements OnInit, OnChanges {
  @Input() zipCode!: string;

  private readonly API_KEY = 'TU_CLAVE_API';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode';

  states: State[] = [];
  loading = false;
  error: string | null = null;

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    this.fetchStateByZipCode();
  }

  ngOnChanges(): void {
    this.fetchStateByZipCode();
  }

  private fetchStateByZipCode(): void {
    if (!this.zipCode) {
      this.states = [];
      return;
    }

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

    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('zipcode', this.zipCode)
      .set('lang', 'en')
      .set('fields', 'id,state_name,lang');

    this.http.get<State[]>(this.BASE_URL, { params }).subscribe({
      next: (data) => {
        this.states = data;
        this.loading = false;
      },
      error: (err) => {
        this.error = err.message;
        this.loading = false;
      }
    });
  }
}

// Búsqueda de código postal con debounce
@Component({
  selector: 'app-zipcode-lookup',
  standalone: true,
  imports: [CommonModule, FormsModule, StateByZipCodeComponent],
  template: `
    <div>
      <form (ngSubmit)="search()">
        <input
          type="text"
          [(ngModel)]="zipInput"
          name="zipcode"
          (ngModelChange)="onZipChange($event)"
          placeholder="Ingresa el código postal..."
        />
        <button type="submit">Buscar</button>
      </form>

      <app-state-by-zipcode
        *ngIf="searchZip"
        [zipCode]="searchZip"
      ></app-state-by-zipcode>
    </div>
  `
})
export class ZipCodeLookupComponent {
  zipInput = '';
  searchZip = '';
  private zipSubject = new Subject<string>();

  constructor() {
    this.zipSubject.pipe(
      debounceTime(500),
      distinctUntilChanged()
    ).subscribe(zip => {
      if (zip.length >= 3) {
        this.searchZip = zip;
      }
    });
  }

  onZipChange(value: string): void {
    this.zipSubject.next(value);
  }

  search(): void {
    this.searchZip = this.zipInput;
  }
}

PHP

<?php

$apiKey = 'TU_CLAVE_API';
$baseUrl = 'https://api.countrydataapi.com/v1/states/zipCode';

function getStateByZipCode($zipCode, $apiKey) {
    $baseUrl = 'https://api.countrydataapi.com/v1/states/zipCode';

    $params = http_build_query([
        'apikey' => $apiKey,
        'zipcode' => $zipCode,
        'lang' => 'en',
        'fields' => 'id,state_name,lang'
    ]);

    $url = $baseUrl . '?' . $params;

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);

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

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

    return json_decode($response, true);
}

// Uso
try {
    $zipCode = '90210';
    $states = getStateByZipCode($zipCode, $apiKey);

    echo "Estados con código postal '$zipCode':\n";
    echo "Se encontraron " . count($states) . " resultado(s)\n\n";

    foreach ($states as $state) {
        echo "- " . $state['state_name'] . " (ID: " . $state['id'] . ")\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

// Función de validación de código postal
function validateZipCode($zipCode, $apiKey) {
    $states = getStateByZipCode($zipCode, $apiKey);

    if (empty($states)) {
        return [
            'valid' => false,
            'message' => "Código postal inválido: $zipCode"
        ];
    }

    if (count($states) === 1) {
        return [
            'valid' => true,
            'state' => $states[0]['state_name'],
            'message' => "El código postal $zipCode está en " . $states[0]['state_name']
        ];
    }

    $stateNames = array_map(function($s) {
        return $s['state_name'];
    }, $states);

    return [
        'valid' => true,
        'states' => $stateNames,
        'message' => "El código postal $zipCode existe en: " . implode(', ', $stateNames)
    ];
}

// Ejemplo
$result = validateZipCode('10001', $apiKey);
echo $result['message'] . "\n";
?>

Python

import requests

API_KEY = 'TU_CLAVE_API'
BASE_URL = 'https://api.countrydataapi.com/v1/states/zipCode'

def get_state_by_zipcode(zip_code):
    """Encontrar el/los estado(s) para un código postal dado."""
    params = {
        'apikey': API_KEY,
        'zipcode': zip_code,
        'lang': 'en',
        'fields': 'id,state_name,lang'
    }

    try:
        response = requests.get(BASE_URL, params=params)
        response.raise_for_status()

        states = response.json()
        return states
    except requests.exceptions.RequestException as e:
        print(f'Error fetching state by ZIP code: {e}')
        raise

def validate_zipcode(zip_code):
    """Validar un código postal y devolver información del estado."""
    states = get_state_by_zipcode(zip_code)

    if not states:
        return {
            'valid': False,
            'message': f'Código postal inválido: {zip_code}'
        }

    if len(states) == 1:
        return {
            'valid': True,
            'state': states[0]['state_name'],
            'state_id': states[0]['id'],
            'message': f"El código postal {zip_code} está en {states[0]['state_name']}"
        }

    state_names = [s['state_name'] for s in states]
    return {
        'valid': True,
        'states': state_names,
        'message': f"El código postal {zip_code} existe en múltiples ubicaciones: {', '.join(state_names)}"
    }

# Uso
if __name__ == '__main__':
    # Códigos postales de EE.UU.
    us_zips = ['90210', '10001', '33101', '60601']

    for zip_code in us_zips:
        result = validate_zipcode(zip_code)
        print(f"{zip_code}: {result['message']}")


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

async def get_state_by_zipcode_async(zip_code):
    """Encontrar estado por código postal de forma asíncrona."""
    params = {
        'apikey': API_KEY,
        'zipcode': zip_code,
        'lang': 'en',
        'fields': 'id,state_name,lang'
    }

    async with aiohttp.ClientSession() as session:
        async with session.get(BASE_URL, params=params) as response:
            if response.status == 200:
                return await response.json()
            else:
                raise Exception(f'HTTP Error: {response.status}')

# Validación por lotes de códigos postales
async def validate_multiple_zipcodes(zip_codes):
    """Validar múltiples códigos postales concurrentemente."""
    tasks = [get_state_by_zipcode_async(z) for z in zip_codes]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(zip_codes, results))

# Uso
# zip_codes = ['90210', '10001', '33101', '60601', '98101']
# results = asyncio.run(validate_multiple_zipcodes(zip_codes))
# for zip_code, states in results.items():
#     if isinstance(states, list) and states:
#         print(f"{zip_code}: {states[0]['state_name']}")

cURL

# Buscar estado por código postal
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=TU_CLAVE_API&zipcode=90210&lang=en&fields=id,state_name,lang"

# Código postal de New York
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=TU_CLAVE_API&zipcode=10001&lang=en"

# Con salida JSON formateada
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=TU_CLAVE_API&zipcode=33101&lang=en" | json_pp

# Código postal europeo
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=TU_CLAVE_API&zipcode=28001&lang=en"

# Obtener información detallada del estado incluyendo ciudades
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=TU_CLAVE_API&zipcode=60601&fields=id,state_name,state_cities"

# Guardar respuesta en archivo
curl -X GET "https://api.countrydataapi.com/v1/states/zipCode?apikey=TU_CLAVE_API&zipcode=98101&lang=en" -o seattle_state.json

# Verificar múltiples códigos postales en secuencia
for zip in 90210 10001 33101 60601; do
  echo "ZIP: $zip"
  curl -s "https://api.countrydataapi.com/v1/states/zipCode?apikey=TU_CLAVE_API&zipcode=$zip&fields=state_name" | json_pp
  echo ""
done

Manejo de errores

La API puede devolver las siguientes respuestas de error:

Código de estado Descripción
400 Bad Request - Parámetros inválidos o código postal faltante
401 Unauthorized - Clave API inválida o faltante
403 Forbidden - Permisos insuficientes o saldo de tokens
404 Not Found - Código postal no encontrado
429 Too Many Requests - Límite de tasa excedido
500 Internal Server Error

Ejemplo de respuesta de error

{
  "statusCode": 404,
  "message": "ZIP code not found",
  "error": "Not Found"
}

Notas importantes

  • Códigos postales internacionales: Los códigos postales varían en formato según el país (ej. EE.UU. usa códigos de 5 dígitos, Reino Unido usa códigos alfanuméricos). Asegúrate de pasar el formato correcto.
  • Códigos duplicados: Algunos códigos postales pueden existir en diferentes países. La API devuelve todos los estados coincidentes.
  • Ceros iniciales: Algunos códigos postales tienen ceros iniciales (ej. "01234"). Siempre pásalos como strings para preservar el formato.