Documentación de la API - Endpoints y Ejemplos

Buscar estados por ciudad

Descripcion general

Este endpoint te permite encontrar el estado que contiene una ciudad específica. Es útil para búsquedas inversas cuando conoces el nombre de la ciudad pero necesitas determinar su estado padre. Ten en cuenta que muchas ciudades en el mundo comparten el mismo nombre, por lo que la API puede devolver múltiples resultados de diferentes países.

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/states/city

Retorna el estado que contiene esa ciudad.

Algunos ejemplos de la estructura

País: EEUU, Estado: Colorado, Ciudad: Denver

País: España, Estado: Comunidad Valenciana, Ciudad: Valencia

Información relevante

Ten en cuenta que hay muchas ciudades con el mismo nombre

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ámetros de consulta


Parámetro Tipo Descripción
apikey requerido, token Clave de autenticación de la cuenta
city requerido, string Nombre de la ciudad que se encuentra en el estado
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

Respuesta

Ejemplo de 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"
    ]
  }
]

Ejemplos de código

JavaScript (Fetch)

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

async function getStateByCity(cityName) {
  try {
    const params = new URLSearchParams({
      apikey: API_KEY,
      city: cityName,
      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 que contienen la ciudad "${cityName}":`, states);
    return states;
  } catch (error) {
    console.error('Error fetching state by city:', error);
    throw error;
  }
}

// Uso - Nota: Pueden devolverse múltiples estados si el nombre de la ciudad existe en diferentes regiones
getStateByCity('Denver');
getStateByCity('Valencia');
getStateByCity('Springfield'); // Nombre de ciudad común - devolverá múltiples resultados

JavaScript (Axios)

import axios from 'axios';

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

async function getStateByCity(cityName) {
  try {
    const response = await axios.get(BASE_URL, {
      params: {
        apikey: API_KEY,
        city: cityName,
        lang: 'en',
        fields: 'id,state_name,lang'
      }
    });

    console.log(`Estados que contienen la ciudad "${cityName}":`, response.data);
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      console.error('API Error:', error.response?.data || error.message);
    }
    throw error;
  }
}

// Uso
getStateByCity('Miami');

React

import { useState, useEffect } from 'react';

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

function StateByCity({ cityName }) {
  const [states, setStates] = useState([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchStateByCity = async () => {
      if (!cityName) {
        setStates([]);
        return;
      }

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

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

    fetchStateByCity();
  }, [cityName]);

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

  return (
    <div>
      <h2>Estados que contienen "{cityName}"</h2>
      {states.length === 0 ? (
        <p>No se encontraron estados para esta ciudad</p>
      ) : (
        <>
          <p>Se encontraron {states.length} estado(s)</p>
          <ul>
            {states.map((state) => (
              <li key={state.id}>
                {state.state_name}
              </li>
            ))}
          </ul>
        </>
      )}
    </div>
  );
}

// Componente de búsqueda de ciudad con input
function CityStateSearch() {
  const [cityInput, setCityInput] = useState('');
  const [searchCity, setSearchCity] = useState('');

  const handleSearch = (e) => {
    e.preventDefault();
    setSearchCity(cityInput);
  };

  return (
    <div>
      <form onSubmit={handleSearch}>
        <input
          type="text"
          value={cityInput}
          onChange={(e) => setCityInput(e.target.value)}
          placeholder="Ingresa el nombre de la ciudad..."
        />
        <button type="submit">Buscar</button>
      </form>

      {searchCity && <StateByCity cityName={searchCity} />}
    </div>
  );
}

export default CityStateSearch;

Vue 3

<template>
  <div>
    <div v-if="loading">Buscando estados...</div>
    <div v-else-if="error">Error: {{ error }}</div>
    <div v-else>
      <h2>Estados que contienen "{{ city }}"</h2>
      <p v-if="states.length === 0">No se encontraron estados para esta ciudad</p>
      <div v-else>
        <p>Se encontraron {{ states.length }} estado(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({
  city: {
    type: String,
    required: true
  }
});

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

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

const fetchStateByCity = async () => {
  if (!props.city) {
    states.value = [];
    return;
  }

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

    const params = new URLSearchParams({
      apikey: API_KEY,
      city: props.city,
      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.city, fetchStateByCity);
onMounted(fetchStateByCity);
</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 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-city',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `
    <div>
      <div *ngIf="loading">Buscando estados...</div>
      <div *ngIf="error">Error: {{ error }}</div>
      <div *ngIf="!loading && !error">
        <h2>Estados que contienen "{{ city }}"</h2>
        <p *ngIf="states.length === 0">No se encontraron estados para esta ciudad</p>
        <div *ngIf="states.length > 0">
          <p>Se encontraron {{ states.length }} estado(s)</p>
          <ul>
            <li *ngFor="let state of states">{{ state.state_name }}</li>
          </ul>
        </div>
      </div>
    </div>
  `
})
export class StateByCityComponent implements OnInit, OnChanges {
  @Input() city!: string;

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

  states: State[] = [];
  loading = false;
  error: string | null = null;

  constructor(private http: HttpClient) {}

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

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

  private fetchStateByCity(): void {
    if (!this.city) {
      this.states = [];
      return;
    }

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

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

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

      <app-state-by-city
        *ngIf="searchCity"
        [city]="searchCity"
      ></app-state-by-city>
    </div>
  `
})
export class CityStateSearchComponent {
  cityInput = '';
  searchCity = '';

  search(): void {
    this.searchCity = this.cityInput;
  }
}

PHP

<?php

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

function getStateByCity($cityName, $apiKey) {
    $baseUrl = 'https://api.countrydataapi.com/v1/states/city';

    $params = http_build_query([
        'apikey' => $apiKey,
        'city' => $cityName,
        '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 {
    $cityName = 'Denver';
    $states = getStateByCity($cityName, $apiKey);

    echo "Estados que contienen '$cityName':\n";
    echo "Se encontraron " . count($states) . " estado(s)\n\n";

    foreach ($states as $state) {
        echo "- " . $state['state_name'] . " (ID: " . $state['id'] . ")\n";
    }
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

// Manejar múltiples ciudades con el mismo nombre
function findStatesForCity($cityName, $apiKey) {
    $states = getStateByCity($cityName, $apiKey);

    if (empty($states)) {
        return "No se encontraron estados para la ciudad: $cityName";
    }

    if (count($states) === 1) {
        return "La ciudad '$cityName' está ubicada en: " . $states[0]['state_name'];
    }

    $stateNames = array_map(function($s) {
        return $s['state_name'];
    }, $states);

    return "La ciudad '$cityName' existe en múltiples estados: " . implode(', ', $stateNames);
}

echo findStatesForCity('Springfield', $apiKey); // Mostrará múltiples estados
?>

Python

import requests

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

def get_state_by_city(city_name):
    """Encontrar el/los estado(s) que contienen una ciudad específica."""
    params = {
        'apikey': API_KEY,
        'city': city_name,
        '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 city: {e}')
        raise

# Uso
if __name__ == '__main__':
    city = 'Denver'
    states = get_state_by_city(city)

    print(f"Estados que contienen '{city}':")
    print(f"Se encontraron {len(states)} estado(s)\n")

    for state in states:
        print(f"  - {state['state_name']} (ID: {state['id']})")

    # Ejemplo con un nombre de ciudad común
    print("\n--- Buscando 'Springfield' (nombre común) ---")
    springfield_states = get_state_by_city('Springfield')
    print(f"Se encontraron {len(springfield_states)} estados con ciudad llamada 'Springfield'")


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

async def get_state_by_city_async(city_name):
    """Encontrar estado por ciudad de forma asíncrona."""
    params = {
        'apikey': API_KEY,
        'city': city_name,
        '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}')

# Buscar múltiples ciudades concurrentemente
async def search_multiple_cities(cities):
    """Buscar estados para múltiples ciudades concurrentemente."""
    tasks = [get_state_by_city_async(city) for city in cities]
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return dict(zip(cities, results))

# Uso
# cities = ['Denver', 'Miami', 'Seattle', 'Austin']
# results = asyncio.run(search_multiple_cities(cities))
# for city, states in results.items():
#     print(f"{city}: {[s['state_name'] for s in states]}")

cURL

# Buscar estado por nombre de ciudad
curl -X GET "https://api.countrydataapi.com/v1/states/city?apikey=TU_CLAVE_API&city=Denver&lang=en&fields=id,state_name,lang"

# Buscar Valencia (existe en múltiples países)
curl -X GET "https://api.countrydataapi.com/v1/states/city?apikey=TU_CLAVE_API&city=Valencia&lang=en"

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

# Buscar un nombre de ciudad común (devuelve múltiples resultados)
curl -X GET "https://api.countrydataapi.com/v1/states/city?apikey=TU_CLAVE_API&city=Springfield&lang=en"

# Obtener información detallada del estado incluyendo ciudades
curl -X GET "https://api.countrydataapi.com/v1/states/city?apikey=TU_CLAVE_API&city=Boston&fields=id,state_name,state_cities"

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

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

  • Nombres de ciudades duplicados: Muchas ciudades comparten el mismo nombre en diferentes estados y países. Por ejemplo, "Springfield" existe en múltiples estados de EE.UU. La API devolverá todos los estados coincidentes.
  • Desambiguación: Si recibes múltiples resultados, considera usar parámetros adicionales o filtrar por país para acotar los resultados.
  • Sensibilidad a mayúsculas/minúsculas: Los nombres de ciudades no distinguen mayúsculas de minúsculas, pero se recomienda usar la capitalización correcta.