curl 'https://api.countrystatecity.in/v1/changes?start_date=2026-08-01T00:00:00Z&country_code=IN&limit=100' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests
response = requests.get(
'https://api.countrystatecity.in/v1/changes',
params={'start_date': '2026-08-01T00:00:00Z', 'country_code': 'IN'},
headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'},
)
response.raise_for_status()
page = response.json()
{
"results": [
{
"change_id": "6b30c790-c46f-4a0f-b7f2-ea1a1a9d8362",
"data_version": "v3.2-export.7-2026.08.24",
"changed_at": "2026-08-24T08:15:00.000Z",
"place_type": "city",
"place_id": "57606",
"change_type": "renamed",
"old_values": {},
"new_values": {}
}
],
"next_page_token": "<string>"
}{
"status": "error",
"message": "start_date is older than the earliest available change. Changes are kept for 90 days.",
"details": {
"earliestAvailableDate": "2026-05-26T00:00:00.000Z"
}
}{
"error": "Unauthorized. You shouldn't be here."
}{
"status": "error",
"message": "This feature is not available on your current plan.",
"details": {
"feature": "dataChangeFeed",
"currentTier": "supporter",
"requiredTier": "professional",
"upgradeUrl": "https://countrystatecity.in/pricing"
}
}{
"error": "Daily usage limit exceeded. Please try again tomorrow or contact support for higher limits.",
"limit": 100,
"period": "daily",
"tier": "community",
"upgradeUrl": "https://countrystatecity.in/pricing"
}Data Change Feed
Keep your copy of Country State City data current without downloading the full dataset again
curl 'https://api.countrystatecity.in/v1/changes?start_date=2026-08-01T00:00:00Z&country_code=IN&limit=100' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests
response = requests.get(
'https://api.countrystatecity.in/v1/changes',
params={'start_date': '2026-08-01T00:00:00Z', 'country_code': 'IN'},
headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'},
)
response.raise_for_status()
page = response.json()
{
"results": [
{
"change_id": "6b30c790-c46f-4a0f-b7f2-ea1a1a9d8362",
"data_version": "v3.2-export.7-2026.08.24",
"changed_at": "2026-08-24T08:15:00.000Z",
"place_type": "city",
"place_id": "57606",
"change_type": "renamed",
"old_values": {},
"new_values": {}
}
],
"next_page_token": "<string>"
}{
"status": "error",
"message": "start_date is older than the earliest available change. Changes are kept for 90 days.",
"details": {
"earliestAvailableDate": "2026-05-26T00:00:00.000Z"
}
}{
"error": "Unauthorized. You shouldn't be here."
}{
"status": "error",
"message": "This feature is not available on your current plan.",
"details": {
"feature": "dataChangeFeed",
"currentTier": "supporter",
"requiredTier": "professional",
"upgradeUrl": "https://countrystatecity.in/pricing"
}
}{
"error": "Daily usage limit exceeded. Please try again tomorrow or contact support for higher limits.",
"limit": 100,
"period": "daily",
"tier": "community",
"upgradeUrl": "https://countrystatecity.in/pricing"
}403 on Community, Starter, Supporter, and Legacy plans. Compare plans to add the change feed to your API key.When to use it
Use the feed to keep a local search index, checkout form, analytics database, or cached copy up to date. Every change has a stablechange_id, the affected place_id, and the data_version that produced it.
Changes are available for 90 days. Run your sync regularly and save the change_id values you have applied so retrying a page cannot create duplicates.
Change types
| Value | Meaning |
|---|---|
added | A new place was added. |
removed | A place was removed. |
renamed | Its name changed. |
place_group_changed | Its region, administrative type, or city kind changed. |
parent_changed | A state moved to another country, or a city moved to another state/country. |
coordinates_changed | Its latitude or longitude changed. |
other_fields_changed | Another public field changed. |
change_type, but old_values and new_values include every changed field.
Response
The API returns changes from oldest to newest.{
"results": [
{
"change_id": "6b30c790-c46f-4a0f-b7f2-ea1a1a9d8362",
"data_version": "v3.2-export.7-2026.08.24",
"changed_at": "2026-08-24T08:15:00.000Z",
"place_type": "city",
"place_id": "132649",
"change_type": "renamed",
"old_values": { "name": "Bombay" },
"new_values": { "name": "Mumbai" }
}
],
"next_page_token": "H2gwOstvc3hy5O7cW1bK0T5S1m4f8h2wYQ"
}
old_values and new_values contain only fields allowed for your API key. The endpoint is not cached, so it does not return ETag or X-Cache.Read every page safely
The first request fixes the result set. Later pages do not suddenly include a release published while you are syncing. After the last page, start a new request to collect newer changes. For page two and later, send the token by itself. Do not change the original filters.let url = new URL('https://api.countrystatecity.in/v1/changes');
url.searchParams.set('start_date', '2026-08-01T00:00:00Z');
url.searchParams.set('country_code', 'IN');
url.searchParams.set('limit', '100');
while (url) {
const response = await fetch(url, {
headers: { 'X-CSCAPI-KEY': 'YOUR_API_KEY' }
});
if (!response.ok) throw new Error(await response.text());
const page = await response.json();
for (const change of page.results) {
console.log(change);
// Apply it to your database and save change.change_id.
}
url = page.next_page_token
? new URL(`https://api.countrystatecity.in/v1/changes?next_page_token=${encodeURIComponent(page.next_page_token)}`)
: null;
}
curl 'https://api.countrystatecity.in/v1/changes?start_date=2026-08-01T00:00:00Z&country_code=IN&limit=100' \
-H 'X-CSCAPI-KEY: YOUR_API_KEY'
import requests
response = requests.get(
'https://api.countrystatecity.in/v1/changes',
params={'start_date': '2026-08-01T00:00:00Z', 'country_code': 'IN'},
headers={'X-CSCAPI-KEY': 'YOUR_API_KEY'},
)
response.raise_for_status()
page = response.json()
Recover from errors
Ifstart_date is older than the retained data, use details.earliestAvailableDate to restart from the oldest available change:
{
"status": "error",
"message": "start_date is older than the earliest available change. Changes are kept for 90 days.",
"details": {
"earliestAvailableDate": "2026-05-26T00:00:00.000Z"
}
}
start_date and no token. Reusing saved change_id values prevents duplicate work. If your sync has been offline for more than 90 days, download a fresh full dataset before continuing.
Lower plans receive a plan-gate response:
{
"status": "error",
"message": "This feature is not available on your current plan.",
"details": {
"feature": "dataChangeFeed",
"currentTier": "supporter",
"requiredTier": "professional",
"upgradeUrl": "https://app.countrystatecity.in/pricing"
}
}
Start syncing changes
Compare API plans
Get Data Version
Authorizations
API key for authentication. Get your free key at app.countrystatecity.in.
Query Parameters
Return changes at or after this ISO 8601 timestamp. A date older than the earliest retained change returns 400 with details.earliestAvailableDate.
"2026-08-01T00:00:00Z"
Return changes for one place type
country, state, city "city"
Return changes for a country and its states and cities. Uses an ISO 3166-1 alpha-2 code.
2^[A-Za-z]{2}$"IN"
Return one kind of change
added, removed, renamed, place_group_changed, parent_changed, coordinates_changed, other_fields_changed "renamed"
Maximum records per page (1–100)
1 <= x <= 10050
Opaque cursor returned by the previous page. It expires after 24 hours. Omit the original filters, or resend all of them unchanged.
1 - 4096^[A-Za-z0-9_-]+$Response
A page from the fixed change-feed snapshot. This endpoint is not cached and does not return Cache-Control, ETag, or X-Cache.