Documentación de la API - Endpoints y Ejemplos

Ciudades por Estado

Descripción general

Este endpoint recupera todas las ciudades que pertenecen a un estado específico. Es perfecto para construir selectores de ubicación, filtrar datos geográficos por estado, o cuando necesitas mostrar todas las ciudades dentro de una región administrativa particular.

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/cities/state

Retorna una lista de todas las ciudades de un estado

Cada 5 ciudades retornadas consumirá 1 token

Parámetros de consulta


Parámetro Tipo Descripción
apikey requerido, token Clave de autenticación de la cuenta
state requerido, id o string ID o nombre del estado
limitToken opcional, number 1000 (predeterminado). Número máximo de tokens que quieres gastar en esta petición
lang opcional, lang en (predeterminado). Idioma esperado de la respuesta

Respuesta

Ejemplo de respuesta

[
  {
    "id": "d54ba796-1136-4776-9776-537fd5a857c9",
    "lang": "en",
    "city_name": "Bala Morghab"
  }
]

Ejemplos de código

JavaScript (Fetch)

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/cities/state';

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

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

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

    const cities = await response.json();
    console.log(`Cities in ${stateName}:`, cities);
    return cities;
  } catch (error) {
    console.error('Error fetching cities by state:', error);
    throw error;
  }
}

// Uso
getCitiesByState('California');
getCitiesByState('Texas');
getCitiesByState('Florida');

JavaScript (Axios)

import axios from 'axios';

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/cities/state';

async function getCitiesByState(stateName) {
  try {
    const response = await axios.get(BASE_URL, {
      params: {
        apikey: API_KEY,
        state: stateName,
        lang: 'en'
      }
    });

    console.log(`Cities in ${stateName}:`, response.data);
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error('API Error:', error.response?.data || error.message);
    }
    throw error;
  }
}

// Uso
getCitiesByState('New York');

React

import { useState, useEffect } from 'react';

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/cities/state';

function CitiesByState({ state }) {
  const [cities, setCities] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchCities = async () => {
      if (!state) {
        setCities([]);
        return;
      }

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

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

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

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

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

    fetchCities();
  }, [state]);

  if (loading) return <div>Cargando ciudades...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <h2>Ciudades en {state}</h2>
      <p>Total: {cities.length} ciudades</p>
      <ul>
        {cities.map((city) => (
          <li key={city.id}>{city.city_name}</li>
        ))}
      </ul>
    </div>
  );
}

// Selector de estado con dropdown de ciudades
function StateCitySelector() {
  const [selectedState, setSelectedState] = useState('');
  const [cities, setCities] = useState([]);
  const [selectedCity, setSelectedCity] = useState('');
  const [loading, setLoading] = useState(false);

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

  useEffect(() => {
    if (!selectedState) {
      setCities([]);
      return;
    }

    const fetchCities = async () => {
      setLoading(true);
      const params = new URLSearchParams({
        apikey: API_KEY,
        state: selectedState,
        lang: 'en'
      });

      try {
        const response = await fetch(`${BASE_URL}?${params}`);
        const data = await response.json();
        setCities(data);
        setSelectedCity('');
      } catch (err) {
        console.error(err);
      } finally {
        setLoading(false);
      }
    };

    fetchCities();
  }, [selectedState]);

  return (
    <div>
      <select
        value={selectedState}
        onChange={(e) => setSelectedState(e.target.value)}
      >
        <option value="">Seleccionar Estado</option>
        {states.map((s) => (
          <option key={s} value={s}>{s}</option>
        ))}
      </select>

      <select
        value={selectedCity}
        onChange={(e) => setSelectedCity(e.target.value)}
        disabled={loading || !cities.length}
      >
        <option value="">
          {loading ? 'Cargando...' : 'Seleccionar Ciudad'}
        </option>
        {cities.map((c) => (
          <option key={c.id} value={c.id}>{c.city_name}</option>
        ))}
      </select>
    </div>
  );
}

export default CitiesByState;

Vue 3

