Documentación de la API - Endpoints y Ejemplos

Todos los Datos de una Ciudad

Descripción general

Este endpoint recupera datos completos de una ciudad específica por su ID o nombre. Proporciona información detallada sobre una ciudad particular, incluyendo todos los campos disponibles para esa ubicación.

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/

Retorna todos los datos de una ciudad

Cada ciudad retornada consumirá 1 token

Parámetros de consulta


Parámetro Tipo Descripción
apikey requerido, token Clave de autenticación de la cuenta
city requerido, id o string ID o nombre de la ciudad
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/';

async function getCityData(cityNameOrId) {
  try {
    const params = new URLSearchParams({
      apikey: API_KEY,
      city: cityNameOrId,
      lang: 'en'
    });

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

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

    const cityData = await response.json();
    console.log('City Data:', cityData);
    return cityData;
  } catch (error) {
    console.error('Error fetching city data:', error);
    throw error;
  }
}

// Uso - por nombre de ciudad
getCityData('Denver');
getCityData('New York');

// Uso - por ID de ciudad
getCityData('d54ba796-1136-4776-9776-537fd5a857c9');

JavaScript (Axios)

import axios from 'axios';

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

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

    console.log('City Data:', response.data);
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error('API Error:', error.response?.data || error.message);
    }
    throw error;
  }
}

// Uso
getCityData('Los Angeles');

React

import { useState, useEffect } from 'react';

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

function CityDetails({ cityName }) {
  const [cityData, setCityData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchCityData = async () => {
      if (!cityName) {
        setCityData(null);
        return;
      }

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

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

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

        if (!response.ok) {
          throw new Error('City not found');
        }

        const data = await response.json();
        setCityData(data[0] || null);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchCityData();
  }, [cityName]);

  if (loading) return <div>Cargando datos de la ciudad...</div>;
  if (error) return <div>Error: {error}</div>;
  if (!cityData) return <div>Introduce un nombre de ciudad para buscar</div>;

  return (
    <div>
      <h2>{cityData.city_name}</h2>
      <p>ID: {cityData.id}</p>
      <p>Idioma: {cityData.lang}</p>
    </div>
  );
}

// Búsqueda de ciudad con autocompletado
function CitySearch() {
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedCity, setSelectedCity] = useState('');

  const handleSearch = (e) => {
    e.preventDefault();
    setSelectedCity(searchTerm);
  };

  return (
    <div>
      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={searchTerm}
          onChange={(e) => setSearchTerm(e.target.value)}
          placeholder="Introduce nombre de ciudad..."
        />
        <button type="submit">Buscar</button>
      </form>

      {selectedCity && <CityDetails cityName={selectedCity} />}
    </div>
  );
}

export default CitySearch;

Vue 3

<template>
  <div>
    <div v-if="loading">Cargando datos de la ciudad...</div>
    <div v-else-if="error">Error: {{ error }}</div>
    <div v-else-if="cityData">
      <h2>{{ cityData.city_name }}</h2>
      <p>ID: {{ cityData.id }}</p>
      <p>Idioma: {{ cityData.lang }}</p>
    </div>
    <div v-else>Introduce un nombre de ciudad para buscar</div>
  </div>
</template>

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

const props = defineProps({
  cityName: {
    type: String,
    default: ''
  }
});

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

const cityData = ref(null);
const loading = ref(false);
const error = ref(null);

const fetchCityData = async () => {
  if (!props.cityName) {
    cityData.value = null;
    return;
  }

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

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

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

    if (!response.ok) {
      throw new Error('City not found');
    }

    const data = await response.json();
    cityData.value = data[0] || null;
  } catch (err) {
    error.value = err.message;
  } finally {
    loading.value = false;
  }
};

watch(() => props.cityName, fetchCityData);
onMounted(() => {
  if (props.cityName) {
    fetchCityData();
  }
});
</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-city-details',
  standalone: true,
  imports: [CommonModule],
  template: `
    <div>
      <div *ngIf="loading">Cargando datos de la ciudad...</div>
      <div *ngIf="error">Error: {{ error }}</div>
      <div *ngIf="!loading && !error && cityData">
        <h2>{{ cityData.city_name }}</h2>
        <p>ID: {{ cityData.id }}</p>
        <p>Idioma: {{ cityData.lang }}</p>
      </div>
      <div *ngIf="!loading && !error && !cityData">
        Introduce un nombre de ciudad para buscar
      </div>
    </div>
  `
})
export class CityDetailsComponent implements OnInit, OnChanges {
  @Input() cityName = '';

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

  cityData: City | null = null;
  loading = false;
  error: string | null = null;

  constructor(private http: HttpClient) {}

  ngOnInit(): void {
    if (this.cityName) {
      this.fetchCityData();
    }
  }

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

