AI Computer Institute
Expert-curated CS & AI curriculum aligned to CBSE standards. A bharath.ai initiative. About Us

India's Open Data Ecosystem: Building with Government APIs

📚 APIs & Data Engineering⏱️ 23 min read🎓 Grade 9
✍️ AI Computer Institute Editorial Team Updated: August 2026 CBSE-aligned · Peer-reviewed · 23 min read
Content curated by subject matter experts with IIT/NIT backgrounds. All chapters are fact-checked against official CBSE/NCERT syllabi.

Imagine you want to build a small app that tells students in your school which railway stations near you have live train running-status updates, or which cities currently have unsafe air quality. The government already collects this data — the Indian Meteorological Department measures rainfall every day, the Central Pollution Control Board tracks air quality every hour, the Ministry of Education publishes school-wise data every year. None of it is secret. So why can't you just use it?

The honest answer is: you can. But not by downloading a giant spreadsheet and scrolling through it. A single Government of India dataset — say, district-wise rainfall records — can hold hundreds of thousands of rows going back decades. If you only need "rainfall in the last 7 days for districts in Maharashtra," downloading the whole file, opening it in a program, and searching through it row by row is slow and wasteful. What you actually want is a way to ask the government's data server a precise question and get back just the rows that answer it. That mechanism is called an API, and understanding how to use one — correctly, respectfully, and without breaking it — is the real subject of this chapter.

What "Open Data" Actually Means

In 2012, the Government of India adopted the National Data Sharing and Accessibility Policy (NDSAP). Its central idea was simple: data collected using public money — census figures, weather records, crop yields, budget allocations — should, by default, be shared with the public rather than locked inside a ministry's internal servers. This policy led to the creation of data.gov.in, the Open Government Data (OGD) Platform India, which today hosts datasets published by central ministries, state departments, and public sector undertakings, ranging from groundwater levels to railway punctuality statistics.

Here is the first misconception worth correcting immediately: "open data" does not mean "do whatever you want with it." Datasets on data.gov.in are published under a Government Open Data License (GODL-India), which typically requires you to attribute the source and does not permit you to claim the data as your own or to imply the government endorses your app. "Open" means the data is freely accessible without needing special permission or payment for most datasets — it does not mean the license disappears. If you publish an app built on government data, saying "Rainfall data source: India Meteorological Department, via data.gov.in" is not optional courtesy — it is a license condition.

An API Is a Structured Request Form, Not a Website

You have likely filled out or seen a Right to Information (RTI) application — a fixed-format form where you specify exactly which record you want from a government office, and the office replies in a fixed-format letter. An API works on almost the same principle, except the "form" and the "reply letter" are both written in a way that a computer program — not a human clerk — can fill out and read, in a fraction of a second.

Formally: an API (Application Programming Interface) is an agreed-upon set of rules that lets one piece of software ask another piece of software for something specific, and receive a predictable, structured answer back. A government open-data API specifically lets your program ask a government data server: "give me these rows, from this dataset, matching this condition" — and get back exactly that, formatted so your code can read it directly, with no human ever opening a spreadsheet.

This is different from visiting a website. When you open data.gov.in in a browser, the server sends back HTML — a page designed to be read by a human eye, with menus, colours, and buttons. When your Python program calls the same platform's API, the server sends back raw data — usually in a format called JSON — with no colours or buttons, designed to be read by a program. Same underlying data, two completely different "shapes" of response depending on who is asking.

Anatomy of a Government API Call

Every API request to a platform like data.gov.in is really just a specially formatted web address (URL) that your program sends a request to. Reading one of these URLs correctly is a skill in itself — each part tells the server something different. Consider this shape, used by data.gov.in's own API:

Anatomy of a Government Open-Data API Call https://api.data.gov.in /resource/{id} ?api-key=KEY&format=json&limit=5 HOST Which server to contact. The Open Government Data Platform's API address. PATH — dataset ID Every published dataset has a unique resource ID. This tells the server WHICH table to open. QUERY STRING — your instructions Your identity (api-key), the reply format (json/xml/csv), and how many rows you want. sent as one HTTP GET request data.gov.in API server returns JSON { "total": 733, "count": 5, "records": [ {...}, ... ] }

