What is an API?
API stands for Application Programming Interface. Think of it like a waiter in a restaurant:
The waiter (API) takes your order to the kitchen.
The kitchen (server) prepares the food.
The waiter (API) brings the food back to you.
You never go into the kitchen yourself. The API is the middleman that lets two systems talk to each other.
In programming terms: an API defines rules for how one piece of software can request data or services from another. When you open a weather app, it uses an API to fetch weather data from a remote server.
What is REST?
REST = REpresentational State Transfer. It is an architectural style (not a protocol, not a library) for designing networked applications. Most modern web APIs follow REST.
REST Principles (6 Constraints)
| # | Principle | What It Means |
|---|---|---|
| 1 | Client-Server | Client (frontend) and Server (backend) are separate. They communicate over HTTP. |
| 2 | Stateless | Each request is independent. Server does NOT remember previous requests. All info must be in the request itself. |
| 3 | Cacheable | Responses can be cached by the client to improve performance. |
| 4 | Uniform Interface | A consistent way to interact: use standard HTTP methods, URIs, and status codes. |
| 5 | Layered System | Client doesn't know if it's talking directly to the server or through a load balancer/proxy. |
| 6 | Code on Demand (optional) | Server can send executable code to the client (e.g., JavaScript). Rarely used. |
HTTP Methods
HTTP methods tell the server what action you want to perform. These are also called HTTP verbs.
| Method | Purpose | Example | Has Body? |
|---|---|---|---|
| GET | Retrieve/Read data | Get list of users | No |
| POST | Create new resource | Create a new user | Yes |
| PUT | Update entire resource (replace) | Update all user fields | Yes |
| PATCH | Update part of resource | Update only email | Yes |
| DELETE | Delete a resource | Delete a user | No (usually) |
GET /api/employees → Get all employeesGET /api/employees/5 → Get employee with id 5POST /api/employees → Create a new employee (data in body)PUT /api/employees/5 → Replace employee 5 completelyPATCH /api/employees/5 → Update some fields of employee 5DELETE /api/employees/5 → Delete employee 5
PUT replaces the ENTIRE resource. If you send a PUT with only the name, other fields become null.
PATCH updates ONLY the fields you send. Other fields stay unchanged.
HTTP Status Codes
| Code | Name | Meaning | When Used |
|---|---|---|---|
| 200 | OK | Request succeeded | GET, PUT, PATCH success |
| 201 | Created | Resource created successfully | POST success |
| 204 | No Content | Success but no response body | DELETE success |
| 400 | Bad Request | Invalid request data | Validation errors, malformed JSON |
| 401 | Unauthorized | Not authenticated | Missing or invalid credentials |
| 403 | Forbidden | Authenticated but no permission | User lacks access rights |
| 404 | Not Found | Resource doesn't exist | Wrong URL or deleted resource |
| 500 | Internal Server Error | Server crashed | Bug in server code |
4xx = Client's fault (you sent something wrong)
5xx = Server's fault (server broke)
401 vs 403: 401 = "Who are you?" (not logged in). 403 = "I know who you are, but you can't do this" (logged in, but no permission).
URL Structure
https://api.example.com/v1/employees/42?sort=name&order=asc |_____| |_____________| |_| |________| |_| |_______________| scheme host ver endpoint id query params
| Part | Example | Purpose |
|---|---|---|
| Base URL | https://api.example.com | Server address |
| Version | /v1 | API version |
| Endpoint | /employees | The resource you want |
| Path Parameter | /employees/42 | Identifies specific resource (42 is the path param) |
| Query Parameters | ?sort=name&order=asc | Filter, sort, paginate (after the ? mark) |
/users/5 (get user 5)Query param → filters/modifies the result:
/users?age=25 (get users where age is 25)
HTTP Headers
Headers are metadata sent with every HTTP request and response. They carry information about the request format, authentication, and more.
| Header | Purpose | Example Value |
|---|---|---|
| Content-Type | Format of data in request body | application/json |
| Accept | Format client wants in response | application/json |
| Authorization | Authentication credentials | Bearer eyJhbGci... |
| Cache-Control | Caching instructions | no-cache |
Accept = "I WANT you to REPLY in this format"
Request and Response Anatomy
HTTP Request
POST /api/employees HTTP/1.1 Host: api.example.com Content-Type: application/json Authorization: Bearer abc123token { "name": "Darshan", "department": "Engineering", "salary": 50000 }
HTTP Response
HTTP/1.1 201 Created Content-Type: application/json { "id": 101, "name": "Darshan", "department": "Engineering", "salary": 50000, "message": "Employee created successfully" }
REST vs SOAP
| Feature | REST | SOAP |
|---|---|---|
| Full Form | REpresentational State Transfer | Simple Object Access Protocol |
| Type | Architectural style | Protocol |
| Data Format | JSON, XML, HTML, plain text | XML only |
| Transport | HTTP | HTTP, SMTP, TCP, etc. |
| Speed | Faster (lightweight) | Slower (heavy XML) |
| Caching | Supports caching | No caching |
| Standards | Flexible, no strict rules | Strict WS-* standards |
| Error Handling | HTTP status codes | SOAP fault elements |
| Use Case | Web apps, mobile, microservices | Banking, enterprise (high security) |
| Learning Curve | Easy | Complex |
Idempotent Methods
Idempotent means: calling the same request multiple times produces the same result as calling it once.
| Method | Idempotent? | Why? |
|---|---|---|
| GET | Yes | Reading data 10 times gives same result |
| PUT | Yes | Replacing a resource 10 times gives same final state |
| DELETE | Yes | Deleting same resource 10 times — it's still deleted |
| PATCH | Not guaranteed | Can depend on current state |
| POST | No | Calling POST 10 times creates 10 resources! |
JSON (JavaScript Object Notation)
JSON is a lightweight data format used to exchange data between client and server. Almost all modern APIs use JSON. It is human-readable and easy for machines to parse.
JSON Syntax Rules
- Data is in key-value pairs:
"key": value - Keys MUST be in double quotes (single quotes are INVALID)
- Values can be: string, number, boolean, null, object, array
- Objects use curly braces
{ } - Arrays use square brackets
[ ] - No trailing commas allowed
- No comments allowed in JSON
{
"name": "Darshan",
"age": 22,
"isEmployee": true,
"address": null
}
[ "Java", "Python", "JavaScript" ]
JSON Data Types
| Type | Example | Notes |
|---|---|---|
| String | "hello" | Must use double quotes |
| Number | 42, 3.14, -10 | No quotes. Integer or decimal. |
| Boolean | true, false | Lowercase only. NOT "true" in quotes. |
| Null | null | Lowercase only. Means "empty/no value". |
| Object | {"key": "value"} | Nested object inside another object |
| Array | [1, 2, 3] | Ordered list of values |
Valid vs Invalid JSON
VALID JSON
// All keys in double quotes, proper syntax { "name": "Darshan", "age": 22, "skills": ["Java", "SQL"], "active": true }
INVALID JSON (with reasons)
// ERROR 1: Single quotes (MUST be double quotes) { 'name': 'Darshan' } // ERROR 2: Key without quotes { name: "Darshan" } // ERROR 3: Trailing comma after last item { "name": "Darshan", } // ERROR 4: Using undefined (not a JSON value) { "name": undefined } // ERROR 5: Single value without object/array wrapper "just a string" // Actually this IS valid JSON! A single value is valid.
Nested JSON Objects and Arrays
{
"employee": {
"id": 101,
"name": "Darshan",
"department": {
"name": "Engineering",
"floor": 3
},
"skills": [
{ "name": "Java", "level": "intermediate" },
{ "name": "SQL", "level": "beginner" }
],
"projects": ["ILP Guide", "Chat App"]
}
}
obj.employee.department.nameTo get "SQL":
obj.employee.skills[1].nameTo get "Chat App":
obj.employee.projects[1]Arrays are zero-indexed: first item is [0], second is [1].
JSON in Java
Using org.json Library (JSONObject, JSONArray)
Creating JSON from scratch
import org.json.JSONObject; import org.json.JSONArray; JSONObject emp = new JSONObject(); emp.put("name", "Darshan"); emp.put("age", 22); emp.put("active", true); JSONArray skills = new JSONArray(); skills.put("Java"); skills.put("SQL"); emp.put("skills", skills); System.out.println(emp.toString(2)); // pretty print with indent 2
Parsing a JSON string
String jsonStr = "{\"name\":\"Darshan\",\"age\":22,\"skills\":[\"Java\",\"SQL\"]}"; JSONObject obj = new JSONObject(jsonStr); // Get values String name = obj.getString("name"); // "Darshan" int age = obj.getInt("age"); // 22 // Get array JSONArray skills = obj.getJSONArray("skills"); for (int i = 0; i < skills.length(); i++) { System.out.println(skills.getString(i)); } // Output: Java // SQL
Accessing nested values
String json = "{\"employee\":{\"name\":\"Darshan\",\"dept\":{\"name\":\"Engg\"}}}"; JSONObject root = new JSONObject(json); JSONObject employee = root.getJSONObject("employee"); JSONObject dept = employee.getJSONObject("dept"); String deptName = dept.getString("name"); // "Engg"
Using Jackson Library (ObjectMapper)
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.JsonNode; ObjectMapper mapper = new ObjectMapper(); // JSON String → Java Object String json = "{\"name\":\"Darshan\",\"age\":22}"; Employee emp = mapper.readValue(json, Employee.class); // Java Object → JSON String String jsonOut = mapper.writeValueAsString(emp); // Parse to tree (when you don't have a class) JsonNode node = mapper.readTree(json); String name = node.get("name").asText(); // "Darshan"
Jackson — industry standard. Can map JSON directly to Java classes. Used in Spring Boot.
Gson (by Google) — similar to Jackson but simpler API.
new Gson().fromJson(json, MyClass.class)
JSON Parsing — HackerRank Pattern
Complete HackerRank Template: Fetch API + Parse JSON
import java.io.*; import java.net.*; import org.json.*; public class Solution { public static void main(String[] args) throws Exception { // Step 1: Build the URL String urlStr = "https://jsonmock.hackerrank.com/api/articles?page=1"; URL url = new URL(urlStr); // Step 2: Open connection HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); // Step 3: Read the response BufferedReader br = new BufferedReader( new InputStreamReader(conn.getInputStream()) ); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line); } br.close(); // Step 4: Parse JSON JSONObject response = new JSONObject(sb.toString()); // Step 5: Get the data array JSONArray data = response.getJSONArray("data"); // Step 6: Loop through and extract fields for (int i = 0; i < data.length(); i++) { JSONObject item = data.getJSONObject(i); // Use optString to avoid errors on null values String title = item.optString("title", ""); if (!title.isEmpty()) { System.out.println(title); } } } }
getString("key") → throws error if key is missingoptString("key", "default") → returns default if key is missing (SAFER)getInt("key") / optInt("key", 0) → same for integersgetJSONObject("key") → get nested objectgetJSONArray("key") → get arrayisNull("key") → check if value is nullhas("key") → check if key exists
Pagination Pattern (Multiple Pages)
int page = 1; int totalPages = 1; while (page <= totalPages) { String urlStr = "https://api.example.com/data?page=" + page; // ... fetch and parse (same as above) ... JSONObject response = new JSONObject(sb.toString()); totalPages = response.getInt("total_pages"); JSONArray data = response.getJSONArray("data"); // process data... page++; }
XML (eXtensible Markup Language)
XML is a markup language designed to store and transport data. Unlike HTML (which displays data), XML carries data. It was widely used before JSON took over, but is still used in SOAP APIs, configuration files (like pom.xml, web.xml), and enterprise systems.
XML vs HTML
| Feature | XML | HTML |
|---|---|---|
| Purpose | Carry/store data | Display data |
| Tags | You define your own tags | Predefined tags (h1, p, div) |
| Case Sensitive | Yes | No |
| Closing Tags | Mandatory | Optional for some tags |
| Strictness | Very strict (well-formed rules) | Forgiving (browsers fix errors) |
XML Syntax
<?xml version="1.0" encoding="UTF-8"?> <!-- Prolog/Declaration --> <employees> <!-- Root element (only ONE allowed) --> <employee id="101"> <!-- Element with attribute --> <name>Darshan</name> <!-- Child element --> <department>Engineering</department> <salary>50000</salary> </employee> <employee id="102"> <name>Priya</name> <department>HR</department> <salary>45000</salary> </employee> </employees>
Well-Formed XML Rules
- Must have exactly one root element
- Every opening tag MUST have a closing tag:
<name>...</name> - Tags are case-sensitive:
<Name>and<name>are different - Elements must be properly nested:
<a><b></b></a>(not<a><b></a></b>) - Attribute values must be in quotes:
id="101" - Prolog (declaration) is optional but recommended
<Name>Darshan</name> — case mismatch (N vs n)<br> without closing → invalid (use <br/> for self-closing)
XML Parsing in Java
DOM Parser (Document Object Model)
Loads the entire XML into memory as a tree. Good for small files. Easy to navigate.
import javax.xml.parsers.*; import org.w3c.dom.*; import java.io.*; public class XMLParser { public static void main(String[] args) throws Exception { // Step 1: Create DocumentBuilder DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); // Step 2: Parse XML file into Document Document doc = builder.parse(new File("employees.xml")); doc.getDocumentElement().normalize(); // Step 3: Get all "employee" elements NodeList empList = doc.getElementsByTagName("employee"); // Step 4: Loop through each employee for (int i = 0; i < empList.getLength(); i++) { Node node = empList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element elem = (Element) node; // Get attribute String id = elem.getAttribute("id"); // Get child element text String name = elem.getElementsByTagName("name") .item(0) .getTextContent(); String dept = elem.getElementsByTagName("department") .item(0) .getTextContent(); System.out.println(id + " - " + name + " - " + dept); } } } } // Output: // 101 - Darshan - Engineering // 102 - Priya - HR
SAX Parser (Simple API for XML)
Event-based. Reads XML sequentially, fires events (start element, end element, characters). Good for large files because it doesn't load everything into memory.
SAX: Reads sequentially → Event-based → Uses less memory → Good for large files
For exams and HackerRank, DOM is used more often. SAX is asked as theory.
JSON vs XML Comparison
| Feature | JSON | XML |
|---|---|---|
| Full Form | JavaScript Object Notation | eXtensible Markup Language |
| Syntax | Key-value pairs: {"k":"v"} | Tags: <k>v</k> |
| Readability | More readable, less verbose | More verbose (lots of tags) |
| Data Types | String, Number, Boolean, Null, Object, Array | Everything is text (no native types) |
| Arrays | Native support: [1,2,3] | No direct array — use repeated elements |
| Comments | Not allowed | Allowed: <!-- comment --> |
| Parsing Speed | Faster | Slower |
| File Size | Smaller | Larger (because of closing tags) |
| Used In | REST APIs, web apps, mobile | SOAP, config files, enterprise |
| Namespace | Not supported | Supported |
"When to use XML?" → Configuration files (pom.xml, web.xml), SOAP APIs, when you need namespaces or comments
API Consumption in Java (HttpURLConnection)
Making a GET Request
import java.io.*; import java.net.*; URL url = new URL("https://api.example.com/users"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Accept", "application/json"); int statusCode = conn.getResponseCode(); // 200, 404, etc. if (statusCode == 200) { BufferedReader br = new BufferedReader( new InputStreamReader(conn.getInputStream()) ); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line); } br.close(); System.out.println(sb.toString()); } else { System.out.println("Error: " + statusCode); } conn.disconnect();
Making a POST Request
URL url = new URL("https://api.example.com/users"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "application/json"); conn.setDoOutput(true); // Enable sending body // Write JSON body String jsonBody = "{\"name\":\"Darshan\",\"age\":22}"; OutputStream os = conn.getOutputStream(); os.write(jsonBody.getBytes()); os.flush(); os.close(); int code = conn.getResponseCode(); // Expect 201 System.out.println("Response Code: " + code);
Complete Template: Fetch + Parse + Extract
import java.io.*; import java.net.*; import org.json.*; public class Solution { // Reusable method: fetch JSON from any URL static String fetchJSON(String urlStr) throws Exception { URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); BufferedReader br = new BufferedReader( new InputStreamReader(conn.getInputStream()) ); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line); } br.close(); return sb.toString(); } public static void main(String[] args) throws Exception { // Example: Get total goals by a football team in a year String team = "Barcelona"; int year = 2011; int totalGoals = 0; int page = 1; int totalPages = 1; while (page <= totalPages) { String url = "https://jsonmock.hackerrank.com/api/football_matches" + "?year=" + year + "&team1=" + URLEncoder.encode(team, "UTF-8") + "&page=" + page; JSONObject resp = new JSONObject(fetchJSON(url)); totalPages = resp.getInt("total_pages"); JSONArray data = resp.getJSONArray("data"); for (int i = 0; i < data.length(); i++) { JSONObject match = data.getJSONObject(i); totalGoals += match.getInt("team1goals"); } page++; } System.out.println("Total Goals: " + totalGoals); } }
Error Handling for API Calls
try { HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(5000); // 5 second timeout conn.setReadTimeout(5000); int code = conn.getResponseCode(); if (code == 200) { // Read from getInputStream() } else { // Read error from getErrorStream() BufferedReader err = new BufferedReader( new InputStreamReader(conn.getErrorStream()) ); // handle error... } } catch (SocketTimeoutException e) { System.out.println("Connection timed out"); } catch (IOException e) { System.out.println("Network error: " + e.getMessage()); }
Practice Questions
Which HTTP method is used to CREATE a new resource?
What does HTTP status code 404 mean?
Which of the following is VALID JSON?
Which REST principle states that each request must contain all information needed to process it?
Which HTTP method is NOT idempotent?
What is the difference between status codes 401 and 403?
What data format does SOAP exclusively use?
Which of the following is NOT a valid JSON data type?
What is the correct way to access the value "SQL" from this JSON?{"employee": {"skills": ["Java", "SQL", "Python"]}}
Which status code should a REST API return after successfully CREATING a resource?
Which XML rule makes this invalid? <Name>Darshan</name>
In the URL https://api.com/users/5?sort=name, what is 5?
Which Java class is used to parse XML using the DOM approach?
What does the Content-Type header specify?
Which is true about REST?
What is the output of this Java code?
JSONObject obj = new JSONObject("{\"a\":10,\"b\":20}");
System.out.println(obj.getInt("a") + obj.getInt("b"));
How many root elements can an XML document have?
Which of the following is an advantage of JSON over XML?
What does conn.setDoOutput(true) do in HttpURLConnection?
Which method safely returns a default value if a JSON key doesn't exist?
What is the difference between PUT and PATCH?
Which HTTP status code means "Success, but no response body"?
In XML, which of these is well-formed?
What does getElementsByTagName("employee") return in DOM parsing?
Which of the following JSON values is valid?