Documentación de la API - Endpoints y Ejemplos

Obtener Estados/Provincias para Select

Obtén estados/provincias por país, optimizados para dropdowns de select

El endpoint /v1/select/states devuelve una lista ligera de estados/provincias filtrados por país, con solo los campos id y name, optimizada para menús desplegables.

Endpoint

GET https://api.countrydataapi.com/v1/select/states

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
country string ID del país (del endpoint /select/countries)
lang string No Código de idioma para nombres de estados (por defecto: en)

Idiomas Soportados

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

Ejemplo de Solicitud

# Obtener estados de Estados Unidos
curl "https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=66c7a6c9e4bda21f4ab10fd5&lang=es"

JavaScript (Fetch)

const API_KEY = 'tu-clave-api';
const COUNTRY_ID = '66c7a6c9e4bda21f4ab10fd5'; // Estados Unidos

async function loadStates(countryId) {
  const response = await fetch(
    `https://api.countrydataapi.com/v1/select/states?apikey=${API_KEY}&country=${countryId}&lang=es`
  );
  const data = await response.json();
  return data;
}

const states = await loadStates(COUNTRY_ID);

JavaScript (Axios)

import axios from 'axios';

const response = await axios.get(
  'https://api.countrydataapi.com/v1/select/states',
  {
    params: {
      apikey: 'tu-clave-api',
      country: '66c7a6c9e4bda21f4ab10fd5',
      lang: 'es',
    },
  }
);

Python

import requests

response = requests.get(
    'https://api.countrydataapi.com/v1/select/states',
    params={
        'apikey': 'tu-clave-api',
        'country': '66c7a6c9e4bda21f4ab10fd5',
        'lang': 'es'
    }
)
data = response.json()

PHP

<?php
$apiKey = 'tu-clave-api';
$countryId = '66c7a6c9e4bda21f4ab10fd5';
$url = "https://api.countrydataapi.com/v1/select/states?apikey={$apiKey}&country={$countryId}&lang=es";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
?>

Angular

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

interface State {
  id: string;
  name: string;
}

interface ApiResponse {
  success: boolean;
  data: State[];
}

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

  constructor(private http: HttpClient) {}

  getStatesByCountry(countryId: string, lang: string = 'es'): Observable<State[]> {
    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('country', countryId)
      .set('lang', lang);

    return this.http.get<ApiResponse>(
      `${this.BASE_URL}/select/states`,
      { params }
    ).pipe(
      map(response => response.data)
    );
  }
}

// state-select.component.ts
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { StateService } from './state.service';

@Component({
  selector: 'app-state-select',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div *ngIf="loading">Cargando estados...</div>
    <div *ngIf="error" class="error">{{ error }}</div>
    <select
      *ngIf="!loading && !error"
      [(ngModel)]="selectedState"
      (ngModelChange)="onStateChange($event)"
      [disabled]="!countryId"
    >
      <option value="">Selecciona un estado...</option>
      <option *ngFor="let state of states" [value]="state.id">
        {{ state.name }}
      </option>
    </select>
  `
})
export class StateSelectComponent implements OnChanges {
  @Input() countryId: string = '';
  @Output() stateChange = new EventEmitter<string>();

  states: any[] = [];
  selectedState = '';
  loading = false;
  error: string | null = null;

  constructor(private stateService: StateService) {}

  ngOnChanges(changes: SimpleChanges) {
    if (changes['countryId'] && this.countryId) {
      this.loadStates();
    } else {
      this.states = [];
      this.selectedState = '';
    }
  }

  loadStates() {
    this.loading = true;
    this.error = null;

    this.stateService.getStatesByCountry(this.countryId, 'es').subscribe({
      next: (data) => {
        this.states = data;
        this.loading = false;
      },
      error: (err) => {
        this.error = 'Error al cargar estados';
        this.loading = false;
      }
    });
  }

  onStateChange(stateId: string) {
    this.stateChange.emit(stateId);
  }
}

Formato de Respuesta

Respuesta Exitosa (Estados Unidos)

{
  "success": true,
  "data": [
    {
      "id": "66c7a6cae4bda21f4ab11d16",
      "name": "Alabama"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d17",
      "name": "Alaska"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d18",
      "name": "Arizona"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d19",
      "name": "Arkansas"
    },
    {
      "id": "66c7a6cae4bda21f4ab11d1a",
      "name": "California"
    }
    // ... 50 estados en total
  ]
}

Campos de Respuesta

Campo Tipo Descripción
success boolean Indica si la solicitud fue exitosa
data array Array de objetos de estado/provincia
data[].id string Identificador único del estado (MongoDB ObjectId)
data[].name string Nombre del estado/provincia en el idioma solicitado

Respuesta de Error

{
  "success": false,
  "error": {
    "code": "MISSING_PARAMETER",
    "message": "Falta el parámetro requerido 'country'"
  }
}

Resultado Vacío

Si un país no tiene estados (ej., países pequeños):

{
  "success": true,
  "data": []
}

Uso de Tokens

Este endpoint consume 1 token por solicitud.

Consejo: Cachea los datos de estados por ID de país para reducir llamadas API cuando los usuarios naveguen de ida y vuelta.

Ejemplo de Dropdown en Cascada

HTML

<select id="country" onchange="loadStates(this.value)">
  <option value="">Selecciona país...</option>
  <!-- Poblado desde /select/countries -->
</select>

<select id="state" disabled>
  <option value="">Selecciona estado...</option>
</select>

<script>
const API_KEY = 'tu-clave-api';

async function loadStates(countryId) {
  const stateSelect = document.getElementById('state');

  // Resetear y deshabilitar
  stateSelect.innerHTML = '<option value="">Cargando...</option>';
  stateSelect.disabled = true;

  if (!countryId) {
    stateSelect.innerHTML = '<option value="">Selecciona estado...</option>';
    return;
  }

  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=${API_KEY}&country=${countryId}&lang=es`
    );
    const { success, data, error } = await response.json();

    if (!success) {
      console.error('Error de API:', error);
      stateSelect.innerHTML = '<option value="">Error al cargar estados</option>';
      return;
    }

    stateSelect.innerHTML = '<option value="">Selecciona estado...</option>';
    data.forEach(state => {
      stateSelect.add(new Option(state.name, state.id));
    });
    stateSelect.disabled = false;
  } catch (err) {
    console.error('Error de Red:', err);
    stateSelect.innerHTML = '<option value="">Error al cargar estados</option>';
  }
}
</script>