Notice the three jobs the URL does. The host (api.data.gov.in) says which server to talk to — the way a house address tells the postal system which building to deliver to. The path (/resource/{id}) says which specific dataset you want out of the tens of thousands hosted there — every dataset on the platform is assigned a unique resource ID when it is published, and that ID is effectively the dataset's permanent name. The query string — everything after the ?, with each instruction separated by & — carries your actual instructions: your API key (proving who is asking), the format you want the reply in, and how many rows to send back.

This request method — asking for data without changing anything on the server — is called an HTTP GET request. Nearly all open-data API calls you will make are GET requests: you are only reading, never modifying, the government's records.

JSON: The Shape of the Reply

Before you can write code that uses an API's answer, you need to recognise the shape that answer comes in. Almost every modern open-data API — including data.gov.in's — replies in JSON (JavaScript Object Notation), a plain-text format built from exactly two structures you already know from Python: the dictionary (curly braces { }, holding "key": value pairs) and the list (square brackets [ ], holding an ordered sequence of items). JSON nests these inside each other freely — a dictionary can contain a list, and that list can contain more dictionaries.

A data.gov.in response typically looks like this in outline: an outer dictionary carries bookkeeping information — "total" (how many rows exist in the whole dataset that match your request), "count" (how many rows this particular reply contains), and "limit"/"offset" (which slice of the data you're looking at) — plus one key called "records", whose value is a list. Each item in that list is itself a dictionary representing one row of the dataset, with the dataset's column names as keys. Once you see that a JSON reply is "a dictionary whose records key holds a list of row-dictionaries," reading any government API's response stops being mysterious — it is a data structure you already understand, just carried over the internet as text.

Worked Example: Filtering a Live Dataset in Python

Let's parse an API reply and answer a real question with it: which of these cities received more than 1000 mm of rainfall? To keep this self-contained and not depend on a live network call, we'll work with a JSON string that has exactly the shape a real API would hand back (the numbers below are illustrative sample values, not an authoritative rainfall record):

import json

response_text = '''
{
  "total": 5,
  "count": 5,
  "records": [
    {"city": "Mumbai",     "rainfall_mm": 2422},
    {"city": "Delhi",      "rainfall_mm": 774},
    {"city": "Chennai",    "rainfall_mm": 1400},
    {"city": "Bengaluru",  "rainfall_mm": 970},
    {"city": "Shillong",   "rainfall_mm": 2500}
  ]
}
'''

data = json.loads(response_text)      # text becomes a Python dict
records = data["records"]             # the list of row-dicts

high_rainfall = []
for city in records:
    if city["rainfall_mm"] > 1000:
        high_rainfall.append(city["city"])

print("Cities above 1000 mm:", high_rainfall)

Trace this exactly the way the interpreter would. json.loads() converts the text into a Python dictionary with three keys: "total", "count", and "records". data["records"] pulls out the list of five row-dictionaries. The for loop visits each dictionary in turn and checks its "rainfall_mm" value: Mumbai's 2422 is greater than 1000, so "Mumbai" is appended; Delhi's 774 fails the test and is skipped; Chennai's 1400 passes; Bengaluru's 970 fails; Shillong's 2500 passes. After the loop, high_rainfall holds three names, and the program prints:

Cities above 1000 mm: ['Mumbai', 'Chennai', 'Shillong']

Notice what didn't happen here: you never opened a file, scrolled through rows, or downloaded anything you didn't need. In a real program, the only thing that changes is where response_text comes from — instead of a hand-typed string, it would be the text returned by an HTTP library after calling the API's URL. The parsing and filtering logic is identical either way, which is exactly why practising it on a fixed string first, before worrying about network calls, is the right order to learn it in.

HTTP Status Codes: What the Server Is Telling You

A second misconception trips up many beginners: "if my program didn't crash, the request succeeded." Not true. Every API reply arrives with a numeric status code attached, and a careless program can happily run json.loads() on an error message and produce garbage instead of failing loudly. The codes you must recognise for government APIs are:

  • 200 OK — the request succeeded; the body contains your data.
  • 400 Bad Request — your query string is malformed, often a typo in a parameter name.
  • 401 Unauthorized / 403 Forbidden — your API key is missing, wrong, or not permitted for this dataset.
  • 404 Not Found — the resource ID in your path doesn't exist (a dataset may have been renamed or removed).
  • 429 Too Many Requests — you have exceeded the rate limit and must slow down (covered below).

A well-written program checks this code before trusting the body of the reply — treating "I got some text back" and "I got the data I asked for" as two different, separately verified facts.

Pagination: Why One Call Rarely Gets You Everything

Government datasets are often enormous — a district-wise daily rainfall table can easily hold over half a million rows spanning decades. No server will hand all of that back in a single reply; it would be slow to generate and slow to transmit. So APIs use pagination: you request a fixed-size "page" of rows at a time, using two query parameters — limit (how many rows per call) and offset (how many rows to skip from the start before returning results).

Suppose an API tells you, via its "total" field, that a dataset has 733 matching records, and the server allows a maximum limit of 100 rows per call. How many calls do you need to fetch everything? This is ordinary division with a twist: 733 ÷ 100 = 7.33, but you cannot make 0.33 of an API call — any leftover rows still need one more full request. So you round up, not to the nearest whole number: this is called ceiling division, and it needs 8 calls, not 7.

import math

total_records = 733   # from the API's "total" field
limit = 100            # max rows the server returns per call

pages_needed = math.ceil(total_records / limit)
print("API calls required:", pages_needed)

for page_number in range(pages_needed):
    offset = page_number * limit
    print(f"Call {page_number + 1}: ...&limit={limit}&offset={offset}")

Trace it: 733 / 100 is 7.33, and math.ceil(7.33) rounds up to 8, so pages_needed is 8 and the first line prints API calls required: 8. The loop then runs page_number from 0 to 7 (eight iterations), and each time offset is page_number * 100 — producing offsets 0, 100, 200, 300, 400, 500, 600, 700. The eighth and final call, at offset=700, asks for rows 700 through 799, but only rows 700 through 732 actually exist — so that last reply's "count" field will correctly say 33, not 100, even though your limit said 100. A program that blindly assumes every page is full-sized will silently miscount the last page unless it reads "count" rather than assuming it always equals limit.

API Keys and Rate Limits: The Fine Print of "Free"

Here is the third misconception: "public" and "free" do not mean "unlimited." When you register on data.gov.in, you receive a personal API key — a long string you attach to every request via the api-key parameter. This key does two things: it identifies you to the server, and it lets the platform enforce a rate limit — a cap on how many requests you're allowed to make in a given time window. If your program sends requests faster than the limit allows, the server starts replying with status code 429 Too Many Requests instead of your data, until the window resets.

This is not a punishment; it protects the server from being overwhelmed by thousands of programs hammering it simultaneously — the same reason a ration shop serves one token number at a time instead of letting everyone crowd the counter at once. A well-behaved program checks for a 429 response and waits before retrying, rather than firing requests in a tight loop the moment one fails.

Case Study: Co-WIN and the Rate-Limited API That Powered a Country

The clearest large-scale example of these ideas in action is Co-WIN, the platform India used to schedule COVID-19 vaccinations from 2021 onward. Alongside the citizen-facing booking website, the government published a set of public, read-only APIs — no login required — that returned JSON listings of vaccination centres and available appointment slots for a given pincode or district and date. Because these endpoints were openly documented, independent developers across the country built their own slot-checking tools and notification bots on top of them during a period when appointment slots were scarce and highly contested, without needing any special partnership with the government — exactly the outcome open APIs are meant to enable.

The same documentation that made this possible also stated an explicit rate limit — reportedly around 100 calls every five minutes per IP address — precisely to stop the surge of independent bots from accidentally taking the booking system down for everyone, including the official website. Developers who ignored that limit found their programs blocked with 429 errors; developers who respected it and paused between calls kept working. Today, with the nationwide vaccination drive concluded, many of these specific endpoints have been withdrawn or restricted — but the pattern Co-WIN established, of a government service exposing a documented, rate-limited public API that citizen developers could build on directly, remains a template followed by newer platforms such as API Setu, the government's broader API exchange for services like document verification.

Common Mistakes When Working With Government APIs

A few practical habits separate working code from code that fails mysteriously. First, always check "count" against what you expected rather than assuming a full page came back, as shown above. Second, query parameter names are usually case-sensitive and must match the dataset's published field names exactly — a filter written as State_Name when the field is actually state_name typically returns zero matches, not an error, which can look like "there's no data" when really there's a typo. Third, never hard-code your API key inside a program you plan to share or publish publicly (for instance on GitHub) — treat it the way you would treat a password, since someone else could use your key and exhaust your quota. Fourth, remember that the "total" field can itself change between calls if the dataset is updated in real time (as with live pollution or traffic data) — code that fetches page 1, waits, then fetches page 2 assuming a fixed total can end up with duplicate or missing rows if the underlying data shifted in between.

Check Your Understanding

  • 1. A dataset's "total" field reports 456 records, and the API's maximum limit per call is 50. How many API calls are needed to retrieve every record, and what is the offset value of the final call?
  • 2. Your program calls an API and gets back a reply with status code 403. Is the problem more likely a typo in the dataset's resource ID, or a missing/incorrect API key? Explain the difference between 403 and 404.
  • 3. A classmate says: "This dataset is on data.gov.in, so I can copy its numbers into my science project and my app without mentioning where they came from — it's open data, after all." What is wrong with this reasoning?
  • 4. Given data = json.loads(response_text) where response_text has the same shape as the rainfall example above, write the single line of code that would compute the average rainfall across all cities in data["records"].
  • 5. Why does a well-designed open-data API enforce a rate limit even though the data itself is free to access? Use the Co-WIN example in your answer.

Answers

  • 1. 456 ÷ 50 = 9.12, which rounds up (ceiling division) to 10 calls. Offsets are 0, 50, 100, ... up to the tenth call at offset = 450, which returns the final 6 records (450 through 455).
  • 2. A missing or incorrect API key is the more likely cause of 403. 403 Forbidden means the server understood exactly which resource you wanted but is refusing to hand it over — typically an authentication problem. 404 Not Found means the server could not locate the resource ID at all, which points to a typo or a removed/renamed dataset in the path, not a key problem.
  • 3. Open data being freely accessible is not the same as it being license-free. Datasets on data.gov.in are published under a government open data license that requires attribution to the source — copying numbers without citing where they came from violates that license even though no payment or login was needed to get the data.
  • 4. sum(c["rainfall_mm"] for c in data["records"]) / len(data["records"]) — sums every city's rainfall_mm value and divides by how many records there are.
  • 5. Because a huge number of independent developers can call a free public API simultaneously, and with no limit their combined traffic can overload the same server that ordinary citizens depend on for the actual service — in Co-WIN's case, the vaccine booking website itself. The rate limit protects the shared infrastructure, not the data's price, which is why "free" and "unlimited" are different promises.

Summary

India's open-data ecosystem, built on the 2012 National Data Sharing and Accessibility Policy and hosted primarily through data.gov.in, gives you programmatic access to government-collected data through APIs rather than raw file downloads. An API request is a specially structured URL — host, dataset path, and a query string of instructions — sent as an HTTP GET call, and the reply comes back as JSON: an outer dictionary carrying bookkeeping fields like total and count, wrapped around a records list of row-dictionaries you can loop over and filter exactly like any Python data structure. Because datasets are too large to send in one reply, you fetch them in pages using limit and offset, computed with ceiling division and verified against the actual count returned rather than assumed. Every call carries a status code that must be checked before the body is trusted, and every registered key is subject to a rate limit — a real constraint that shaped how independent developers built tools on top of Co-WIN's public vaccination-slot API during 2021. None of this data is truly "free of rules": open access still comes bundled with a license, most commonly requiring attribution, that a good citizen-developer honours even though no one is forcing a login to check.

Practice Exercises

Now it is time to practice! Complete these challenges to solidify your understanding:

  • Exercise 1: Write a short program that demonstrates the core concept from this chapter. Test it with at least 3 different inputs.
  • Exercise 2: Find a real-world example where india's open data ecosystem: building with government apis is used in an Indian company (like TCS, Infosys, Flipkart, or ISRO). Write a paragraph explaining the connection.
  • Exercise 3: Create a mind-map connecting india's open data ecosystem: building with government apis to at least 3 other topics you have studied.
← Real-Time Data: WebSockets and Live UpdatesGraph Theory: Networks, Connections, and Relationships →

Found this useful? Share it!

📱 WhatsApp 🐦 Twitter 💼 LinkedIn