Documentación de la API - Endpoints y Ejemplos

Ciudades por País

Descripción general

Este endpoint recupera todas las ciudades que pertenecen a un país específico. Es perfecto para construir selectores de país-ciudad, filtrar datos geográficos por país, o cuando necesitas mostrar todas las ciudades dentro de una nación 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/country

Retorna todas las ciudades de un país

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
country requerido, id o string ID o nombre del país
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/country';

async function getCitiesByCountry(countryName) {
  try {
    const params = new URLSearchParams({
      apikey: API_KEY,
      country: countryName,
      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 ${countryName}:`, cities.length);
    return cities;
  } catch (error) {
    console.error('Error fetching cities by country:', error);
    throw error;
  }
}

// Uso
getCitiesByCountry('United States');
getCitiesByCountry('Spain');
getCitiesByCountry('Germany');

JavaScript (Axios)

import axios from 'axios';

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

async function getCitiesByCountry(countryName, limitToken = 1000) {
  try {
    const response = await axios.get(BASE_URL, {
      params: {
        apikey: API_KEY,
        country: countryName,
        lang: 'en',
        limitToken: limitToken
      }
    });

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

// Uso
getCitiesByCountry('France');
getCitiesByCountry('Japan', 500);

React

import { useState, useEffect } from 'react';

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

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

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

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

        const params = new URLSearchParams({
          apikey: API_KEY,
          country: country,
          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();
  }, [country]);

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

  return (
    <div>
      <h2>Ciudades en {country}</h2>
      <p>Total: {cities.length} ciudades</p>
      <ul>
        {cities.slice(0, 50).map((city) => (
          <li key={city.id}>{city.city_name}</li>
        ))}
      </ul>
      {cities.length > 50 && (
        <p>...y {cities.length - 50} ciudades más</p>
      )}
    </div>
  );
}

// Selector de país con lista de ciudades
function CountryCityBrowser() {
  const [selectedCountry, setSelectedCountry] = useState('');
  const [cities, setCities] = useState([]);
  const [loading, setLoading] = useState(false);
  const [searchTerm, setSearchTerm] = useState('');

  const countries = ['United States', 'Spain', 'Germany', 'France', 'Japan', 'Mexico', 'Canada'];

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

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

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

    fetchCities();
  }, [selectedCountry]);

  const filteredCities = cities.filter(city =>
    city.city_name.toLowerCase().includes(searchTerm.toLowerCase())
  );

  return (
    <div>
      <select
        value={selectedCountry}
        onChange={(e) => setSelectedCountry(e.target.value)}
      >
        <option value="">Seleccionar País</option>
        {countries.map((c) => (
          <option key={c} value={c}>{c}</option>
        ))}
      </select>

      {selectedCountry && (
        <>
          <input
            type="text"
            value={searchTerm}
            onChange={(e) => setSearchTerm(e.target.value)}
            placeholder="Filtrar ciudades..."
          />
          <p>Mostrando {filteredCities.length} de {cities.length} ciudades</p>
        </>
      )}

      {loading ? (
        <p>Cargando...</p>
      ) : (
        <ul>
          {filteredCities.slice(0, 100).map((city) => (
            <li key={city.id}>{city.city_name}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default CitiesByCountry;

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 {{ country }}</h2>
      <p>Total: {{ cities.length }} ciudades</p>
      <input
        v-model="searchTerm"
        type="text"
        placeholder="Filtrar ciudades..."
      />
      <ul>
        <li v-for="city in filteredCities" :key="city.id">
          {{ city.city_name }}
        </li>
      </ul>
    </div>
  </div>
</template>

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

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

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

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

const filteredCities = computed(() => {
  if (!searchTerm.value) {
    return cities.value.slice(0, 100);
  }
  return cities.value
    .filter(city =>
      city.city_name.toLowerCase().includes(searchTerm.value.toLowerCase())
    )
    .slice(0, 100);
});

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

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

    const params = new URLSearchParams({
      apikey: API_KEY,
      country: props.country,
      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.country, 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-country',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div>
      <div *ngIf="loading">Cargando ciudades...</div>
      <div *ngIf="error">Error: {{ error }}</div>
      <div *ngIf="!loading && !error">
        <h2>Ciudades en {{ country }}</h2>
        <p>Total: {{ cities.length }} ciudades</p>
        <input
          type="text"
          [(ngModel)]="searchTerm"
          placeholder="Filtrar ciudades..."
        />
        <ul>
          <li *ngFor="let city of filteredCities">{{ city.city_name }}</li>
        </ul>
      </div>
    </div>
  `
})
export class CitiesByCountryComponent implements OnInit, OnChanges {
  @Input() country!: string;

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

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

  constructor(private http: HttpClient) {}

  get filteredCities(): City[] {
    if (!this.searchTerm) {
      return this.cities.slice(0, 100);
    }
    return this.cities
      .filter(city =>
        city.city_name.toLowerCase().includes(this.searchTerm.toLowerCase())
      )
      .slice(0, 100);
  }

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

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

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

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

    const params = new HttpParams()
      .set('apikey', this.API_KEY)
      .set('country', this.country)
      .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;
      }
    });
  }
}

