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.
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.
https://api.countrydataapi.com/v1/states/zipCode
Retorna una lista de todos los estados según su código postal
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á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 |
[
{
"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"
]
}
]
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
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
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;
<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>
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
$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";
?>
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']}")
# 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
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 |
{
"statusCode": 404,
"message": "ZIP code not found",
"error": "Not Found"
}