Componente React

import { useState, useEffect } from 'react';

function StateSelect({ countryId, onChange }) {
  const [states, setStates] = useState([]);
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    if (!countryId) {
      setStates([]);
      return;
    }

    setLoading(true);
    fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=${countryId}&lang=es`
    )
      .then(res => res.json())
      .then(({ data }) => {
        setStates(data || []);
        setLoading(false);
      })
      .catch(err => {
        console.error(err);
        setLoading(false);
      });
  }, [countryId]);

  return (
    <select onChange={e => onChange(e.target.value)} disabled={!countryId || loading}>
      <option value="">
        {loading ? 'Cargando...' : 'Selecciona estado...'}
      </option>
      {states.map(state => (
        <option key={state.id} value={state.id}>
          {state.name}
        </option>
      ))}
    </select>
  );
}

Componente Vue

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

const props = defineProps(['countryId']);
const emit = defineEmits(['change']);

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

watch(() => props.countryId, async (countryId) => {
  if (!countryId) {
    states.value = [];
    return;
  }

  loading.value = true;
  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=${countryId}&lang=es`
    );
    const { data } = await response.json();
    states.value = data || [];
  } catch (err) {
    console.error(err);
  } finally {
    loading.value = false;
  }
});
</script>

<template>
  <select @change="emit('change', $event.target.value)" :disabled="!countryId || loading">
    <option value="">{{ loading ? 'Cargando...' : 'Selecciona estado...' }}</option>
    <option v-for="state in states" :key="state.id" :value="state.id">
      {{ state.name }}
    </option>
  </select>
</template>

Ejemplos Específicos por País

Estados Unidos (50 estados)

const US_ID = '66c7a6c9e4bda21f4ab10fd5';
const response = await fetch(
  `https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=${US_ID}`
);
// Devuelve: Alabama, Alaska, Arizona, ... Wyoming

Canadá (10 provincias + 3 territorios)

const CANADA_ID = '66c7a6c9e4bda21f4ab10ef7';
const response = await fetch(
  `https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=${CANADA_ID}`
);
// Devuelve: Alberta, British Columbia, ... Yukon

México (32 estados)

const MEXICO_ID = '66c7a6c9e4bda21f4ab10fa8';
const response = await fetch(
  `https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=${MEXICO_ID}&lang=es`
);
// Devuelve: Aguascalientes, Baja California, ... Zacatecas (en español)

Estrategia de Caché

Cachea estados por país para minimizar llamadas API:

const stateCache = new Map();

async function getStates(countryId) {
  // Verificar caché primero
  if (stateCache.has(countryId)) {
    return stateCache.get(countryId);
  }

  // Obtener de la API
  const response = await fetch(
    `https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=${countryId}&lang=es`
  );
  const { data } = await response.json();

  // Guardar en caché
  stateCache.set(countryId, data);

  return data;
}

Manejo de Errores

Siempre maneja errores con gracia:

async function loadStates(countryId) {
  try {
    const response = await fetch(
      `https://api.countrydataapi.com/v1/select/states?apikey=tu-clave-api&country=${countryId}`
    );

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

    const result = await response.json();

    if (!result.success) {
      throw new Error(result.error?.message || 'Error de API');
    }

    return result.data;
  } catch (err) {
    console.error('Error al cargar estados:', err);
    // Mostrar mensaje de error amigable
    alert('Error al cargar estados. Por favor intenta de nuevo.');
    return [];
  }
}

Consejos de Rendimiento

  1. Carga perezosa: Solo obtén cuando se seleccione el país
  2. Caché por país: Almacena en memoria o localStorage
  3. Debounce en solicitudes: Si usas búsqueda/filtro
  4. Muestra estado de carga: Proporciona retroalimentación visual

Límites de Tasa

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

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

Errores Comunes

Código de Error Descripción Solución
INVALID_API_KEY Clave API inválida Verifica tu clave API en el panel de cuenta
MISSING_PARAMETER Falta parámetro country Incluye ID de país en la solicitud
INVALID_COUNTRY_ID Formato de ID de país inválido Usa un ObjectId válido de MongoDB de /select/countries
QUOTA_EXCEEDED Límite diario de tokens alcanzado Actualiza tu plan o espera el reinicio

Consulta la documentación de Códigos de Error para todos los errores posibles.

Endpoints Relacionados

Guías de Integración Completas

¿Necesitas Ayuda?


Nota: Algunos países no tienen divisiones administrativas (ej., Mónaco, Ciudad del Vaticano) y devolverán un array vacío. Siempre maneja resultados vacíos con gracia en tu UI.