> ## Documentation Index
> Fetch the complete documentation index at: https://docs.countrystatecity.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Change Feed

> Keep your copy of Country State City data current without downloading the full dataset again

If your app stores Country State City data in its own database, a full download is wasteful when only a few places changed. The change feed returns the countries, states, and cities that were added, removed, or updated so you can apply only those changes.

<Note>
  **Available on Professional and Business plans.** Returns `403` on Community, Starter, Supporter, and Legacy plans. [Compare plans](https://countrystatecity.in/pricing?source=docs\&campaign=data_change_feed) to add the change feed to your API key.
</Note>

## 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 stable `change_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. |

When several fields change in one release, the record has one main `change_type`, but `old_values` and `new_values` include every changed field.

## Response

The API returns changes from oldest to newest.

```json 200 - Renamed city theme={null}
{
  "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"
}
```

<Info>
  `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`.
</Info>

## 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.

```javascript JavaScript theme={null}
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;
}
```

<RequestExample>
  ```bash cURL theme={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'
  ```

  ```python Python theme={null}
  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()
  ```
</RequestExample>

## Recover from errors

If `start_date` is older than the retained data, use `details.earliestAvailableDate` to restart from the oldest available change:

```json 400 - Start date is too old theme={null}
{
  "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"
  }
}
```

If a token expires, is changed, or is invalid, start again with `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:

```json 403 - Professional plan required theme={null}
{
  "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

<CardGroup cols={2}>
  <Card title="Compare API plans" icon="credit-card" href="https://countrystatecity.in/pricing?source=docs&campaign=data_change_feed">
    Choose Professional or Business to keep your database current with small incremental requests.
  </Card>

  <Card title="Get Data Version" icon="clock-rotate-left" href="/api/endpoints/get-data-version">
    Check which dataset release your API responses use.
  </Card>
</CardGroup>


## OpenAPI

````yaml GET /changes
openapi: 3.0.3
info:
  title: Country State City API
  description: >-
    Geographic data API providing countries, states, cities, timezones,
    currencies, and phone dial codes with tiered access levels.


    ## Authentication

    All endpoints require an API key passed via the `X-CSCAPI-KEY` header. Get
    your free key at [app.countrystatecity.in](https://app.countrystatecity.in).


    ## Pricing & Limits

    The fields returned, endpoints available, and request quotas depend on your
    plan. See current tiers and limits at:


    **[countrystatecity.in/pricing](https://countrystatecity.in/pricing)**


    ## Data Access Levels

    Each plan includes a data access level that controls which fields are
    returned:


    - **Basic** — Core fields: id, name, iso2, iso3, phonecode, capital,
    currency, coordinates, region, timezones, emoji

    - **Coordinates** — Basic + extended metadata (population, tld, nationality,
    currency details, postal codes, etc.)

    - **Full** — All fields including translations (18+ languages) and
    wikiDataId


    Fields restricted to higher tiers are marked in each schema below.


    ## Feature Gating

    Some endpoints require a minimum tier. Restricted endpoints return `403`
    with an `upgradeUrl` when accessed on a lower plan. Check the [pricing
    page](https://countrystatecity.in/pricing) for current feature availability.


    ## Rate Limiting

    Requests exceeding your daily or monthly quota receive a `429` response with
    your current limit, period, tier, and an upgrade URL.


    ## Caching

    Cacheable geographic responses include `Cache-Control`, `ETag`, and
    `X-Cache` (HIT/MISS) headers; send `If-None-Match` on them to receive `304
    Not Modified`. Phone number parsing is never cached (`Cache-Control:
    no-store`, no `ETag`); see each endpoint for exceptions.


    ## Usage Headers

    All `/v1/*` responses include usage and plan headers:

    - `X-CSC-Plan` — your current tier

    - `X-CSC-Daily-Used` / `X-CSC-Daily-Limit` — today's usage vs limit

    - `X-CSC-Monthly-Used` / `X-CSC-Monthly-Limit` — this month's usage vs limit


    Use these to monitor consumption without a separate API call.
  contact:
    name: Darshan Gada (dr5hn)
    email: gadadarshan@gmail.com
    url: https://countrystatecity.in
  license:
    name: Creative Commons Attribution 4.0
    url: https://creativecommons.org/licenses/by/4.0/
  version: 2.4.1
servers:
  - url: https://api.countrystatecity.in/v1
    description: Production API
security: []
tags:
  - name: Countries
    description: Country data — 250+ countries with metadata, coordinates, and translations
  - name: States
    description: State/province/region data — 5,000+ subdivisions
  - name: Cities
    description: City data — 150,000+ cities worldwide
  - name: Postcodes
    description: >-
      Postcode and ZIP code lookup and search. Informational data, not address
      verification.
  - name: Regions
    description: Geographic regions and subregions — continental groupings of countries
  - name: Timezones
    description: >-
      IANA timezone lookup by country, state, or city — includes UTC offset and
      DST status
  - name: Currencies
    description: ISO 4217 currency data — list all currencies or look up by country
  - name: Phone
    description: >-
      International dial codes — list, lookup by country, and E.164 phone number
      parsing
  - name: ISO
    description: >-
      ISO 3166 code lookup and conversion — country (alpha-2/3/numeric) and
      state (ISO 3166-2)
  - name: Search
    description: Typo-tolerant fuzzy search across cities, states, and countries
  - name: Changes
    description: >-
      Data change feed — track additions, removals, and updates to place records
      over time. **Professional and Business plans only.**
  - name: Meta
    description: Information about the dataset release currently served
paths:
  /changes:
    get:
      tags:
        - Changes
      summary: List data changes
      description: >-
        Returns additions, removals, and updates to country, state, and city
        records, oldest first. Changes are retained for 90 days. Use this feed
        to keep a local copy in sync instead of downloading the full dataset
        again.


        Pagination is stable: the first request fixes the result set, and every
        `next_page_token` continues through that same snapshot. Changes
        published after page one are not added to later pages; start a new
        request to receive them. The token also carries the original filters, is
        valid for 24 hours, and must be treated as opaque.


        Fields inside `old_values` and `new_values` follow the caller's data
        access level.


        **Availability:** Professional and Business plans only. [Compare
        plans](https://countrystatecity.in/pricing?source=api_playground&campaign=data_change_feed).
      operationId: listChanges
      parameters:
        - name: start_date
          in: query
          description: >-
            Return changes at or after this ISO 8601 timestamp. A date older
            than the earliest retained change returns `400` with
            `details.earliestAvailableDate`.
          required: false
          schema:
            type: string
            format: date-time
            example: '2026-08-01T00:00:00Z'
        - name: place_type
          in: query
          description: Return changes for one place type
          required: false
          schema:
            type: string
            enum:
              - country
              - state
              - city
            example: city
        - name: country_code
          in: query
          description: >-
            Return changes for a country and its states and cities. Uses an ISO
            3166-1 alpha-2 code.
          required: false
          schema:
            type: string
            minLength: 2
            maxLength: 2
            pattern: ^[A-Za-z]{2}$
            example: IN
        - name: change_type
          in: query
          description: Return one kind of change
          required: false
          schema:
            type: string
            enum:
              - added
              - removed
              - renamed
              - place_group_changed
              - parent_changed
              - coordinates_changed
              - other_fields_changed
            example: renamed
        - name: limit
          in: query
          description: Maximum records per page (1–100)
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
            example: 50
        - name: next_page_token
          in: query
          description: >-
            Opaque cursor returned by the previous page. It expires after 24
            hours. Omit the original filters, or resend all of them unchanged.
          required: false
          schema:
            type: string
            minLength: 1
            maxLength: 4096
            pattern: ^[A-Za-z0-9_-]+$
      responses:
        '200':
          description: >-
            A page from the fixed change-feed snapshot. This endpoint is not
            cached and does not return `Cache-Control`, `ETag`, or `X-Cache`.
          headers:
            X-Request-ID:
              $ref: '#/components/headers/XRequestId'
            X-CSC-Data-Version:
              $ref: '#/components/headers/XCSCDataVersion'
            X-CSC-Data-Updated-At:
              $ref: '#/components/headers/XCSCDataUpdatedAt'
            X-CSC-Plan:
              $ref: '#/components/headers/XCSCPlan'
            X-CSC-Daily-Used:
              $ref: '#/components/headers/XCSCDailyUsed'
            X-CSC-Daily-Limit:
              $ref: '#/components/headers/XCSCDailyLimit'
            X-CSC-Monthly-Used:
              $ref: '#/components/headers/XCSCMonthlyUsed'
            X-CSC-Monthly-Limit:
              $ref: '#/components/headers/XCSCMonthlyLimit'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChangeFeedResponse'
        '400':
          description: >-
            Invalid parameter or token, filters that disagree with the token, or
            a start date outside the retained window
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChangeFeedError'
              example:
                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'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: >-
            The API key's plan does not include the data change feed.
            Professional is the standard required tier.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChangeFeedFeatureError'
              example:
                status: error
                message: This feature is not available on your current plan.
                details:
                  feature: dataChangeFeed
                  currentTier: supporter
                  requiredTier: professional
                  upgradeUrl: https://countrystatecity.in/pricing
        '429':
          $ref: '#/components/responses/RateLimited'
      security:
        - ApiKeyAuth: []
components:
  headers:
    XRequestId:
      description: Unique ID for this request
      schema:
        type: string
        format: uuid
        example: 8b4c01b8-60f1-4c29-a105-8dc65ca9925e
    XCSCDataVersion:
      description: Current dataset version. Present when version metadata is available.
      schema:
        type: string
        example: v3.2-export.7-2026.08.24
    XCSCDataUpdatedAt:
      description: >-
        When the current dataset version was published. Present when version
        metadata is available.
      schema:
        type: string
        format: date-time
        example: '2026-08-24T08:15:00.000Z'
    XCSCPlan:
      description: Your current pricing tier
      schema:
        type: string
        enum:
          - community
          - starter
          - supporter
          - professional
          - business
          - legacy
          - custom
        example: supporter
    XCSCDailyUsed:
      description: Number of requests used today
      schema:
        type: integer
        example: 42
    XCSCDailyLimit:
      description: Your daily request limit (or 'unlimited' for custom plans)
      schema:
        type: string
        example: '1000'
    XCSCMonthlyUsed:
      description: Number of requests used this month
      schema:
        type: integer
        example: 850
    XCSCMonthlyLimit:
      description: Your monthly request limit (or 'unlimited' for custom plans)
      schema:
        type: string
        example: '30000'
  schemas:
    ChangeFeedResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/ChangeRecord'
        next_page_token:
          type: string
          nullable: true
          maxLength: 4096
          pattern: ^[A-Za-z0-9_-]+$
          description: Opaque cursor for the next page, or `null` after the last page.
      required:
        - results
        - next_page_token
    ChangeFeedError:
      type: object
      properties:
        status:
          type: string
          enum:
            - error
        message:
          type: string
        details:
          type: object
          additionalProperties: true
          description: >-
            Extra context when available, including `earliestAvailableDate` for
            an expired retention window.
      required:
        - status
        - message
    ChangeFeedFeatureError:
      type: object
      properties:
        status:
          type: string
          enum:
            - error
        message:
          type: string
        details:
          type: object
          properties:
            feature:
              type: string
              enum:
                - dataChangeFeed
            currentTier:
              type: string
            requiredTier:
              type: string
              nullable: true
            upgradeUrl:
              type: string
              format: uri
          required:
            - feature
            - currentTier
            - requiredTier
            - upgradeUrl
      required:
        - status
        - message
        - details
    ChangeRecord:
      type: object
      description: >-
        One recorded change. Fields inside `old_values` and `new_values` are
        filtered to the caller's data access level.
      properties:
        change_id:
          type: string
          format: uuid
          description: Unique ID for this change
          example: 6b30c790-c46f-4a0f-b7f2-ea1a1a9d8362
        data_version:
          type: string
          description: Dataset release that produced this change
          example: v3.2-export.7-2026.08.24
        changed_at:
          type: string
          format: date-time
          description: When the release was recorded
          example: '2026-08-24T08:15:00.000Z'
        place_type:
          type: string
          enum:
            - country
            - state
            - city
          example: city
        place_id:
          type: string
          description: Stable ID of the changed place
          example: '57606'
        change_type:
          type: string
          enum:
            - added
            - removed
            - renamed
            - place_group_changed
            - parent_changed
            - coordinates_changed
            - other_fields_changed
          example: renamed
        old_values:
          type: object
          nullable: true
          additionalProperties: true
          description: Values before the change. `null` for an added place.
        new_values:
          type: object
          nullable: true
          additionalProperties: true
          description: Values after the change. `null` for a removed place.
      required:
        - change_id
        - data_version
        - changed_at
        - place_type
        - place_id
        - change_type
        - old_values
        - new_values
    Error:
      type: object
      properties:
        error:
          type: string
          description: Error message
      required:
        - error
    RateLimitError:
      type: object
      properties:
        error:
          type: string
          example: >-
            Daily usage limit exceeded. Please try again tomorrow or contact
            support for higher limits.
        limit:
          type: integer
          description: Your plan's limit for the exceeded period
          example: 100
        period:
          type: string
          enum:
            - daily
            - monthly
          example: daily
        tier:
          type: string
          description: Your current tier
          example: community
        upgradeUrl:
          type: string
          description: URL to upgrade your plan
          example: https://countrystatecity.in/pricing
      required:
        - error
  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: Unauthorized. You shouldn't be here.
    RateLimited:
      description: Daily or monthly usage limit exceeded
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimitError'
          example:
            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
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      description: >-
        API key for authentication. Get your free key at
        [app.countrystatecity.in](https://app.countrystatecity.in).
      name: X-CSCAPI-KEY
      in: header

````

## Related topics

- [Self-hosting and extending CSC data](/database/self-hosting-and-custom-data.md)
- [Changelog](/changelog.md)
- [Submitting Changes](/tools/update-tool/submitting-changes.md)
- [Export Formats](/tools/export-tool/formats.md)
- [Review Process](/tools/update-tool/review-process.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.