  private fetchCityData(): void {
    if (!this.cityName) {
      this.cityData = null;
      return;
    }

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

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

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

// Componente de búsqueda de ciudad
@Component({
  selector: 'app-city-search',
  standalone: true,
  imports: [CommonModule, FormsModule, CityDetailsComponent],
  template: `
    <div>
      <form (ngSubmit)="search()">
        <input
          type="text"
          [(ngModel)]="searchTerm"
          name="city"
          placeholder="Introduce nombre de ciudad..."
        />
        <button type="submit">Buscar</button>
      </form>

      <app-city-details
        *ngIf="selectedCity"
        [cityName]="selectedCity"
      ></app-city-details>
    </div>
  `
})
export class CitySearchComponent {
  searchTerm = '';
  selectedCity = '';

  search(): void {
    this.selectedCity = this.searchTerm;
  }
}

PHP

<?php

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

function getCityData($cityNameOrId, $apiKey) {
    $baseUrl = 'https://api.countrydataapi.com/v1/cities/';

    $params = http_build_query([
        'apikey' => $apiKey,
        'city' => $cityNameOrId,
        'lang' => 'en'
    ]);

    $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 - por nombre de ciudad
try {
    $cityName = 'Denver';
    $cities = getCityData($cityName, $apiKey);

    if (!empty($cities)) {
        $city = $cities[0];
        echo "Ciudad: " . $city['city_name'] . "\n";
        echo "ID: " . $city['id'] . "\n";
        echo "Idioma: " . $city['lang'] . "\n";
    } else {
        echo "Ciudad no encontrada\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

// Uso - por ID de ciudad
try {
    $cityId = 'd54ba796-1136-4776-9776-537fd5a857c9';
    $cities = getCityData($cityId, $apiKey);

    if (!empty($cities)) {
        $city = $cities[0];
        echo "Encontrada ciudad por ID: " . $city['city_name'] . "\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

Python

import requests

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

def get_city_data(city_name_or_id):
    """Obtener datos detallados de una ciudad específica."""
    params = {
        'apikey': API_KEY,
        'city': city_name_or_id,
        'lang': 'en'
    }

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

        city_data = response.json()
        return city_data[0] if city_data else None
    except requests.exceptions.RequestException as e:
        print(f'Error fetching city data: {e}')
        raise

# Uso
if __name__ == '__main__':
    # Buscar por nombre de ciudad
    city = get_city_data('Denver')

    if city:
        print(f"Ciudad: {city['city_name']}")
        print(f"ID: {city['id']}")
        print(f"Idioma: {city['lang']}")
    else:
        print("Ciudad no encontrada")

    # Buscar por ID de ciudad
    city_by_id = get_city_data('d54ba796-1136-4776-9776-537fd5a857c9')
    if city_by_id:
        print(f"\nEncontrada por ID: {city_by_id['city_name']}")


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

async def get_city_data_async(city_name_or_id):
    """Obtener datos de ciudad de forma asíncrona."""
    params = {
        'apikey': API_KEY,
        'city': city_name_or_id,
        'lang': 'en'
    }

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

# Obtener múltiples ciudades concurrentemente
async def get_multiple_cities(city_names):
    """Obtener múltiples ciudades concurrentemente."""
    tasks = [get_city_data_async(name) for name in city_names]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(city_names, results))

# Uso
# cities = ['Denver', 'Miami', 'Seattle', 'Boston']
# results = asyncio.run(get_multiple_cities(cities))
# for name, data in results.items():
#     if data:
#         print(f"{name}: {data['id']}")

cURL

# Obtener datos de ciudad por nombre
curl -X GET "https://api.countrydataapi.com/v1/cities/?apikey=TU_CLAVE_API&city=Denver&lang=en"

# Obtener datos de ciudad por ID
curl -X GET "https://api.countrydataapi.com/v1/cities/?apikey=TU_CLAVE_API&city=d54ba796-1136-4776-9776-537fd5a857c9&lang=en"

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

# Obtener ciudad en español
curl -X GET "https://api.countrydataapi.com/v1/cities/?apikey=TU_CLAVE_API&city=Madrid&lang=es"

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

# Buscar múltiples ciudades
for city in Denver Miami Seattle Boston; do
  echo "Ciudad: $city"
  curl -s "https://api.countrydataapi.com/v1/cities/?apikey=TU_CLAVE_API&city=$city" | 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 ciudad faltante
401 Unauthorized - Clave API inválida o faltante
403 Forbidden - Permisos insuficientes o saldo de tokens
404 Not Found - Ciudad no encontrada
429 Too Many Requests - Límite de tasa excedido
500 Internal Server Error

Ejemplo de respuesta de error

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

Notas importantes

  • Variaciones de nombre de ciudad: Algunas ciudades tienen múltiples nombres o escrituras. Prueba diferentes variaciones si tu búsqueda inicial falla.
  • Nombres duplicados: Muchas ciudades comparten el mismo nombre (por ejemplo, "Springfield"). La API puede devolver múltiples resultados.
  • Usar ID de ciudad: Para búsquedas precisas, usa el ID único de la ciudad en lugar de su nombre.