Complete Integration Examples
Basic API Client Setup
Set up a robust API client with proper authentication, error handling, and rate limiting:Copy
Ask AI
class CountryStateCityAPI {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseURL = 'https://api.countrystatecity.in/v1';
}
async request(endpoint) {
try {
const response = await fetch(`${this.baseURL}${endpoint}`, {
headers: {
'X-CSCAPI-KEY': this.apiKey,
'Content-Type': 'application/json'
}
});
if (!response.ok) {
if (response.status === 401) {
throw new Error('Invalid API key. Please check your credentials.');
} else if (response.status === 429) {
throw new Error('Rate limit exceeded. Please try again later.');
} else {
throw new Error(`API error: ${response.status}`);
}
}
return await response.json();
} catch (error) {
console.error('API request failed:', error);
throw error;
}
}
async getCountries() {
return await this.request('/countries');
}
async getStates(countryCode) {
return await this.request(`/countries/${countryCode}/states`);
}
async getCities(countryCode, stateCode = null) {
const endpoint = stateCode
? `/countries/${countryCode}/states/${stateCode}/cities`
: `/countries/${countryCode}/cities`;
return await this.request(endpoint);
}
async getCountryDetails(countryCode) {
return await this.request(`/countries/${countryCode}`);
}
}
// Usage
const api = new CountryStateCityAPI('YOUR_API_KEY');
const countries = await api.getCountries();
const usStates = await api.getStates('US');
const californiaCities = await api.getCities('US', 'CA');
Real-World Use Cases
1. Complete Registration Form with Cascading Dropdowns
Build a comprehensive user registration form with dependent location selectors:Copy
Ask AI
import React, { useState, useEffect } from 'react';
const LocationSelector = ({ apiKey, onLocationChange }) => {
const [countries, setCountries] = useState([]);
const [states, setStates] = useState([]);
const [cities, setCities] = useState([]);
const [selectedCountry, setSelectedCountry] = useState('');
const [selectedState, setSelectedState] = useState('');
const [selectedCity, setSelectedCity] = useState('');
const [loading, setLoading] = useState(false);
const api = new CountryStateCityAPI(apiKey);
// Load countries on component mount
useEffect(() => {
const loadCountries = async () => {
try {
setLoading(true);
const countriesData = await api.getCountries();
setCountries(countriesData);
} catch (error) {
console.error('Failed to load countries:', error);
} finally {
setLoading(false);
}
};
loadCountries();
}, []);
// Load states when country changes
useEffect(() => {
if (selectedCountry) {
const loadStates = async () => {
try {
setLoading(true);
const statesData = await api.getStates(selectedCountry);
setStates(statesData);
setSelectedState(''); // Reset state selection
setCities([]); // Clear cities
setSelectedCity(''); // Reset city selection
} catch (error) {
console.error('Failed to load states:', error);
} finally {
setLoading(false);
}
};
loadStates();
}
}, [selectedCountry]);
// Load cities when state changes
useEffect(() => {
if (selectedCountry && selectedState) {
const loadCities = async () => {
try {
setLoading(true);
const citiesData = await api.getCities(selectedCountry, selectedState);
setCities(citiesData);
setSelectedCity(''); // Reset city selection
} catch (error) {
console.error('Failed to load cities:', error);
} finally {
setLoading(false);
}
};
loadCities();
}
}, [selectedState]);
return (
<div className="location-selector">
<div className="form-group">
<label htmlFor="country">Country *</label>
<select
id="country"
value={selectedCountry}
onChange={(e) => setSelectedCountry(e.target.value)}
disabled={loading}
required
>
<option value="">Select Country</option>
{countries.map(country => (
<option key={country.iso2} value={country.iso2}>
{country.emoji} {country.name}
</option>
))}
</select>
</div>
<div className="form-group">
<label htmlFor="state">State/Province *</label>
<select
id="state"
value={selectedState}
onChange={(e) => setSelectedState(e.target.value)}
disabled={loading || !selectedCountry}
required
>
<option value="">Select State</option>
{states.map(state => (
<option key={state.iso2} value={state.iso2}>
{state.name}
</option>
))}
</select>
</div>
<div className="form-group">
<label htmlFor="city">City *</label>
<select
id="city"
value={selectedCity}
onChange={(e) => setSelectedCity(e.target.value)}
disabled={loading || !selectedState}
required
>
<option value="">Select City</option>
{cities.map(city => (
<option key={city.id} value={city.id}>
{city.name}
</option>
))}
</select>
</div>
{loading && <div className="loading">Loading...</div>}
</div>
);
};
2. E-commerce Shipping Calculator
Calculate shipping costs and delivery times based on geographical locations:Copy
Ask AI
class ShippingCalculator {
constructor(apiKey) {
this.api = new CountryStateCityAPI(apiKey);
this.shippingRates = {
domestic: { base: 5.99, perKg: 1.50, deliveryDays: '2-3' },
international: {
asia: { base: 25.99, perKg: 8.50, deliveryDays: '7-10' },
europe: { base: 29.99, perKg: 9.50, deliveryDays: '7-12' },
americas: { base: 19.99, perKg: 7.50, deliveryDays: '5-8' },
africa: { base: 35.99, perKg: 12.50, deliveryDays: '10-15' }
}
};
}
async calculateShipping(fromCountryCode, toCountryCode, weight) {
try {
const [fromCountry, toCountry] = await Promise.all([
this.api.getCountryDetails(fromCountryCode),
this.api.getCountryDetails(toCountryCode)
]);
// Domestic shipping
if (fromCountryCode === toCountryCode) {
const rate = this.shippingRates.domestic;
return {
cost: rate.base + (weight * rate.perKg),
deliveryTime: rate.deliveryDays,
type: 'Domestic',
from: fromCountry.name,
to: toCountry.name
};
}
// International shipping
const toRegion = this.getRegion(toCountry.region);
const rate = this.shippingRates.international[toRegion];
return {
cost: rate.base + (weight * rate.perKg),
deliveryTime: rate.deliveryDays,
type: 'International',
region: toRegion,
from: fromCountry.name,
to: toCountry.name
};
} catch (error) {
throw new Error(`Shipping calculation failed: ${error.message}`);
}
}
getRegion(countryRegion) {
const regionMap = {
'Asia': 'asia',
'Europe': 'europe',
'Americas': 'americas',
'Africa': 'africa'
};
return regionMap[countryRegion] || 'international';
}
}
// Usage
const calculator = new ShippingCalculator('YOUR_API_KEY');
const shippingInfo = await calculator.calculateShipping('US', 'CA', 2.5);
console.log(`Shipping cost: $${shippingInfo.cost.toFixed(2)}`);
console.log(`Delivery: ${shippingInfo.deliveryTime} business days`);
3. Multi-Currency Price Display
Display prices in local currencies based on user location:Copy
Ask AI
class PriceLocalization {
constructor(apiKey) {
this.api = new CountryStateCityAPI(apiKey);
this.exchangeRates = {}; // Cache exchange rates
this.baseCurrency = 'USD';
}
async getLocalizedPrice(basePrice, userCountryCode) {
try {
const country = await this.api.getCountryDetails(userCountryCode);
const currency = country.currency;
if (currency === this.baseCurrency) {
return {
amount: basePrice,
currency: currency,
symbol: country.currency_symbol || '$',
formatted: `${country.currency_symbol || '$'}${basePrice.toFixed(2)}`
};
}
// Get exchange rate (you'd typically use a service like exchangerates-api.io)
const rate = await this.getExchangeRate(this.baseCurrency, currency);
const localAmount = basePrice * rate;
return {
amount: localAmount,
currency: currency,
symbol: country.currency_symbol || '',
formatted: `${country.currency_symbol || ''}${localAmount.toFixed(2)}`,
exchangeRate: rate,
originalPrice: basePrice,
originalCurrency: this.baseCurrency
};
} catch (error) {
console.error('Price localization failed:', error);
// Fallback to base price
return {
amount: basePrice,
currency: this.baseCurrency,
symbol: '$',
formatted: `$${basePrice.toFixed(2)}`
};
}
}
async getExchangeRate(from, to) {
// This is a placeholder - use a real exchange rate service
const cacheKey = `${from}-${to}`;
if (this.exchangeRates[cacheKey] &&
this.exchangeRates[cacheKey].timestamp > Date.now() - 3600000) {
return this.exchangeRates[cacheKey].rate;
}
// Mock exchange rate - replace with real service
const mockRates = { 'EUR': 0.85, 'GBP': 0.73, 'CAD': 1.25, 'INR': 74.5 };
const rate = mockRates[to] || 1;
this.exchangeRates[cacheKey] = {
rate: rate,
timestamp: Date.now()
};
return rate;
}
}
Best Practices and Optimization
Caching Strategy for Performance
Implement intelligent caching to minimize API calls and improve performance:Copy
Ask AI
class OptimizedCountryStateCityAPI extends CountryStateCityAPI {
constructor(apiKey, cacheOptions = {}) {
super(apiKey);
this.cache = new Map();
this.cacheTTL = cacheOptions.ttl || 3600000; // 1 hour default
this.requestQueue = new Map(); // Prevent duplicate requests
}
async request(endpoint) {
// Check cache first
const cached = this.cache.get(endpoint);
if (cached && Date.now() - cached.timestamp < this.cacheTTL) {
return cached.data;
}
// Check if request is already in progress
if (this.requestQueue.has(endpoint)) {
return await this.requestQueue.get(endpoint);
}
// Make request and cache the promise
const requestPromise = super.request(endpoint);
this.requestQueue.set(endpoint, requestPromise);
try {
const data = await requestPromise;
this.cache.set(endpoint, {
data,
timestamp: Date.now()
});
return data;
} finally {
this.requestQueue.delete(endpoint);
}
}
// Preload commonly used data
async preloadEssentials() {
const essentials = [
'/countries',
'/countries/US/states',
'/countries/GB/states',
'/countries/CA/states'
];
await Promise.all(essentials.map(endpoint => this.request(endpoint)));
}
}
Rate Limiting and Error Handling
Implement robust error handling and rate limiting strategies:Copy
Ask AI
class ResilientCountryStateCityAPI extends CountryStateCityAPI {
constructor(apiKey, options = {}) {
super(apiKey);
this.maxRetries = options.maxRetries || 3;
this.baseDelay = options.baseDelay || 1000;
this.requestsPerSecond = options.requestsPerSecond || 2;
this.requestQueue = [];
this.processing = false;
this.startRequestProcessor();
}
async request(endpoint) {
return new Promise((resolve, reject) => {
this.requestQueue.push({ endpoint, resolve, reject, retries: 0 });
this.processQueue();
});
}
async processQueue() {
if (this.processing || this.requestQueue.length === 0) return;
this.processing = true;
while (this.requestQueue.length > 0) {
const { endpoint, resolve, reject, retries } = this.requestQueue.shift();
try {
const data = await this.makeRequestWithRetry(endpoint, retries);
resolve(data);
} catch (error) {
reject(error);
}
// Rate limiting: wait between requests
await this.sleep(1000 / this.requestsPerSecond);
}
this.processing = false;
}
async makeRequestWithRetry(endpoint, retries) {
try {
return await super.request(endpoint);
} catch (error) {
if (retries >= this.maxRetries) {
throw error;
}
if (error.message.includes('Rate limit exceeded') ||
error.message.includes('500') ||
error.message.includes('503')) {
const delay = this.baseDelay * Math.pow(2, retries);
await this.sleep(delay);
return this.makeRequestWithRetry(endpoint, retries + 1);
}
throw error;
}
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
startRequestProcessor() {
setInterval(() => this.processQueue(), 100);
}
}
Need More Help?
API Reference
Complete API documentation with all endpoints and parameters.
SDKs & Libraries
Official SDKs and community libraries for popular programming languages.
Rate Limits
Understanding rate limits and best practices for high-volume usage.
Support
Get help from our community and support team.
All code examples are production-ready and include proper error handling, caching, and rate limiting. Remember to replace
YOUR_API_KEY
with your actual API key from the Country State City portal.