{
  "openapi": "3.0.3",
  "info": {
    "contact": {
      "name": "India Cities API"
    },
    "description": "Reference data for 76 Indian cities, including every state and union-territory capital and all major metros. Filter by state, tier or tag, look a city up by id, find the nearest cities to a coordinate, or measure the distance between two cities. Read-only, no authentication required.",
    "license": {
      "name": "Reference data, free to use"
    },
    "title": "India Cities API",
    "version": "1.0.0"
  },
  "servers": [
    {
      "description": "This deployment",
      "url": "."
    }
  ],
  "tags": [
    {
      "description": "Browse and look up cities",
      "name": "cities"
    },
    {
      "description": "Distance and proximity",
      "name": "geo"
    },
    {
      "description": "About this service",
      "name": "meta"
    }
  ],
  "paths": {
    "/v1/cities": {
      "get": {
        "description": "Returns cities ordered by population, largest first. All filters are optional and combine with AND.",
        "operationId": "listCities",
        "parameters": [
          {
            "description": "Exact state or union-territory name, case-insensitive.",
            "example": "Gujarat",
            "in": "query",
            "name": "state",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "City tier.",
            "example": "metro",
            "in": "query",
            "name": "tier",
            "required": false,
            "schema": {
              "enum": [
                "metro",
                "tier-1",
                "tier-2"
              ],
              "type": "string"
            }
          },
          {
            "description": "A single tag; cities carrying that tag are returned.",
            "example": "port",
            "in": "query",
            "name": "tag",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Free-text match against name, state and id.",
            "example": "pur",
            "in": "query",
            "name": "q",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Page size.",
            "example": 5,
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 20,
              "maximum": 100,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Number of matching cities to skip.",
            "example": 0,
            "in": "query",
            "name": "offset",
            "required": false,
            "schema": {
              "default": 0,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "count": 2,
                  "items": [
                    {
                      "id": "delhi",
                      "lat": 28.6139,
                      "lon": 77.209,
                      "name": "Delhi",
                      "population": 16787941,
                      "state": "Delhi",
                      "tags": [
                        "capital",
                        "national-capital",
                        "administrative",
                        "heritage"
                      ],
                      "tier": "metro"
                    },
                    {
                      "id": "mumbai",
                      "lat": 19.076,
                      "lon": 72.8777,
                      "name": "Mumbai",
                      "population": 12442373,
                      "state": "Maharashtra",
                      "tags": [
                        "capital",
                        "port",
                        "financial",
                        "entertainment"
                      ],
                      "tier": "metro"
                    }
                  ],
                  "limit": 20,
                  "offset": 0
                },
                "schema": {
                  "$ref": "#/components/schemas/CityList"
                }
              }
            },
            "description": "Matching cities"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "next": "remove the tier parameter or use one of the allowed values",
                    "what": "invalid tier \"tier-9\"",
                    "why": "tier must be one of metro, tier-1, tier-2"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "A parameter is invalid"
          }
        },
        "summary": "List cities",
        "tags": [
          "cities"
        ]
      }
    },
    "/v1/cities/{id}": {
      "get": {
        "operationId": "getCity",
        "parameters": [
          {
            "description": "City id (slug), for example mumbai or navi-mumbai.",
            "example": "mumbai",
            "in": "path",
            "name": "id",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "id": "mumbai",
                  "lat": 19.076,
                  "lon": 72.8777,
                  "name": "Mumbai",
                  "population": 12442373,
                  "state": "Maharashtra",
                  "tags": [
                    "capital",
                    "port",
                    "financial",
                    "entertainment"
                  ],
                  "tier": "metro"
                },
                "schema": {
                  "$ref": "#/components/schemas/City"
                }
              }
            },
            "description": "The city"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "next": "search with GET /v1/cities?q=\u003cname\u003e",
                    "what": "city \"atlantis\" not found",
                    "why": "no city with that id is in the dataset"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unknown id"
          }
        },
        "summary": "Get one city",
        "tags": [
          "cities"
        ]
      }
    },
    "/v1/distance": {
      "get": {
        "description": "Great-circle distance in kilometres and the initial bearing from the first city to the second.",
        "operationId": "cityDistance",
        "parameters": [
          {
            "description": "Origin city id.",
            "example": "mumbai",
            "in": "query",
            "name": "from",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "description": "Destination city id.",
            "example": "delhi",
            "in": "query",
            "name": "to",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "bearing_deg": 21.7,
                  "distance_km": 1148.1,
                  "from": {
                    "id": "mumbai",
                    "lat": 19.076,
                    "lon": 72.8777,
                    "name": "Mumbai",
                    "population": 12442373,
                    "state": "Maharashtra",
                    "tags": [
                      "capital",
                      "port",
                      "financial",
                      "entertainment"
                    ],
                    "tier": "metro"
                  },
                  "to": {
                    "id": "delhi",
                    "lat": 28.6139,
                    "lon": 77.209,
                    "name": "Delhi",
                    "population": 16787941,
                    "state": "Delhi",
                    "tags": [
                      "capital",
                      "national-capital",
                      "administrative",
                      "heritage"
                    ],
                    "tier": "metro"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Distance"
                }
              }
            },
            "description": "Distance and bearing"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "next": "example: ?from=mumbai\u0026to=delhi",
                    "what": "missing from or to",
                    "why": "both from and to city ids are required"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Missing id"
          },
          "404": {
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "next": "list ids with GET /v1/cities",
                    "what": "city \"atlantis\" not found",
                    "why": "the to id is not in the dataset"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Unknown id"
          }
        },
        "summary": "Distance between two cities",
        "tags": [
          "geo"
        ]
      }
    },
    "/v1/nearest": {
      "get": {
        "description": "Great-circle (haversine) distance from the given coordinate to every city, closest first.",
        "operationId": "nearestCities",
        "parameters": [
          {
            "description": "Latitude in decimal degrees.",
            "example": 22.4707,
            "in": "query",
            "name": "lat",
            "required": true,
            "schema": {
              "maximum": 90,
              "minimum": -90,
              "type": "number"
            }
          },
          {
            "description": "Longitude in decimal degrees.",
            "example": 70.0577,
            "in": "query",
            "name": "lon",
            "required": true,
            "schema": {
              "maximum": 180,
              "minimum": -180,
              "type": "number"
            }
          },
          {
            "description": "How many cities to return.",
            "example": 5,
            "in": "query",
            "name": "limit",
            "required": false,
            "schema": {
              "default": 5,
              "maximum": 25,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "count": 1,
                  "items": [
                    {
                      "bearing_deg": 103.5,
                      "distance_km": 78.8,
                      "id": "rajkot",
                      "lat": 22.3039,
                      "lon": 70.8022,
                      "name": "Rajkot",
                      "population": 1286995,
                      "state": "Gujarat",
                      "tags": [
                        "engineering",
                        "industrial",
                        "jewellery"
                      ],
                      "tier": "tier-1"
                    }
                  ],
                  "origin": {
                    "lat": 22.4707,
                    "lon": 70.0577
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/NearestList"
                }
              }
            },
            "description": "Closest cities"
          },
          "400": {
            "content": {
              "application/json": {
                "example": {
                  "error": {
                    "next": "add ?lat=\u003cdecimal degrees\u003e",
                    "what": "missing lat",
                    "why": "lat is required"
                  }
                },
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "description": "Missing or invalid coordinate"
          }
        },
        "summary": "Nearest cities to a point",
        "tags": [
          "geo"
        ]
      }
    },
    "/v1/states": {
      "get": {
        "description": "One row per state or union territory present in the dataset, sorted by the combined population of its listed cities.",
        "operationId": "listStates",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": [
                  {
                    "cities": 7,
                    "population": 23595700,
                    "state": "Maharashtra"
                  },
                  {
                    "cities": 1,
                    "population": 16787941,
                    "state": "Delhi"
                  }
                ],
                "schema": {
                  "$ref": "#/components/schemas/StateList"
                }
              }
            },
            "description": "State summaries"
          }
        },
        "summary": "Summarise by state",
        "tags": [
          "cities"
        ]
      }
    },
    "/v1/whoami": {
      "get": {
        "description": "Returns a fresh request id, the time the reply was produced, the caller's address as seen by the service, and the identity of the device that served the request when one is reported.",
        "operationId": "whoami",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "example": {
                  "client_ip": "203.0.113.7",
                  "note": "answered by the device that served this request",
                  "request_id": "9f1c2a7b3d4e5f60",
                  "served_at": "2026-09-04T12:00:00Z",
                  "served_by": "unknown",
                  "service": "india-cities-api",
                  "uptime_s": 4321,
                  "version": "1.0.0"
                },
                "schema": {
                  "$ref": "#/components/schemas/WhoAmI"
                }
              }
            },
            "description": "Request receipt"
          }
        },
        "summary": "Which device answered",
        "tags": [
          "meta"
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "City": {
        "properties": {
          "id": {
            "description": "Stable slug identifier",
            "example": "mumbai",
            "type": "string"
          },
          "lat": {
            "example": 19.076,
            "format": "double",
            "type": "number"
          },
          "lon": {
            "example": 72.8777,
            "format": "double",
            "type": "number"
          },
          "name": {
            "example": "Mumbai",
            "type": "string"
          },
          "population": {
            "description": "Municipal population, 2011 Census",
            "example": 12442373,
            "format": "int64",
            "type": "integer"
          },
          "state": {
            "example": "Maharashtra",
            "type": "string"
          },
          "tags": {
            "example": [
              "capital",
              "port",
              "financial"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          },
          "tier": {
            "enum": [
              "metro",
              "tier-1",
              "tier-2"
            ],
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "state",
          "lat",
          "lon",
          "population",
          "tier",
          "tags"
        ],
        "type": "object"
      },
      "CityList": {
        "properties": {
          "count": {
            "description": "Total matches before paging",
            "type": "integer"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/City"
            },
            "type": "array"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          }
        },
        "required": [
          "count",
          "items"
        ],
        "type": "object"
      },
      "Distance": {
        "properties": {
          "bearing_deg": {
            "type": "number"
          },
          "distance_km": {
            "type": "number"
          },
          "from": {
            "$ref": "#/components/schemas/City"
          },
          "to": {
            "$ref": "#/components/schemas/City"
          }
        },
        "required": [
          "from",
          "to",
          "distance_km",
          "bearing_deg"
        ],
        "type": "object"
      },
      "Error": {
        "properties": {
          "error": {
            "properties": {
              "next": {
                "description": "What to do next",
                "type": "string"
              },
              "what": {
                "description": "What did not happen",
                "type": "string"
              },
              "why": {
                "description": "Why it did not happen",
                "type": "string"
              }
            },
            "required": [
              "what",
              "why",
              "next"
            ],
            "type": "object"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "NearestCity": {
        "allOf": [
          {
            "$ref": "#/components/schemas/City"
          },
          {
            "properties": {
              "bearing_deg": {
                "description": "Initial bearing from the origin, degrees clockwise from north",
                "type": "number"
              },
              "distance_km": {
                "description": "Great-circle distance, one decimal",
                "type": "number"
              }
            },
            "required": [
              "distance_km",
              "bearing_deg"
            ],
            "type": "object"
          }
        ]
      },
      "NearestList": {
        "properties": {
          "count": {
            "type": "integer"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/NearestCity"
            },
            "type": "array"
          },
          "origin": {
            "properties": {
              "lat": {
                "type": "number"
              },
              "lon": {
                "type": "number"
              }
            },
            "type": "object"
          }
        },
        "required": [
          "origin",
          "count",
          "items"
        ],
        "type": "object"
      },
      "StateList": {
        "items": {
          "$ref": "#/components/schemas/StateSummary"
        },
        "type": "array"
      },
      "StateSummary": {
        "properties": {
          "cities": {
            "description": "Cities listed for this state",
            "type": "integer"
          },
          "population": {
            "description": "Sum of listed city populations",
            "format": "int64",
            "type": "integer"
          },
          "state": {
            "type": "string"
          }
        },
        "required": [
          "state",
          "cities",
          "population"
        ],
        "type": "object"
      },
      "WhoAmI": {
        "properties": {
          "client_ip": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "request_id": {
            "description": "Random id unique to this reply",
            "type": "string"
          },
          "served_at": {
            "format": "date-time",
            "type": "string"
          },
          "served_by": {
            "description": "Identity of the serving device when reported, otherwise \"unknown\"",
            "type": "string"
          },
          "service": {
            "type": "string"
          },
          "uptime_s": {
            "description": "Seconds since this instance started",
            "type": "integer"
          },
          "version": {
            "type": "string"
          }
        },
        "required": [
          "service",
          "served_at",
          "request_id",
          "client_ip",
          "served_by",
          "note"
        ],
        "type": "object"
      }
    }
  }
}