<template>
  <div>
    <div v-if="loading">Cargando ciudades...</div>
    <div v-else-if="error">Error: {{ error }}</div>
    <div v-else>
      <h2>Ciudades en {{ state }}</h2>
      <p>Total: {{ cities.length }} ciudades</p>
      <ul>
        <li v-for="city in cities" :key="city.id">
          {{ city.city_name }}
        </li>
      </ul>
    </div>
  </div>
</template>

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

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

const API_KEY = 'TU_CLAVE_API';
const BASE_URL = 'https://api.countrydataapi.com/v1/cities/state';

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

const fetchCities = async () => {
  if (!props.state) {
    cities.value = [];
    return;
  }

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

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

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

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

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

watch(() => props.state, fetchCities);
onMounted(fetchCities);
</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';

interface City {
  id: string;
  city_name: string;
  lang: string;
}

@Component({
  selector: 'app-cities-by-state',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div>
      <div *ngIf="loading">Cargando ciudades...</div>
      <div *ngIf="error">Error: {{ error }}</div>
      <div *ngIf="!loading && !error">
        <h2>Ciudades en {{ state }}</h2>
        <p>Total: {{ cities.length }} ciudades</p>
        <ul>
          <li *ngFor="let city of cities">{{ city.city_name }}</li>
        </ul>
      </div>
    </div>
  `
})
export class CitiesByStateComponent implements OnInit, OnChanges {
  @Input() state!: string;

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

  cities: City[] = [];
  loading = false;
  error: string | null = null;

  constructor(private http: HttpClient) {}

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

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

  private fetchCities(): void {
    if (!this.state) {
      this.cities = [];
      return;
    }

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

    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('state', this.state)
      .set('lang', 'en');

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

// Componente selector Estado-Ciudad
@Component({
  selector: 'app-state-city-selector',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div>
      <select [(ngModel)]="selectedState" (ngModelChange)="onStateChange()">
        <option value="">Seleccionar Estado</option>
        <option *ngFor="let s of states" [value]="s">{{ s }}</option>
      </select>

      <select
        [(ngModel)]="selectedCity"
        [disabled]="loading || cities.length === 0"
      >
        <option value="">{{ loading ? 'Cargando...' : 'Seleccionar Ciudad' }}</option>
        <option *ngFor="let c of cities" [value]="c.id">
          {{ c.city_name }}
        </option>
      </select>
    </div>
  `
})
export class StateCitySelectorComponent {
  private readonly API_KEY = 'TU_CLAVE_API';
  private readonly BASE_URL = 'https://api.countrydataapi.com/v1/cities/state';

  states = ['California', 'Texas', 'Florida', 'New York', 'Colorado'];
  selectedState = '';
  selectedCity = '';
  cities: City[] = [];
  loading = false;

  constructor(private http: HttpClient) {}

  onStateChange(): void {
    if (!this.selectedState) {
      this.cities = [];
      return;
    }

    this.loading = true;
    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('state', this.selectedState)
      .set('lang', 'en');

    this.http.get<City[]>(this.BASE_URL, { params }).subscribe({
      next: (data) => {
        this.cities = data;
        this.selectedCity = '';
        this.loading = false;
      },
      error: () => {
        this.loading = false;
      }
    });
  }
}

PHP

<?php

$apiKey = 'TU_CLAVE_API';
$baseUrl = 'https://api.countrydataapi.com/v1/cities/state';

function getCitiesByState($stateName, $apiKey, $limitToken = 1000) {
    $baseUrl = 'https://api.countrydataapi.com/v1/cities/state';

    $params = http_build_query([
        'apikey' => $apiKey,
        'state' => $stateName,
        'lang' => 'en',
        'limitToken' => $limitToken
    ]);

    $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 {
    $stateName = 'California';
    $cities = getCitiesByState($stateName, $apiKey);

    echo "Ciudades en $stateName:\n";
    echo "Total: " . count($cities) . " ciudades\n\n";

    // Mostrar las primeras 20 ciudades
    foreach (array_slice($cities, 0, 20) as $city) {
        echo "- " . $city['city_name'] . "\n";
    }

    if (count($cities) > 20) {
        echo "... y " . (count($cities) - 20) . " ciudades más\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

// Calcular uso de tokens
function calculateTokenUsage($cityCount) {
    return ceil($cityCount / 5);
}

$cities = getCitiesByState('Texas', $apiKey);
echo "\nCiudades en Texas: " . count($cities) . "\n";
echo "Tokens consumidos: " . calculateTokenUsage(count($cities)) . "\n";
?>

Python

import requests

API_KEY = 'TU_CLAVE_API'
BASE_URL = 'https://api.countrydataapi.com/v1/cities/state'

def get_cities_by_state(state_name, limit_token=1000):
    """Obtener todas las ciudades de un estado específico."""
    params = {
        'apikey': API_KEY,
        'state': state_name,
        'lang': 'en',
        'limitToken': limit_token
    }

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

        cities = response.json()
        return cities
    except requests.exceptions.RequestException as e:
        print(f'Error fetching cities: {e}')
        raise

def calculate_token_usage(city_count):
    """Calcular tokens consumidos (5 ciudades = 1 token)."""
    return (city_count + 4) // 5

# Uso
if __name__ == '__main__':
    state = 'California'
    cities = get_cities_by_state(state)

    print(f"Ciudades en {state}:")
    print(f"Total: {len(cities)} ciudades")
    print(f"Tokens consumidos: {calculate_token_usage(len(cities))}")
    print("\nPrimeras 10 ciudades:")

    for city in cities[:10]:
        print(f"  - {city['city_name']}")


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

async def get_cities_by_state_async(state_name):
    """Obtener ciudades por estado de forma asíncrona."""
    params = {
        'apikey': API_KEY,
        'state': state_name,
        'lang': 'en'
    }

    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}')

# Obtener ciudades de múltiples estados concurrentemente
async def get_cities_for_multiple_states(states):
    """Obtener ciudades de múltiples estados concurrentemente."""
    tasks = [get_cities_by_state_async(state) for state in states]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(states, results))

# Uso
# states = ['California', 'Texas', 'Florida', 'New York']
# results = asyncio.run(get_cities_for_multiple_states(states))
# for state, cities in results.items():
#     if isinstance(cities, list):
#         print(f"{state}: {len(cities)} ciudades")

cURL

# Obtener ciudades de California
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=TU_CLAVE_API&state=California&lang=en"

# Obtener ciudades de Texas
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=TU_CLAVE_API&state=Texas&lang=en"

# Con salida JSON formateada
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=TU_CLAVE_API&state=Florida&lang=en" | json_pp

# Limitar uso de tokens
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=TU_CLAVE_API&state=New%20York&limitToken=500"

# Obtener ciudades por ID de estado
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=TU_CLAVE_API&state=8dd25479-067a-43b0-ac4a-8e7faf2bcafb&lang=en"

# Guardar respuesta en archivo
curl -X GET "https://api.countrydataapi.com/v1/cities/state?apikey=TU_CLAVE_API&state=Colorado&lang=en" -o colorado_cities.json

# Obtener ciudades de múltiples estados
for state in California Texas Florida; do
  echo "Estado: $state"
  curl -s "https://api.countrydataapi.com/v1/cities/state?apikey=TU_CLAVE_API&state=$state" | json_pp | head -20
  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 estado faltante
401 Unauthorized - Clave API inválida o faltante
403 Forbidden - Permisos insuficientes o saldo de tokens
404 Not Found - Estado no encontrado
429 Too Many Requests - Límite de tasa excedido
500 Internal Server Error

Ejemplo de respuesta de error

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

Consumo de tokens

Cada 5 ciudades retornadas consumirá 1 token. Por ejemplo:

  • 50 ciudades = 10 tokens
  • 100 ciudades = 20 tokens
  • 500 ciudades = 100 tokens

Usa el parámetro limitToken para controlar tu uso de tokens.