PHP

<?php

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

function getCitiesByCountry($countryName, $apiKey, $limitToken = 1000) {
    $baseUrl = 'https://api.countrydataapi.com/v1/cities/country';

    $params = http_build_query([
        'apikey' => $apiKey,
        'country' => $countryName,
        '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 {
    $countryName = 'United States';
    $cities = getCitiesByCountry($countryName, $apiKey);

    echo "Ciudades en $countryName:\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 = getCitiesByCountry('Spain', $apiKey);
echo "\nCiudades en España: " . count($cities) . "\n";
echo "Tokens consumidos: " . calculateTokenUsage(count($cities)) . "\n";

// Buscar ciudades por nombre dentro de un país
function searchCitiesInCountry($countryName, $searchTerm, $apiKey) {
    $cities = getCitiesByCountry($countryName, $apiKey);

    return array_filter($cities, function($city) use ($searchTerm) {
        return stripos($city['city_name'], $searchTerm) !== false;
    });
}

$results = searchCitiesInCountry('Germany', 'Berlin', $apiKey);
print_r($results);
?>

Python

import requests

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

def get_cities_by_country(country_name, limit_token=1000):
    """Obtener todas las ciudades de un país específico."""
    params = {
        'apikey': API_KEY,
        'country': country_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

def search_cities_in_country(country_name, search_term):
    """Buscar ciudades que contengan un término específico dentro de un país."""
    cities = get_cities_by_country(country_name)
    return [
        city for city in cities
        if search_term.lower() in city['city_name'].lower()
    ]

# Uso
if __name__ == '__main__':
    country = 'United States'
    cities = get_cities_by_country(country)

    print(f"Ciudades en {country}:")
    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']}")

    # Ejemplo de búsqueda
    print("\nBuscando 'New' en ciudades de EE.UU.:")
    results = search_cities_in_country('United States', 'New')
    for city in results[:5]:
        print(f"  - {city['city_name']}")


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

async def get_cities_by_country_async(country_name):
    """Obtener ciudades por país de forma asíncrona."""
    params = {
        'apikey': API_KEY,
        'country': country_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 países concurrentemente
async def get_cities_for_multiple_countries(countries):
    """Obtener ciudades de múltiples países concurrentemente."""
    tasks = [get_cities_by_country_async(country) for country in countries]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(countries, results))

# Uso
# countries = ['United States', 'Spain', 'Germany', 'France']
# results = asyncio.run(get_cities_for_multiple_countries(countries))
# for country, cities in results.items():
#     if isinstance(cities, list):
#         print(f"{country}: {len(cities)} ciudades")

cURL

# Obtener ciudades de Estados Unidos
curl -X GET "https://api.countrydataapi.com/v1/cities/country?apikey=TU_CLAVE_API&country=United%20States&lang=en"

# Obtener ciudades de España
curl -X GET "https://api.countrydataapi.com/v1/cities/country?apikey=TU_CLAVE_API&country=Spain&lang=en"

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

# Limitar uso de tokens
curl -X GET "https://api.countrydataapi.com/v1/cities/country?apikey=TU_CLAVE_API&country=France&limitToken=500"

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

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

# Obtener ciudades de múltiples países
for country in "United States" Spain Germany France; do
  echo "País: $country"
  curl -s "https://api.countrydataapi.com/v1/cities/country?apikey=TU_CLAVE_API&country=$country" | json_pp | head -20
  echo ""
done

# Contar ciudades por país
for country in "United States" Spain Germany; do
  count=$(curl -s "https://api.countrydataapi.com/v1/cities/country?apikey=TU_CLAVE_API&country=$country" | jq '. | length')
  echo "$country: $count ciudades"
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 país faltante
401 Unauthorized - Clave API inválida o faltante
403 Forbidden - Permisos insuficientes o saldo de tokens
404 Not Found - País no encontrado
429 Too Many Requests - Límite de tasa excedido
500 Internal Server Error

Ejemplo de respuesta de error

{
  "statusCode": 404,
  "message": "Country 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, especialmente al consultar países con muchas ciudades.

Notas importantes

  • Países grandes: Países como Estados Unidos, China o Rusia pueden tener miles de ciudades. Usa limitToken para gestionar los costos.
  • Variaciones de nombre de país: Usa el nombre oficial en inglés del país para mejores resultados.
  • Rendimiento: Para países con muchas ciudades, considera almacenar en caché los resultados del lado del cliente para reducir las llamadas a la API.