0% found this document useful (0 votes)
5 views104 pages

API Study Guide

The API Study Guide is a comprehensive resource designed to take readers from beginner to expert in API development, covering essential topics like REST, GraphQL, gRPC, security, and performance. It is structured for various audiences, including beginners, intermediate developers, and senior engineers, with practical exercises in multiple programming languages. The guide emphasizes hands-on learning and includes a variety of resources such as quizzes, projects, and interview preparation materials.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views104 pages

API Study Guide

The API Study Guide is a comprehensive resource designed to take readers from beginner to expert in API development, covering essential topics like REST, GraphQL, gRPC, security, and performance. It is structured for various audiences, including beginners, intermediate developers, and senior engineers, with practical exercises in multiple programming languages. The guide emphasizes hands-on learning and includes a variety of resources such as quizzes, projects, and interview preparation materials.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

COMPREHENSIVE TECHNICAL REFERENCE

API Study Guide


Beginner to Expert

A Comprehensive Guide from Fundamentals to Production-Ready Systems

Covering REST, GraphQL, gRPC, Security, Performance, System Design & More

Prepared for Sasank

April 2026

Version 1.0 | Last Updated: April 21, 2026

Preface
Dear Sasank,

Welcome to the API Study Guide — Beginner to Expert. This guide was created to serve as a single,
comprehensive reference that takes you from your very first API call all the way to designing production-
grade, globally distributed API platforms that serve millions of users.

APIs — Application Programming Interfaces — are the connective tissue of modern software. Every
mobile app you use, every website you visit, every cloud service you depend on is powered by APIs.
Understanding how to design, build, secure, test, and scale APIs is one of the most valuable skills in
software engineering today.

Why This Guide Exists


The API landscape is vast and fragmented. Information is scattered across hundreds of blog posts,
documentation sites, RFCs, and textbooks. This guide consolidates everything into a structured learning
path with practical, hands-on exercises in four major programming languages: [Link], Python, Java,
and Go.
Who This Guide Is For
● Beginners who have basic programming knowledge and want to understand APIs from the
ground up

● Intermediate developers who build APIs but want to deepen their understanding of design
principles, security, and performance

● Senior engineers preparing for system design interviews at top tech companies

● Architects who need a comprehensive reference for API governance and platform design

● QA engineers who need to understand API testing strategies and automation

● DevOps engineers who deploy, monitor, and scale API infrastructure

Prerequisites
● Basic understanding of at least one programming language (JavaScript, Python, Java, or Go
preferred)

● Familiarity with the command line / terminal

● A computer with internet access for hands-on exercises

● Basic understanding of databases (SQL or NoSQL) is helpful but not required

● No prior API experience is necessary — we start from zero

How to Get the Most Out of This Guide


1. Read actively: Don't just read — type out every code example and run it yourself

2. Complete every quiz: Each chapter ends with a quiz to reinforce concepts

3. Do the exercises: Hands-on projects are where real learning happens

4. Use the glossary: When you encounter an unfamiliar term, look it up in Appendix B

5. Build the projects: Chapter 17 contains four complete projects — build at least two of them

6. Review the interview questions: Appendix A has 100+ interview questions with model answers
Learning Objectives
Upon completing this guide, you will be able to:

Beginner Level
7. Define what an API is and explain how APIs enable software communication

8. Describe the client-server model and the HTTP request-response cycle

9. Use tools like curl, Postman, and httpie to make API calls

10. Explain HTTP methods (GET, POST, PUT, PATCH, DELETE) and when to use each

11. Interpret HTTP status codes and understand their categories (1xx–5xx)

12. Read and write JSON data structures for API payloads

13. Make API calls programmatically in [Link], Python, Java, and Go

Intermediate Level
14. Design RESTful APIs following best practices and naming conventions

15. Implement pagination, filtering, sorting, and searching in APIs

16. Write OpenAPI/Swagger specifications to document APIs

17. Implement authentication using API keys, JWT tokens, and OAuth 2.0

18. Apply rate limiting and quota management to protect APIs

19. Write comprehensive API tests (unit, integration, contract, end-to-end)

20. Handle API errors gracefully with standardized error responses

Advanced Level
21. Build GraphQL APIs with schemas, resolvers, subscriptions, and federation

22. Build gRPC services with Protocol Buffers and streaming patterns

23. Implement API gateways for routing, security, and traffic management

24. Design caching strategies (HTTP caching, Redis, CDN) for high-performance APIs

25. Set up observability with metrics, structured logging, and distributed tracing
26. Apply the OWASP API Security Top 10 to protect APIs from common vulnerabilities

Expert Level
27. Design APIs for large-scale systems like Twitter, Stripe, Uber, and Netflix

28. Implement event-driven architectures with Kafka, RabbitMQ, and AsyncAPI

29. Apply microservices patterns including saga, CQRS, and event sourcing

30. Architect multi-tenant API platforms with tenant isolation and resource governance

31. Build serverless APIs on AWS Lambda, Azure Functions, and Cloudflare Workers

32. Lead API product strategy including monetization, developer experience, and ecosystem
building

How to Use This Book


Different readers have different goals. Use the reading paths below to focus on what matters most to
you:

Your Role Priority Chapters Supplementary Chapters Estimated


Time

Frontend 1, 2, 3, 5, 6, 8, 11 4, 16, 17 (Projects 1–2) 20–30 hours


Developer

Backend Developer 1–5, 7–10, 12–13, 16–17 6, 11, 14, 15 40–60 hours

Software Architect 3–4, 9–10, 14, 18–20 5–8, 13, 15–16 30–40 hours

QA Engineer 1–3, 5, 8, 12–13 4, 9, 11, Appendix G 20–30 hours

DevOps Engineer 9, 14–16, Appendix H 8, 12–13, 17 (Project 4) 15–25 hours

Interview Prep All chapters + Appendix A + Ch Complete all quizzes 60–80 hours
20

TIP:
If you're preparing for interviews, read Chapter 20 (Case Studies & System Design) and Appendix A
(Interview Questions) last — after you've built a solid foundation through the other chapters.
System design answers are far more compelling when grounded in real implementation experience.

Table of Contents
Front Matter

Preface

Learning Objectives

How to Use This Book

Chapter 1: Introduction to APIs

1.1 What Is an API?

1.2 Evolution of APIs

1.3 Types of APIs

1.4 The API Economy

1.5 API-First Design Philosophy

1.6 Real-World API Examples

1.7 How APIs Work

1.8 API Terminology Glossary

1.9 Setting Up Your Development Environment

1.10 Your First API Call

1.11 Quiz & Exercises

Chapter 2: Web Fundamentals

2.1 HTTP Protocol Deep Dive

2.2 HTTP Methods

2.3 HTTP Status Codes

2.4 HTTP Headers


2.5 URL Structure

2.6 Request/Response Body Formats

2.7 CORS

2.8 TCP/IP, TLS, and DNS

2.9 WebSockets, SSE, and Polling

2.10 Quiz & Exercises

Chapter 3: Types of APIs

3.1 REST APIs

3.2 SOAP APIs

3.3 GraphQL APIs

3.4 gRPC APIs

3.5 WebSocket & Webhook APIs

3.6 AsyncAPI & Event-Driven APIs

3.7 Comparison Matrix

3.8 Quiz & Exercises

Chapter 4: API Design Principles

4.1 API-First Design

4.2 Resource Naming & URI Design

4.3 Pagination, Filtering, and Sorting

4.4 Error Handling & Response Design

4.5 HATEOAS & Hypermedia

4.6 Idempotency

4.7 API Contracts & OpenAPI

4.8 Quiz & Exercises

Chapter 5: RESTful API Deep Dive

Chapter 6: GraphQL & Alternatives

Chapter 7: gRPC & Protocol Buffers

Chapter 8: Authentication & Authorization

Chapter 9: Rate Limiting & Quotas


Chapter 10: Versioning & Lifecycle

Chapter 11: Documentation & Developer Experience

Chapter 12: Testing & Automation

Chapter 13: API Security

Chapter 14: API Gateways & Service Mesh

Chapter 15: Monitoring & Observability

Chapter 16: Performance & Caching

Chapter 17: Building APIs — Projects

Chapter 18: Advanced Topics

Chapter 19: API Business Models

Chapter 20: Case Studies & System Design

Appendices

Appendix A: 100+ Interview Questions with Model Answers

Appendix B: Glossary of API Terms

Appendix C: CLI Cheatsheets

Appendix D: OpenAPI/Swagger Complete Examples

Appendix E: Protocol Buffers Examples

Appendix F: Security Checklist

Appendix G: Testing Checklist

Appendix H: CI/CD Pipeline Examples

Appendix I: Sample API Contracts

Appendix J: Quiz Answers & Solutions

Back Matter

References

Acknowledgements

Index
Chapter 1: Introduction to APIs

1.1 What Is an API?


An API (Application Programming Interface) is a set of defined rules, protocols, and tools that allows
different software applications to communicate with each other. Think of an API as a contract between
two pieces of software: one piece (the client) makes a request, and the other piece (the server) provides
a response, all following a predefined format.

At its most fundamental level, an API abstracts away the internal complexity of a system and exposes
only what external consumers need. You don't need to know how Google's search algorithm works
internally to use the Google Search API — you just need to know what request to send and what
response to expect.

Analogies to Understand APIs


The Restaurant Waiter Analogy: Imagine you're at a restaurant. You (the client) want to order food. The
kitchen (the server) can prepare your meal, but you can't walk into the kitchen yourself. The waiter (the
API) takes your order (request), delivers it to the kitchen, and brings back your food (response). The
waiter is the intermediary that enables communication between you and the kitchen, following a
defined protocol (the menu).

The Electrical Outlet Analogy: An electrical outlet is an API for electricity. You don't need to understand
how the power grid works, how electricity is generated, or how it's transmitted. You just need to know
the interface: plug in a compatible device, and you get power. The outlet defines the "contract" —
voltage, current, plug shape — that both the provider and consumer must follow.

The Universal Remote Analogy: A universal remote control is like an API client. It can communicate with
many different devices (TV, sound system, streaming box) using defined protocols (infrared signals with
specific codes). Each device exposes an "API" of commands it understands (power on, volume up,
change input), and the remote sends the right signals to trigger those commands.
Figure 1.1 — How an API serves as an intermediary between client applications and backend systems

Formal Definition
In formal terms, an API defines:

33. Endpoints: The URLs or addresses where requests can be sent

34. Methods: The operations that can be performed (e.g., GET, POST, PUT, DELETE)

35. Request format: The structure and data the client must send

36. Response format: The structure and data the server will return

37. Authentication: How the client proves its identity

38. Error handling: How errors are communicated back to the client

ô TIP:

APIs are not just for web development. APIs exist everywhere in computing — your operating
system has APIs (Windows API, POSIX), programming languages have APIs (Java Standard Library),
hardware devices have APIs (GPU drivers), and even databases expose APIs (SQL is technically an
API for data access).

1.2 Evolution of APIs


APIs have evolved dramatically over the past five decades. Understanding this evolution helps you
appreciate why modern API technologies exist and what problems they solve.

Era Technology Year Key Characteristics Limitations

Early RPC RPC (Remote 1970s– Call functions on remote Platform-dependent,


Procedure 1980s machines as if they were binary protocols, hard to
Call) local; tightly coupled debug
Era Technology Year Key Characteristics Limitations

Distributed CORBA, 1990s Object-oriented distributed Complex, heavy


Objects DCOM, RMI computing; IDL-defined middleware, vendor
interfaces lock-in

Web SOAP / XML- Late XML-based messaging, Verbose XML, complex


Services RPC 1990s– WSDL contracts, WS-* specifications, heavy
2000s standards payloads

RESTful Web REST 2000– HTTP-based, stateless, Over-fetching/under-


present resource-oriented, JSON fetching, no real-time
payloads built-in

Query GraphQL 2015– Client-specified queries, Complexity, caching


Languages present single endpoint, strong type challenges, N+1 queries
system

High- gRPC 2016– Protocol Buffers, HTTP/2, Not browser-native,


Performance present bidirectional streaming, binary protocol harder to
RPC code generation debug

Event- AsyncAPI, 2017– Asynchronous, event- Eventual consistency,


Driven Webhooks present driven, message brokers, complex debugging,
real-time delivery guarantees

The REST Revolution


In 2000, Roy Fielding published his doctoral dissertation defining Representational State Transfer
(REST). REST leveraged the existing HTTP protocol and introduced a simpler, more intuitive way to build
web APIs compared to the heavyweight SOAP standard. REST's simplicity — combined with the rise of
JSON over XML — sparked an explosion in API adoption that continues today.

The Modern API Landscape


Today, organizations typically use multiple API styles simultaneously. A company might expose REST
APIs for public consumption, use gRPC for internal microservice communication, offer GraphQL for
mobile clients that need flexible queries, and use webhooks for event notifications. The key is choosing
the right tool for each use case.

✅BEST PRACTICE:
Don't adopt a new API technology just because it's trendy. Choose your API style based on your
specific requirements: REST for CRUD operations and broad compatibility, GraphQL for complex
client queries with varying data needs, gRPC for high-performance inter-service communication, and
webhooks for event-driven integrations.

1.3 Types of APIs


APIs can be classified by their accessibility (who can use them) and by their architectural style (how
they work). Let's first examine the accessibility classification:

Type Description Audience Examples

Public (Open) Available to any developer, often External Google Maps API,
APIs with free tiers. May require API key developers, OpenWeatherMap,
registration. public Twitter/X API

Private Used within an organization only. Internal teams Internal user service,
(Internal) Not exposed externally. Powers inventory management API
APIs internal applications.

Partner APIs Shared with specific business Vetted Supplier integrations, B2B
partners under formal agreements partners data exchange
(contracts, SLAs).

Composite Combine multiple API calls into a Internal or Order processing


APIs single request to reduce network partner (combines inventory +
overhead. payment + shipping)

1.4 The API Economy


The API economy refers to the set of business models and practices that have emerged around APIs as
products. APIs are no longer just technical implementation details — they are revenue-generating
products, distribution channels, and competitive advantages.

Key statistics:

● The global API management market is valued at over $5 billion and is projected to grow to $20+
billion by 2030

● Over 90% of developers use APIs in their applications


● Salesforce generates over 50% of its revenue through APIs

● Expedia generates nearly 90% of its revenue through API-powered partner integrations

● Stripe processes hundreds of billions of dollars annually, all through its APIs

TIP:

When evaluating your career growth, note that API-related skills consistently rank among the most
in-demand in software engineering job postings. Understanding API design, security, and scalability
can significantly boost your market value.

1.5 API-First Design Philosophy


API-First design means that the API is treated as a "first-class citizen" in the development process.
Instead of building an application and then bolting on an API, you design the API first — define its
contract, get stakeholder feedback, and then build the implementation behind it.

Benefits of API-First:

● Parallel development: Frontend and backend teams can work simultaneously once the API
contract is defined

● Better design: Thinking about the API upfront leads to cleaner, more consistent interfaces

● Reusability: APIs designed as standalone products are more reusable across applications

● Documentation: API-first naturally produces documentation (from the specification)

● Testing: Contract tests can be written before implementation begins

Companies that follow API-First: Stripe, Twilio, Plaid, SendGrid, Shopify, Slack.

1.6 Real-World API Examples

Company API What It Does Why It Matters

Google Maps API Geocoding, directions, place Powers location features in


search, Street View millions of apps
Company API What It Does Why It Matters

Stripe Payments API Process payments, manage Gold standard for API design
subscriptions, handle refunds and DX

Twilio Communications SMS, voice calls, video, email Programmatic access to


API (SendGrid) telecom infrastructure

X (Twitter) Twitter API Post tweets, read timelines, Enables entire ecosystem of
search, manage users social media tools

Spotify Web API Search music, manage playlists, Powers third-party music
get recommendations applications

GitHub REST + GraphQL Manage repos, issues, PRs, Enables CI/CD tools, project
APIs actions, users management integrations

1.7 How APIs Work: The Request-Response Cycle


At its core, most API communication follows a simple request-response pattern:

39. Client constructs a request: The client application builds an HTTP request containing the
method, URL, headers, and optionally a body

40. DNS resolution: The domain name in the URL is resolved to an IP address

41. TCP connection: A TCP connection is established between client and server (including TLS
handshake for HTTPS)

42. Request sent: The HTTP request is transmitted over the established connection

43. Server processes: The server receives the request, routes it to the appropriate handler, executes
business logic, accesses databases/services as needed

44. Response returned: The server constructs an HTTP response with a status code, headers, and
body, then sends it back

45. Client processes: The client receives and processes the response data
Figure 1.2 — The complete API request-response cycle from client to server

1.8 API Terminology Glossary

Term Definition

Endpoint A specific URL where an API can be accessed. Example:


[Link]

Resource An object or entity that the API manages. Examples: user, product, order, post.

Method The HTTP verb indicating the action: GET (read), POST (create), PUT (replace),
PATCH (update), DELETE (remove).

Header Key-value metadata sent with requests/responses. Used for authentication,


content type, caching, etc.

Payload / The data sent in the request or response body, typically in JSON or XML format.
Body

Status Code A three-digit number in the response indicating the result: 200 OK, 404 Not Found,
500 Server Error, etc.

Authentication Verifying the identity of the caller. "Who are you?"

Authorization Determining what an authenticated caller is allowed to do. "What can you access?"

Rate Limit A restriction on how many API calls a client can make within a time period.

SDK Software Development Kit — a pre-built library that wraps API calls in a language-
specific interface.
Term Definition

Webhook A callback mechanism where the server pushes data to the client's URL when an
event occurs.

Idempotent An operation that produces the same result regardless of how many times it's
executed.

1.9 Setting Up Your Development Environment


Before making your first API call, you need to set up your development tools. Here's what to install:

Essential Tools

Tool Purpose Install Command / Download

[Link] 20+ JavaScript runtime for building APIs Download from [Link] or use nvm
install 20

Python Python runtime for building APIs Download from [Link] or use pyenv
3.11+ install 3.11

Java JDK 21+ Java runtime for Spring Boot APIs Download from [Link] or use
sdkman install java 21

Go 1.22+ Go runtime for high-performance APIs Download from [Link]

VS Code Code editor with API development Download from [Link]


extensions

Postman GUI tool for testing and exploring APIs Download from [Link]

curl Command-line HTTP client (pre- Pre-installed on most systems; Windows:


installed on macOS/Linux) install via winget

httpie User-friendly command-line HTTP client pip install httpie or brew


install httpie

Docker Container runtime for databases and Download from [Link]


deployment

Git Version control Download from [Link]

VS Code Extensions for API Development


● REST Client — Make HTTP requests directly from VS Code

● Thunder Client — Lightweight Postman alternative inside VS Code


● OpenAPI Editor — YAML/JSON editor with OpenAPI schema validation

● Prettier — Auto-format JSON, YAML, and code files

● Docker — Manage containers from VS Code

1.10 Your First API Call


Let's make your first API call using JSONPlaceholder, a free public API for testing and prototyping. We'll
fetch a list of posts from [Link] .

Using curl
BASH

curl -X GET [Link] \ -H "Accept:


application/json" | python -m [Link]
Response:

JSON

{ "userId": 1, "id": 1, "title": "sunt aut facere repellat


provident occaecati excepturi optio reprehenderit", "body": "quia et
suscipit\nsuscipit recusandae consequuntur..." }

Using httpie
BASH

http GET [Link]

Using [Link] (fetch)


JAVASCRIPT

// [Link] const response = await


fetch('[Link] const post = await
[Link](); [Link]('Post Title:', [Link]); [Link]('Post
Body:', [Link]); [Link]('Status:', [Link]);

Using Python (requests)


PYTHON

# first_api_call.py import requests response =


[Link]('[Link] post =
[Link]() print(f"Post Title: {post['title']}") print(f"Post Body:
{post['body']}") print(f"Status Code: {response.status_code}")

Using Java (HttpClient)


JAVA

import [Link].*; import [Link]; public class FirstApiCall {


public static void main(String[] args) throws Exception { HttpClient
client = [Link](); HttpRequest request =
[Link]()
.uri([Link]("[Link]
.header("Accept", "application/json") .GET()
.build(); HttpResponse<String> response = [Link](
request, [Link]() );
[Link]("Status: " + [Link]());
[Link]("Body: " + [Link]()); } }

Using Go (net/http)
GO

package main import ( "fmt" "io" "net/http" ) func main() {


resp, err := [Link]("[Link] if
err != nil { [Link]("Error:", err) return }
defer [Link]() body, _ := [Link]([Link])
[Link]("Status:", [Link]) [Link]("Body:",
string(body)) }

TIP:

JSONPlaceholder ([Link]) is a free, public API that requires no


authentication. It supports all HTTP methods (GET, POST, PUT, PATCH, DELETE) and is perfect for
learning and prototyping. Other great free APIs for practice include: [Link] (request
inspection), [Link] (user CRUD), and [Link] (fun facts).

WARNING:

Never hardcode API keys, tokens, or secrets directly in your source code. Even in tutorials and
learning projects, develop the habit of using environment variables or configuration files.
Accidentally committing credentials to a Git repository is one of the most common and costly
security mistakes in the industry.

✅BEST PRACTICE:
Always check the HTTP status code before processing the response body. A non-2xx status code
means the request was not successful. Build this habit from day one — it will save you hours of
debugging mysterious errors in production.

1.11 Chapter 1 Quiz


Q1. What does API stand for, and what is its primary purpose?

Q2. Name three real-world analogies for an API and explain how each relates to the concept.

Q3. What is the difference between a Public API, a Private API, and a Partner API?

Q4. Roy Fielding defined REST in his doctoral dissertation. In what year was it published?

Q5. What are the four main components of an HTTP request?

Q6. What tool would you use to make API calls from the command line? Name two options.

Q7. What status code would you expect from a successful GET request?

Q8. Explain the difference between authentication and authorization.

Q9. What is an API endpoint? Give an example.

Q10. What percentage of Salesforce's revenue is reportedly generated through APIs?

Q11. Name three advantages of API-First design.

Q12. What is an idempotent operation? Why does it matter for APIs?

Q13. What is the difference between SOAP and REST at a high level?

Q14. What data format has largely replaced XML for modern APIs, and why?

Q15. Write a curl command to make a GET request to [Link] with an


Accept header of application/json.

Hands-on Exercise: Build an API Consumer


Objective: Build a command-line application that fetches all posts from JSONPlaceholder, displays them
in a formatted list, allows the user to select a post by ID to see its full details and comments, and
handles errors gracefully.

Requirements:

46. Fetch all posts from [Link]

47. Display a numbered list with title and userId

48. Accept user input to select a post ID

49. Fetch and display the selected post's details

50. Fetch and display comments for that post from /posts/{id}/comments

51. Handle network errors and invalid input gracefully

Solution (Python):

PYTHON

import requests import sys BASE_URL = "[Link]


def fetch_posts(): """Fetch all posts from the API.""" try:
response = [Link](f"{BASE_URL}/posts", timeout=10)
response.raise_for_status() return [Link]() except
[Link] as e: print(f"Error fetching posts: {e}")
[Link](1) def fetch_post(post_id): """Fetch a single post by ID."""
response = [Link](f"{BASE_URL}/posts/{post_id}", timeout=10)
response.raise_for_status() return [Link]() def
fetch_comments(post_id): """Fetch comments for a specific post."""
response = [Link](f"{BASE_URL}/posts/{post_id}/comments", timeout=10)
response.raise_for_status() return [Link]() def main():
print("=" * 60) print(" JSONPlaceholder API Explorer") print("=" *
60) posts = fetch_posts() print(f"\nFound {len(posts)} posts:\n")
for post in posts[:10]: # Show first 10 print(f" [{post['id']:3d}]
{post['title'][:50]}...") print(f"\n ... and {len(posts) - 10} more
posts") while True: try: post_id =
int(input("\nEnter post ID (1-100) or 0 to quit: ")) if post_id
== 0: break if post_id < 1 or post_id > 100:
print("Invalid ID. Please enter 1-100.") continue
post = fetch_post(post_id) print(f"\n--- Post #{post['id']} ---")
print(f"Title: {post['title']}") print(f"Author (userId):
{post['userId']}") print(f"Body:\n{post['body']}")
comments = fetch_comments(post_id) print(f"\n Comments
({len(comments)}):") for c in comments: print(f"
- {c['name']} ({c['email']})") print(f"
{c['body'][:80]}...") except ValueError: print("Please
enter a valid number.") except [Link] as e:
print(f"API error: {e}") if __name__ == "__main__": main()
Chapter 2: Web Fundamentals

2.1 HTTP Protocol Deep Dive


The Hypertext Transfer Protocol (HTTP) is the foundation of data communication on the Web and the
primary protocol used by APIs. Understanding HTTP deeply is essential for any API developer.

HTTP Version Comparison

Feature HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/3 (QUIC)

Year 1996 1997 2015 2022

Connections New connection per Persistent (keep- Multiplexed Multiplexed


request alive) streams (QUIC/UDP)

Head-of-line Yes Yes (at TCP level) Solved at HTTP Fully solved (UDP)
blocking level

Header No No HPACK QPACK


compression

Server push No No Yes Yes

Protocol TCP TCP TCP + TLS QUIC (UDP + TLS


1.3)

Encryption Optional Optional Practically Built-in


required (mandatory)

HTTP/1.1 is still the most widely deployed version. It introduced persistent connections (keep-alive),
chunked transfer encoding, and the Host header (enabling virtual hosting). However, it suffers from
head-of-line blocking — if one request is slow, subsequent requests on the same connection must wait.

HTTP/2 solved many HTTP/1.1 problems by introducing multiplexing (multiple streams over a single TCP
connection), header compression (HPACK), and server push. For APIs, HTTP/2 significantly reduces
latency, especially when making many parallel requests.

HTTP/3 replaces TCP with QUIC, a UDP-based transport protocol with built-in TLS 1.3 encryption. This
eliminates TCP head-of-line blocking entirely and provides faster connection establishment (0-RTT in
many cases). HTTP/3 is particularly beneficial for mobile API clients on unreliable networks.
Figure 2.1 — The HTTP protocol as the foundation of RESTful APIs

2.2 HTTP Methods


HTTP defines several request methods (also called "verbs") that indicate the desired action to be
performed on the identified resource:

Method Purpose Has Idempotent? Safe? Cacheable?


Body?

GET Retrieve a resource or collection No Yes Yes Yes

POST Create a new resource Yes No No No

PUT Replace a resource entirely Yes Yes No No

PATCH Partially update a resource Yes No* No No

DELETE Remove a resource Optional Yes No No

HEAD Same as GET but returns only headers No Yes Yes Yes

OPTIONS Describe communication options No Yes Yes No


(CORS preflight)

TRACE Diagnostic: echoes back the received No Yes Yes No


request

*PATCH can be idempotent if implemented with JSON Merge Patch, but is not guaranteed to be.
WARNING:

Never use GET requests for operations that modify data. GET requests can be cached by browsers
and proxies, bookmarked by users, and replayed by crawlers. Using GET for destructive operations
(e.g., GET /delete-account) is a serious security vulnerability and design flaw.

When to Use PUT vs PATCH


PUT replaces the entire resource. If you PUT a user object, you must send all fields — any field you omit
will be set to null or its default value. PATCH applies a partial update. You only send the fields you want
to change.

JSON — PUT Request (full replacement)

PUT /api/users/42 { "name": "Sasank", "email": "sasank@[Link]",


"role": "admin", "department": "engineering", "phone": "+1-555-0100"
}
JSON — PATCH Request (partial update)

PATCH /api/users/42 { "email": "[Link]@[Link]" }

2.3 HTTP Status Codes — Complete Reference


1xx — Informational

Code Name Description

100 Continue Server has received request headers; client should proceed to send
body

101 Switching Protocols Server is switching to protocol requested in Upgrade header (e.g.,
WebSocket)

102 Processing Server has received request and is processing (WebDAV)

103 Early Hints Server sends preliminary headers before final response
(preloading)

2xx — Success
Code Name When to Use

200 OK Successful GET, PUT, PATCH, or DELETE. The most common success
code.

201 Created Successful POST that created a new resource. Include Location header
pointing to the new resource.

202 Accepted Request accepted for async processing. The result isn't ready yet.

204 No Content Successful request with no response body. Common for DELETE
operations.

206 Partial Content Response contains only part of the resource (range requests for file
downloads).

3xx — Redirection

Code Name When to Use

301 Moved Resource has permanently moved to new URL. Clients should update
Permanently bookmarks.

302 Found Temporary redirect. Client should use original URL for future requests.

304 Not Modified Resource hasn't changed since last request (conditional GET with
ETags). Saves bandwidth.

307 Temporary Like 302, but the method must not change (POST stays POST).
Redirect

308 Permanent Like 301, but the method must not change.
Redirect

4xx — Client Errors

Code Name When to Use

400 Bad Request Malformed request syntax, invalid parameters, or validation failure.

401 Unauthorized Authentication required or credentials invalid. Should include


WWW-Authenticate header.

403 Forbidden Authenticated but not authorized to access this resource.

404 Not Found Resource does not exist at the specified URL.
Code Name When to Use

405 Method Not HTTP method not supported for this endpoint. Include Allow header
Allowed listing supported methods.

409 Conflict Request conflicts with current state (e.g., duplicate email,
concurrent edit).

413 Payload Too Large Request body exceeds server limits.

415 Unsupported Media Content-Type not supported (e.g., sending XML to a JSON-only
Type endpoint).

422 Unprocessable Request is well-formed but semantically invalid (e.g., email format
Entity wrong).

429 Too Many Requests Rate limit exceeded. Include Retry-After header.

5xx — Server Errors

Code Name When to Use

500 Internal Server Error Generic server error. Something unexpected went wrong.

501 Not Implemented Server doesn't support the functionality required to fulfill the
request.

502 Bad Gateway Server acting as gateway received invalid response from
upstream.

503 Service Unavailable Server temporarily overloaded or under maintenance. Include


Retry-After.

504 Gateway Timeout Gateway/proxy didn't receive response from upstream in time.

✅BEST PRACTICE:

Use the most specific status code that applies. Don't return 200 for everything and hide the actual
status in the response body. Don't return 500 for client errors. The status code is the first thing
automated systems (load balancers, monitoring, client libraries) check — make it meaningful.

2.4 HTTP Headers


Common Request Headers

Header Purpose Example


Accept Media types the client accepts application/json

Content-Type Media type of request body application/json;


charset=utf-8

Authorization Authentication credentials Bearer eyJhbGciOi...

User-Agent Client software identification MyApp/1.0 ([Link])

Accept- Compression algorithms the client gzip, br, deflate


Encoding supports
If-None-Match Conditional request (ETag-based caching) "33a64df551425fcc55e"

X-Request-ID Unique request identifier for tracing 550e8400-e29b-41d4-a716

Common Response Headers

Header Purpose Example


Content-Type Media type of response body application/json

Cache-Control Caching directives max-age=3600, public

ETag Resource version identifier for caching "33a64df551425fcc55e"

Location URL of newly created or redirected /api/users/42


resource
X-RateLimit- Number of requests remaining in window 95
Remaining

Retry-After Seconds to wait before retrying (429/503) 30

2.5 URL Structure


Understanding URL anatomy is critical for API design:

URL ANATOMY

[Link]
=1#section2 |_____| |_______________|___|_|________________|
|_________________________________| |_______| scheme host port
path query parameters fragment
Component Description Example

Scheme Protocol (always HTTPS for production APIs) https

Host Domain name or IP address of the server [Link]

Port Network port (443 for HTTPS, 80 for HTTP) 443 (default, can be omitted)

Path Resource location, hierarchical structure /v2/users/42/posts

Query Filtering, sorting, pagination parameters ?status=published&page=1

Fragment Client-side anchor (not sent to server) #section2

2.6 Request/Response Body Formats

Format Content-Type Pros Cons Use Cases

JSON application/json Lightweight, human- No schema Most


readable, native JS enforcement, no REST/GraphQL
support, widely comments, APIs
supported limited types

XML application/xml Schema validation Verbose, complex SOAP,


(XSD), namespaces, parsing, heavy enterprise,
mature tooling payloads legacy

Protocol application/protobuf Very compact, fast Not human- gRPC, inter-


Buffers serialization, strong readable, service
typing requires proto
definitions

Form application/x-www- Simple key-value Flat structure, no HTML forms,


Data form-urlencoded pairs, browser-native nesting, encoding OAuth token
overhead requests

Multipart multipart/form-data File uploads, mixed Complex parsing, File uploads,


content types large overhead image
for small data processing

2.7 CORS (Cross-Origin Resource Sharing)


CORS is a browser security mechanism that restricts web pages from making requests to a different
domain than the one that served the page. When your frontend at [Link] tries
to call an API at [Link] the browser will block the request unless the API server
explicitly allows it through CORS headers.

How CORS Works


52. Simple requests (GET, POST with standard headers): Browser adds Origin header and sends
the request directly. Server responds with Access-Control-Allow-Origin.

53. Preflight requests (PUT, DELETE, custom headers): Browser first sends an OPTIONS request to
check if the actual request is allowed. If the server responds with appropriate CORS headers, the

browser proceeds with the actual request.

CORS Headers

Header Purpose Example Value


Access-Control- Which origins can access the API [Link]
Allow-Origin or *
Access-Control- Which HTTP methods are allowed GET, POST, PUT, DELETE
Allow-Methods

Access-Control- Which custom headers are allowed Authorization, Content-


Allow-Headers Type

Access-Control-Max- How long preflight results are cached 86400


Age (seconds)
Access-Control- Whether cookies/auth headers are true
Allow-Credentials allowed

WARNING:

Setting Access-Control-Allow-Origin: * allows any website to call your API. This is fine for
public APIs but dangerous for private APIs that rely on cookies or session-based authentication.
Never use * with Access-Control-Allow-Credentials: true — browsers will reject this
combination.

[Link] — Express CORS Configuration


const express = require('express'); const cors = require('cors'); const app =
express(); [Link](cors({ origin: ['[Link]
'[Link] methods: ['GET', 'POST', 'PUT', 'PATCH',
'DELETE'], allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true, maxAge: 86400 }));
PYTHON — FastAPI CORS Configuration

from fastapi import FastAPI from [Link] import


CORSMiddleware app = FastAPI() app.add_middleware( CORSMiddleware,
allow_origins=["[Link] allow_credentials=True,
allow_methods=["*"], allow_headers=["*"], max_age=86400, )

2.8 TCP/IP, TLS, and DNS Fundamentals


TCP Three-Way Handshake
Before any HTTP data can be exchanged, the client and server must establish a TCP connection using a
three-step process:

54. SYN: Client sends a SYN (synchronize) packet to the server

55. SYN-ACK: Server responds with SYN-ACK (synchronize-acknowledge)

56. ACK: Client sends ACK (acknowledge) — connection established

TLS Handshake (HTTPS)


After TCP, an additional TLS handshake occurs for HTTPS:

57. Client sends ClientHello with supported cipher suites and TLS versions

58. Server responds with ServerHello, chosen cipher suite, and its certificate

59. Client verifies server certificate against trusted Certificate Authorities

60. Both sides derive session keys through key exchange (ECDHE in TLS 1.3)

61. Encrypted communication begins

TLS 1.3 improvements: Only 1-RTT handshake (vs 2-RTT in TLS 1.2), supports 0-RTT resumption,
removed outdated cipher suites, faster and more secure.

2.9 WebSockets, SSE, and Polling


Technology Direction Protocol Best For Limitations

Short Polling Client → Server HTTP Simple use cases, low Wasteful, high latency,
(repeated) update frequency server load

Long Polling Client → Server HTTP Near-real-time with Connection management


(held open) HTTP compatibility complexity, timeouts

SSE (Server- Server → Client HTTP Live feeds, One-directional only,


Sent Events) (one-way) notifications, limited browser
dashboards connections

WebSocket Bidirectional WS/WSS Chat, gaming, real- Connection management,


time collaboration proxy/firewall issues

TIP:

For most real-time API use cases (notifications, live updates, dashboards), Server-Sent Events (SSE)
is the simplest and most reliable choice. It works over standard HTTP, supports automatic
reconnection, and is well-supported by browsers. Only reach for WebSockets when you truly need
bidirectional communication (e.g., chat, collaborative editing).

2.10 Chapter 2 Quiz


Q1. What are the main differences between HTTP/1.1 and HTTP/2?

Q2. Which HTTP methods are idempotent? Which are safe?

Q3. When should you return 401 vs 403?

Q4. What is the difference between PUT and PATCH?

Q5. What status code should you return after successfully creating a resource via POST?

Q6. Explain what CORS is and why browsers enforce it.

Q7. What is a preflight request and when does the browser send one?

Q8. Describe the TCP three-way handshake.


Q9. What is the ETag header used for?

Q10. Compare WebSockets, SSE, and Long Polling. When would you choose each?

Q11. What Content-Type header should you set when sending JSON data?

Q12. What does HTTP/3 use instead of TCP, and what advantage does this provide?

Q13. What is the significance of the 429 status code and which header should accompany it?

Q14. Explain the difference between the Accept and Content-Type headers.

Q15. Why should production APIs always use HTTPS (TLS) rather than plain HTTP?

Chapter 3: Types of APIs

3.1 REST APIs


REST (Representational State Transfer) is an architectural style for distributed systems, defined by Roy
Fielding in 2000. REST APIs are the most widely used API type on the web today.

REST Constraints
62. Client-Server: Separation of concerns between UI and data storage/logic

63. Stateless: Each request contains all information needed to process it; no session state stored on
server

64. Cacheable: Responses must define whether they are cacheable

65. Uniform Interface: Standardized way to interact with resources (resource identification via URIs,
manipulation through representations, self-descriptive messages, HATEOAS)

66. Layered System: Client cannot tell whether it's connected directly to the server or through
intermediaries

67. Code on Demand (optional): Server can extend client functionality by sending executable code
Richardson Maturity Model
The Richardson Maturity Model measures how "RESTful" an API truly is:

Level Name Description Example

Level 0 The Swamp Single endpoint, single HTTP method POST /api with action in
of POX (usually POST). Essentially RPC over body
HTTP.

Level 1 Resources Individual URIs for different resources, POST /users, POST
but still uses only POST. /orders

Level 2 HTTP Verbs Uses proper HTTP methods (GET, POST, GET /users, POST
PUT, DELETE) with resources. Most APIs /users, DELETE
are here. /users/42

Level 3 Hypermedia Responses include links to related Response includes


(HATEOAS) resources and available actions. True "_links": {"self":
REST. ..., "orders": ...}

3.2 SOAP APIs


SOAP (Simple Object Access Protocol) is a protocol for exchanging structured information using XML.
While less popular for new development, SOAP remains prevalent in banking, healthcare, and enterprise
environments.

Key SOAP Components:

● WSDL (Web Services Description Language): XML document describing the service, its
operations, messages, and bindings

● SOAP Envelope: XML wrapper containing the header and body of the message

● WS-Security: Standard for securing SOAP messages (encryption, digital signatures)

● WS-ReliableMessaging: Guaranteed message delivery

● WS-Transaction: Distributed transaction support


XML — SOAP Request Example

<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope


xmlns:soap="[Link] <soap:Header>
<auth:credentials xmlns:auth="[Link]
<auth:username>sasank</auth:username>
<auth:token>abc123</auth:token> </auth:credentials>
</soap:Header> <soap:Body> <m:GetUser
xmlns:m="[Link] <m:UserId>42</m:UserId>
</m:GetUser> </soap:Body> </soap:Envelope>

3.3 GraphQL APIs


GraphQL is a query language for APIs developed by Facebook (now Meta) and open-sourced in 2015. It
lets clients request exactly the data they need — no more, no less.

GRAPHQL — Schema Definition

type User { id: ID! name: String! email: String! posts:


[Post!]! } type Post { id: ID! title: String! body: String!
author: User! comments: [Comment!]! } type Query { user(id: ID!):
User users(limit: Int, offset: Int): [User!]! post(id: ID!): Post }
type Mutation { createUser(name: String!, email: String!): User!
createPost(title: String!, body: String!, authorId: ID!): Post! }
GRAPHQL — Client Query

query GetUserWithPosts { user(id: "42") { name email


posts { title comments { body
} } } }

3.4 gRPC APIs


gRPC (Google Remote Procedure Call) is a high-performance, open-source framework that uses Protocol
Buffers for serialization and HTTP/2 for transport.

PROTOBUF — Service Definition

syntax = "proto3"; package userservice; service UserService { rpc


GetUser (GetUserRequest) returns (User); rpc ListUsers (ListUsersRequest)
returns (stream User); // Server streaming rpc CreateUser
(CreateUserRequest) returns (User); } message User { int32 id = 1;
string name = 2; string email = 3; string role = 4; } message
GetUserRequest { int32 id = 1; } message ListUsersRequest { int32
page_size = 1; string page_token = 2; } message CreateUserRequest {
string name = 1; string email = 2; }

3.5 WebSocket & Webhook APIs


WebSocket APIs provide full-duplex communication over a single TCP connection. After an HTTP
handshake upgrades the connection to WebSocket, both client and server can send messages freely
without the overhead of HTTP headers for each message.

Webhook APIs reverse the traditional request-response model. Instead of the client polling for updates,
the server sends HTTP POST requests to a client-specified URL when events occur.

JAVASCRIPT — WebSocket Client

const ws = new WebSocket('[Link] [Link] = () => {


[Link]('Connected'); [Link]([Link]({ type: 'subscribe',
channel: 'orders' })); }; [Link] = (event) => { const data =
[Link]([Link]); [Link]('Received:', data); }; [Link] =
() => [Link]('Disconnected'); [Link] = (err) =>
[Link]('Error:', err);

3.6 AsyncAPI & Event-Driven APIs


Event-driven APIs use message brokers (Kafka, RabbitMQ, MQTT) to enable asynchronous, decoupled
communication between services. The AsyncAPI specification provides a standard way to document
these APIs, similar to how OpenAPI documents REST APIs.

3.7 Comprehensive Comparison Matrix

Figure 3.1 — API architectural styles comparison overview

Criteria REST SOAP GraphQL gRPC WebSocket Webhook

Protocol HTTP/HTTP HTTP, HTTP/HTTPS HTTP/2 WS/WSS HTTP/HTTP


S SMTP, TCP S

Data JSON, XML XML only JSON Protocol Any JSON


Format Buffers

Direction Request- Request- Request- Unary + Bidirection Server →


Response Response Response Streaming al Client

Real-time No No Yes Yes Yes Yes (push)


(polling) (subscription (streaming)
s)
Criteria REST SOAP GraphQL gRPC WebSocket Webhook

Type Safety Weak Strong Strong Strong None None


(JSON (XSD/WSD (schema) (protobuf)
Schema) L)

Performanc Good Poor (XML Good Excellent Excellent Good


e overhead) (flexible) (binary)

Browser Excellent Limited Excellent Via gRPC- Excellent N/A


Support Web

Caching HTTP Complex Difficult Not built-in N/A N/A


caching

Learning Low High Medium Medium- Low- Low


Curve High Medium

Best For CRUD, Enterprise, Complex Microservice Chat, Notification


public APIs banking queries, s, IoT gaming s
mobile

✅BEST PRACTICE:

Most organizations benefit from a polyglot API strategy: REST for external/public APIs (broadest
compatibility), gRPC for internal microservice communication (performance), GraphQL for BFF
(Backend for Frontend) layers serving mobile clients, and webhooks for event notifications to
partners. Don't force one style on every use case.

3.8 Chapter 3 Quiz


Q1. List the six REST architectural constraints.

Q2. What is the Richardson Maturity Model and what level are most real-world APIs at?

Q3. What is HATEOAS and why do few APIs implement it in practice?

Q4. Describe the over-fetching and under-fetching problems that GraphQL solves.

Q5. What serialization format does gRPC use, and why is it faster than JSON?

Q6. When would you choose SOAP over REST for a new project?
Q7. Explain the difference between a WebSocket connection and an HTTP connection.

Q8. What is a webhook? How does it differ from polling?

Q9. What transport protocol does gRPC use, and what advantages does it provide?

Q10. Name three gRPC streaming types and give a use case for each.

Chapter 4: API Design Principles

4.1 API-First Design


In API-First design, you write the API specification (OpenAPI/Swagger) before writing any code. This
specification becomes the single source of truth that frontend teams, backend teams, QA, and
documentation writers all work from simultaneously.

API-First Workflow
68. Define requirements: Gather use cases, identify resources, map data models

69. Write the specification: Create an OpenAPI 3.1 YAML/JSON document

70. Review with stakeholders: Get feedback from frontend, mobile, QA, and product teams

71. Generate mocks: Use Prism or similar tools to create a mock server from the spec

72. Parallel development: Frontend builds against mocks; backend implements the spec

73. Contract testing: Automated tests verify implementation matches the specification

74. Generate documentation: Auto-generate interactive docs from the spec

4.2 Resource Naming & URI Design


Naming Rules
Rule Good ✓ Bad ✗ Why

Use nouns, /users /getUsers HTTP methods


not verbs already express the
action

Use plurals /users /user Consistency:


for /users (list) and
collections /users/42 (single)

Use kebab- /user-profiles /userProfiles URLs are case-


case insensitive by
convention

Nest for /users/42/posts /getUserPosts?userId=42 Hierarchy expresses


relationshi ownership/relations
ps hip

Limit /users/42/posts /users/42/posts/5/comments/3/l Deep nesting


nesting ikes creates rigid, hard-
depth (≤3) to-maintain URLs

Use query /users?role=adm /admin-users Filtering shouldn't


params for in create new
filtering endpoints

URI Design Patterns


REST URI Examples

# Collection operations GET /api/v1/users # List all users


(with pagination) POST /api/v1/users # Create a new user #
Single resource operations GET /api/v1/users/42 # Get user by
ID PUT /api/v1/users/42 # Replace user PATCH /api/v1/users/42
# Partially update user DELETE /api/v1/users/42 # Delete user #
Sub-resources GET /api/v1/users/42/posts # Get posts by user 42 POST
/api/v1/users/42/posts # Create post for user 42 # Filtering, sorting,
searching GET /api/v1/users?role=admin&status=active GET
/api/v1/users?sort=-created_at,name GET /api/v1/users?search=sasank #
Pagination GET /api/v1/users?page=2&per_page=25 GET
/api/v1/users?cursor=eyJpZCI6MTAwfQ==&limit=25 # Actions (when CRUD doesn't
fit) POST /api/v1/users/42/activate POST /api/v1/orders/99/cancel

4.3 Pagination, Filtering, and Sorting


Pagination Strategies
Strategy How It Works Pros Cons Best For

Offset- ?page=3&per_page=25 or Simple, Slow on large datasets Small


based ?offset=50&limit=25 supports (OFFSET scans), datasets,
"jump to inconsistent with admin panels
page N" concurrent writes

Cursor- ?cursor=abc123&limit=25 Consistent No "jump to page N", Infinite scroll,


based results, fast cursor must be opaque mobile, large
at scale datasets
(indexed
queries)

Keyset- ?after_id=100&limit=25 Very fast Requires sortable, Time-series


based (uses indexed unique column; no data, feeds
column), random page access
simple to
understand

Pagination Response Format


JSON — Cursor-based Pagination Response

{ "data": [ { "id": 101, "name": "User A" }, { "id": 102,


"name": "User B" } ], "pagination": { "next_cursor":
"eyJpZCI6MTAyfQ==", "prev_cursor": "eyJpZCI6MTAxfQ==",
"has_more": true, "total_count": 1250 } }

4.4 Error Handling & Response Design


RFC 7807 — Problem Details for HTTP APIs
RFC 7807 defines a standard format for error responses, ensuring consistency across your API:

JSON — RFC 7807 Error Response

{ "type": "[Link] "title":


"Validation Error", "status": 422, "detail": "The request body
contains invalid fields.", "instance": "/api/v1/users", "errors": [
{ "field": "email", "message": "Must be a valid email
address", "code": "INVALID_FORMAT" }, {
"field": "age", "message": "Must be between 13 and 150",
"code": "OUT_OF_RANGE" } ], "trace_id": "abc-123-def-456" }

WARNING:

Never expose internal implementation details in error messages sent to clients. Stack traces,
database table names, internal IP addresses, or SQL queries in error responses are information
disclosure vulnerabilities. Log detailed errors server-side and return sanitized, user-friendly
messages to clients.

4.5 HATEOAS & Hypermedia


HATEOAS (Hypermedia as the Engine of Application State) means that API responses include hyperlinks
to related resources and available actions. The client doesn't need to hardcode URL patterns — it
discovers them by following links.

JSON — HATEOAS Response (HAL format)

{ "id": 42, "name": "Sasank", "email": "sasank@[Link]",


"status": "active", "_links": { "self": { "href":
"/api/v1/users/42" }, "posts": { "href": "/api/v1/users/42/posts" },
"deactivate": { "href": "/api/v1/users/42/deactivate", "method": "POST" },
"update": { "href": "/api/v1/users/42", "method": "PATCH" } } }

4.6 Idempotency
An operation is idempotent if performing it multiple times has the same effect as performing it once.
This is critical for reliability — if a network failure occurs after a client sends a request but before it
receives a response, the client can safely retry without causing duplicate side effects.

Method Idempotent? Example

GET Yes Fetching a user always returns the same user

PUT Yes Replacing a user with the same data has no additional effect

DELETE Yes Deleting an already-deleted resource returns 404 but causes no harm

POST No Each POST /orders creates a new order

PATCH Maybe Depends on implementation (absolute vs relative changes)

Idempotency Keys
For non-idempotent operations like POST, implement idempotency keys: the client sends a unique key
(usually a UUID) in the Idempotency-Key header. The server stores the result and returns the same
response for duplicate keys.

BASH — Request with Idempotency Key


curl -X POST [Link] \ -H "Authorization:
Bearer sk_live_abc123" \ -H "Idempotency-Key: 550e8400-e29b-41d4-a716-
446655440000" \ -H "Content-Type: application/json" \ -d '{"amount":
2000, "currency": "usd", "customer": "cus_123"}'

✅BEST PRACTICE:

Implement idempotency keys for any API endpoint that creates resources or triggers side effects
(payments, emails, order placement). Stripe's API is the gold standard — every POST request
supports an Idempotency-Key header, making retries safe and ensuring at-most-once semantics.

4.7 API Contracts & OpenAPI


An API contract is a formal specification that defines what the API looks like, what inputs it expects, and
what outputs it returns. The OpenAPI Specification (OAS), formerly known as Swagger, is the industry
standard for documenting REST APIs.

YAML — OpenAPI 3.1 Example (excerpt)

openapi: 3.1.0 info: title: User Management API version: 1.0.0


description: API for managing users servers: - url:
[Link] paths: /users: get: summary: List all
users parameters: - name: page in: query
schema: type: integer default: 1 - name:
per_page in: query schema: type: integer
default: 25 maximum: 100 responses: '200':
description: Successful response content:
application/json: schema: type: object
properties: data: type: array
items: $ref: '#/components/schemas/User'
pagination: $ref: '#/components/schemas/Pagination'
post: summary: Create a new user requestBody: required:
true content: application/json: schema:
$ref: '#/components/schemas/CreateUserRequest' responses:
'201': description: User created headers:
Location: schema: type: string
content: application/json: schema:
$ref: '#/components/schemas/User' '422': description:
Validation error content: application/json:
schema: $ref: '#/components/schemas/Error' components:
schemas: User: type: object properties: id:
type: integer name: type: string email:
type: string format: email created_at: type:
string format: date-time CreateUserRequest: type: object
required: [name, email] properties: name: type:
string minLength: 1 maxLength: 100 email:
type: string format: email
4.8 Chapter 4 Quiz
Q1. What is API-First design and what are its three biggest advantages?

Q2. Should API resource names be nouns or verbs? Explain why.

Q3. Compare offset-based and cursor-based pagination. Which scales better?

Q4. What is RFC 7807 and what problem does it solve?

Q5. What is an idempotency key and when should you use one?

Q6. What is HATEOAS? Give an example of a HATEOAS response.

Q7. Design the URI structure for a blog API with users, posts, comments, and tags.

Q8. What is the OpenAPI Specification and how does it benefit API development?

Chapter 5: RESTful API Deep Dive

5.1 REST Constraints in Practice


Let's examine each REST constraint with practical examples that show how they affect real-world API
design and implementation.

Statelessness in Practice
Statelessness means the server does not store any client session state between requests. Every request
must contain all the information needed to process it — including authentication credentials (typically a
JWT token in the Authorization header).

JAVASCRIPT — Stateless Request (each request is self-contained)

// Every request includes the auth token — no server-side session const


response = await fetch('[Link] { headers:
{ 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIs...',
'Accept': 'application/json' } });
5.2 Advanced HTTP Methods
JSON Patch (RFC 6902)
JSON Patch is a format for describing changes to a JSON document using an array of operations:

JSON — JSON Patch Operations

PATCH /api/v1/users/42 Content-Type: application/json-patch+json [ {


"op": "replace", "path": "/email", "value": "new@[Link]" }, { "op":
"add", "path": "/phone", "value": "+1-555-0100" }, { "op": "remove",
"path": "/nickname" }, { "op": "test", "path": "/version", "value": 5 } ]

Conditional Requests with ETags


ETags enable optimistic concurrency control and efficient caching:

BASH — Conditional Update with ETag

# 1. GET the resource (server returns ETag) GET /api/v1/users/42 # Response:


ETag: "v5-abc123" # 2. Update only if the resource hasn't changed (prevents
lost updates) PUT /api/v1/users/42 If-Match: "v5-abc123" Content-Type:
application/json {"name": "Sasank Updated", "email": "sasank@[Link]"}
# If another client modified it first → 412 Precondition Failed # If it
matches → 200 OK with new ETag

5.3 Building a Complete RESTful API — [Link]/Express


Project Structure
TEXT — Project Directory Structure

task-api/ ├── src/ │ ├── config/ │ │ ├── [Link] │ │ └── [Link]


│ ├── middleware/ │ │ ├── [Link] │ │ ├── [Link] │ │
├── [Link] │ │ └── [Link] │ ├── models/ │ │ ├──
[Link] │ │ └── [Link] │ ├── routes/ │ │ ├── [Link] │ │
├── [Link] │ │ └── [Link] │ ├── controllers/ │ │
├── [Link] │ │ ├── [Link] │ │ └──
[Link] │ ├── services/ │ │ ├── [Link] │ │ └──
[Link] │ └── [Link] ├── tests/ ├── Dockerfile ├── docker-
[Link] ├── [Link] └── .env

Main Application ([Link])


JAVASCRIPT

const express = require('express'); const cors = require('cors'); const


helmet = require('helmet'); const morgan = require('morgan'); const {
connectDB } = require('./config/database'); const { errorHandler } =
require('./middleware/errorHandler'); const authRoutes =
require('./routes/[Link]'); const userRoutes =
require('./routes/[Link]'); const taskRoutes =
require('./routes/[Link]'); const app = express(); // Security &
parsing middleware [Link](helmet()); [Link](cors({ origin:
[Link].ALLOWED_ORIGINS?.split(',') })); [Link](morgan('combined'));
[Link]([Link]({ limit: '10mb' })); // Health check [Link]('/health',
(req, res) => { [Link]({ status: 'healthy', timestamp: new
Date().toISOString() }); }); // Routes [Link]('/api/v1/auth', authRoutes);
[Link]('/api/v1/users', userRoutes); [Link]('/api/v1/tasks', taskRoutes);
// Global error handler [Link](errorHandler); // Start server const PORT =
[Link] || 3000; connectDB().then(() => { [Link](PORT, () =>
[Link](`API running on port ${PORT}`)); });

Task Controller with Pagination


JAVASCRIPT

const Task = require('../models/Task'); [Link] = async (req, res,


next) => { try { const { page = 1,
per_page = 25, status, priority, sort =
'-created_at', search } = [Link]; // Build
filter const filter = { user: [Link] }; if (status)
[Link] = status; if (priority) [Link] = priority;
if (search) { filter.$text = { $search: search }; }
// Parse sort const sortObj = {};
[Link](',').forEach(field => { if ([Link]('-')) {
sortObj[[Link](1)] = -1; } else {
sortObj[field] = 1; } }); const skip =
(parseInt(page) - 1) * parseInt(per_page); const limit =
[Link](parseInt(per_page), 100); const [tasks, total] = await
[Link]([
[Link](filter).sort(sortObj).skip(skip).limit(limit),
[Link](filter) ]); [Link]({ data:
tasks, pagination: { page: parseInt(page),
per_page: limit, total, total_pages:
[Link](total / limit), has_more: skip + [Link] <
total } }); } catch (error) { next(error);
} };

TIP:

Always cap the per_page parameter with a maximum value (e.g., 100). Without this, a client could
request per_page=1000000, potentially overwhelming your database and crashing your server.
Validate and sanitize all query parameters.

5.4 Building the Same API — Python/FastAPI


PYTHON

from fastapi import FastAPI, Query, Depends, HTTPException, status from


pydantic import BaseModel, EmailStr from typing import Optional from datetime
import datetime app = FastAPI(title="Task API", version="1.0.0") class
TaskCreate(BaseModel): title: str description: Optional[str] = None
priority: str = "medium" due_date: Optional[datetime] = None class
TaskResponse(BaseModel): id: int title: str description:
Optional[str] status: str priority: str created_at: datetime
updated_at: datetime class PaginatedResponse(BaseModel): data:
list[TaskResponse] total: int page: int per_page: int
has_more: bool @[Link]("/api/v1/tasks", response_model=PaginatedResponse)
async def list_tasks( page: int = Query(1, ge=1), per_page: int =
Query(25, ge=1, le=100), status: Optional[str] = None, priority:
Optional[str] = None, sort: str = "-created_at", search:
Optional[str] = None, ): """List tasks with filtering, sorting, and
pagination.""" # Build query (simplified — real implementation uses
SQLAlchemy/Tortoise) tasks = await [Link](status=status,
priority=priority) \ .offset((page - 1) * per_page) \
.limit(per_page) total = await [Link]() return
PaginatedResponse( data=tasks, total=total,
page=page, per_page=per_page, has_more=(page * per_page) <
total ) @[Link]("/api/v1/tasks", status_code=status.HTTP_201_CREATED)
async def create_task(task: TaskCreate): """Create a new task."""
new_task = await [Link](**[Link]()) return new_task

5.5 Chapter 5 Quiz


Q1. Explain the difference between JSON Patch and JSON Merge Patch.

Q2. How do ETags enable optimistic concurrency control?

Q3. What HTTP status code should you return if an If-Match condition fails?

Q4. Why is it important to cap the per_page parameter in pagination?

Q5. Describe the typical folder structure for a REST API project and explain the purpose of each layer.

Chapter 6: GraphQL & Alternatives

6.1 GraphQL Fundamentals


GraphQL provides a complete description of the data in your API through a type system. Clients send
queries that exactly describe the data they need, and the server returns exactly that data — nothing
more, nothing less.

Building a GraphQL Server — [Link] (Apollo Server)


JAVASCRIPT

const { ApolloServer } = require('@apollo/server'); const {


startStandaloneServer } = require('@apollo/server/standalone'); const
typeDefs = `#graphql type User { id: ID! name: String!
email: String! posts: [Post!]! } type Post { id: ID!
title: String! body: String! author: User! createdAt:
String! } type Query { users(limit: Int = 10, offset: Int =
0): [User!]! user(id: ID!): User posts(authorId: ID):
[Post!]! } type Mutation { createUser(input:
CreateUserInput!): User! createPost(input: CreatePostInput!): Post!
} input CreateUserInput { name: String! email: String!
} input CreatePostInput { title: String! body: String!
authorId: ID! } `; const resolvers = { Query: { users: (_, {
limit, offset }) => [Link]({ limit, offset }),
user: (_, { id }) => [Link](id), posts: (_, {
authorId }) => authorId ? [Link](authorId) :
[Link]() }, User: { posts: (user) =>
[Link]([Link]) }, Mutation: { createUser: (_,
{ input }) => [Link](input), createPost: (_, { input }) =>
[Link](input) } }; const server = new ApolloServer({ typeDefs,
resolvers }); const { url } = await startStandaloneServer(server, { listen: {
port: 4000 } }); [Link](`GraphQL server running at ${url}`);

The N+1 Problem and DataLoader


When a GraphQL query requests nested data (e.g., users with their posts), a naive resolver makes 1
query for users + N queries for each user's posts. The DataLoader pattern batches and caches these
lookups:

JAVASCRIPT

const DataLoader = require('dataloader'); // Batch function: receives an


array of user IDs, returns posts grouped by userId const postsByUserLoader =
new DataLoader(async (userIds) => { const posts = await
[Link](userIds); // Single DB query // Group posts by
userId and return in same order as input IDs return [Link](id =>
[Link](p => [Link] === id)); }); // Resolver uses DataLoader
instead of direct DB call const resolvers = { User: { posts:
(user) => [Link]([Link]) } };

WARNING:

Without DataLoader or a similar batching solution, GraphQL APIs can suffer severe N+1 query
performance issues. For a query returning 100 users with posts, a naive implementation executes
101 database queries (1 for users + 100 for posts). DataLoader reduces this to 2 queries. Always
implement DataLoader for nested resolvers in production.

6.2 GraphQL Security


Attack Vector Mitigation Implementation

Deep nesting attacks Query depth limiting Max depth of 10 levels

Wide queries Query complexity analysis Assign cost to fields, cap total cost

Introspection abuse Disable introspection in production introspection: false in config

Batch attacks Limit batch size Max 10 queries per batch request

Resource exhaustion Persisted queries Only allow pre-approved query


hashes

6.3 Chapter 6 Quiz


Q1. What is the N+1 problem in GraphQL, and how does DataLoader solve it?

Q2. Compare GraphQL queries and mutations. When do you use each?

Q3. What are GraphQL subscriptions and what transport do they typically use?

Q4. Name three GraphQL security concerns and their mitigations.

Q5. When would you choose GraphQL over REST?

Chapter 7: gRPC & Protocol Buffers

7.1 Protocol Buffers (proto3)


Protocol Buffers (protobuf) is Google's language-neutral, platform-neutral mechanism for serializing
structured data. It is more compact, faster to serialize/deserialize, and more strongly typed than JSON.

Proto3 Syntax Reference


PROTOBUF

syntax = "proto3"; package ecommerce; import


"google/protobuf/[Link]"; // Enum definition enum OrderStatus {
ORDER_STATUS_UNSPECIFIED = 0; ORDER_STATUS_PENDING = 1;
ORDER_STATUS_CONFIRMED = 2; ORDER_STATUS_SHIPPED = 3;
ORDER_STATUS_DELIVERED = 4; ORDER_STATUS_CANCELLED = 5; } // Message
with various field types message Product { int32 id = 1; string name
= 2; string description = 3; double price = 4; int32
stock_quantity = 5; repeated string tags = 6; // Array of
strings map<string, string> metadata = 7; // Key-value pairs
[Link] created_at = 8; } message Order { int32 id =
1; int32 customer_id = 2; repeated OrderItem items = 3;
OrderStatus status = 4; double total_amount = 5; // Nested message
message OrderItem { int32 product_id = 1; int32 quantity = 2;
double unit_price = 3; } } // Service with all four streaming types
service OrderService { // Unary RPC rpc CreateOrder
(CreateOrderRequest) returns (Order); // Server streaming — server
sends a stream of updates rpc TrackOrder (TrackOrderRequest) returns
(stream OrderUpdate); // Client streaming — client sends a stream of
items rpc UploadBulkOrders (stream Order) returns (BulkOrderResponse);
// Bidirectional streaming — both stream simultaneously rpc LiveOrderChat
(stream ChatMessage) returns (stream ChatMessage); }

7.2 gRPC Streaming Patterns

Pattern Description Use Cases

Unary Client sends one request, server sends one CRUD operations, simple lookups
response (like REST)

Server Streaming Client sends one request, server streams Real-time updates, progress
multiple responses tracking, live feeds

Client Streaming Client streams multiple messages, server File upload, bulk data ingestion,
sends one response sensor data

Bidirectional Both client and server stream messages Chat, real-time collaboration,
Streaming independently gaming

gRPC Server in Go
GO

package main import ( "context" "log" "net" pb


"myapp/proto/userservice" "[Link]/grpc" ) type server struct
{ [Link] } func (s *server) GetUser(ctx
[Link], req *[Link]) (*[Link], error) { // Fetch
user from database user := &[Link]{ Id: [Link], Name:
"Sasank", Email: "sasank@[Link]", Role: "admin", }
return user, nil } func main() { lis, err := [Link]("tcp", ":50051")
if err != nil { [Link]("Failed to listen: %v", err) } s
:= [Link]() [Link](s, &server{})
[Link]("gRPC server listening on :50051") if err := [Link](lis);
err != nil { [Link]("Failed to serve: %v", err) } }

✅BEST PRACTICE:
When designing proto files, always use field numbers 1–15 for the most frequently accessed fields
(they use only 1 byte for encoding). Fields 16–2047 use 2 bytes. Never reuse or change field
numbers after deployment — this breaks backward compatibility. Mark deprecated fields as
reserved.

7.3 Chapter 7 Quiz


Q1. What are the four gRPC streaming types? Give a use case for each.

Q2. Why is Protocol Buffers faster than JSON for serialization?

Q3. What transport protocol does gRPC use, and why?

Q4. How do you handle backward compatibility in proto files?

Q5. What is gRPC-Web and why is it needed?

Chapter 8: Authentication & Authorization

8.1 Authentication vs Authorization

Aspect Authentication (AuthN) Authorization (AuthZ)

Question "Who are you?" "What are you allowed to do?"

When First — before authorization After authentication succeeds

Mechanism Credentials (password, token, Permissions, roles, policies


certificate)

Failure Code 401 Unauthorized 403 Forbidden

Example Logging in with username/password Admin can delete users; regular user
cannot
8.2 API Authentication Methods

Method Security Level Complexity Best For

API Keys Low-Medium Low Public APIs, server-to-server, rate limiting

Basic Auth Low (requires Very Low Internal tools, simple scripts (over HTTPS
HTTPS) only)

JWT (Bearer Medium-High Medium Single-page apps, mobile apps,


Token) microservices

OAuth 2.0 High High Third-party integrations, delegated access

Mutual TLS (mTLS) Very High High Zero-trust, service mesh, banking

8.3 OAuth 2.0 Deep Dive


Figure 8.1 — OAuth 2.0 authorization flows overview

OAuth 2.0 Grant Types

Grant Type Use Case Client Type Flow

Authorization Web apps, mobile apps, Public or User authenticates via browser →
Code + PKCE SPAs Confidential auth code → exchange for tokens

Client Machine-to-machine Confidential Client sends credentials directly →


Credentials communication receives access token

Device Code TVs, IoT, CLI tools (devices Public Device displays code → user
without keyboards) authorizes on another device
Grant Type Use Case Client Type Flow

Refresh Token Renewing expired access Any Client sends refresh token →
tokens receives new access token

WARNING:

The Implicit Grant and Resource Owner Password Credentials (ROPC) grant types are deprecated in
OAuth 2.1 and should NEVER be used in new implementations. The Implicit Grant exposes tokens in
URLs (browser history, referrer headers). ROPC requires the client to handle the user's password
directly. Always use Authorization Code + PKCE instead.

8.4 JWT (JSON Web Tokens)


A JWT consists of three Base64URL-encoded parts separated by dots: [Link]

JSON — JWT Header

{ "alg": "RS256", "typ": "JWT", "kid": "key-2026-04" }


JSON — JWT Payload (Claims)

{ "sub": "user_42", "name": "Sasank", "email":


"sasank@[Link]", "roles": ["admin", "user"], "iat": 1777000000,
"exp": 1777003600, "iss": "[Link] "aud":
"[Link] }

JWT Implementation — [Link]


JAVASCRIPT

const jwt = require('jsonwebtoken'); const { readFileSync } = require('fs');


// Use RS256 (asymmetric) in production — never HS256 with shared secrets
const PRIVATE_KEY = readFileSync('./keys/[Link]'); const PUBLIC_KEY =
readFileSync('./keys/[Link]'); // Generate token function
generateAccessToken(user) { return [Link]( { sub:
[Link], name: [Link], roles: [Link]
}, PRIVATE_KEY, { algorithm: 'RS256',
expiresIn: '15m', // Short-lived access token issuer:
'[Link] audience: '[Link]
} ); } function generateRefreshToken(user) { return [Link](
{ sub: [Link], type: 'refresh' }, PRIVATE_KEY, { algorithm:
'RS256', expiresIn: '7d' } ); } // Verify token middleware function
authenticate(req, res, next) { const authHeader =
[Link]; if (!authHeader?.startsWith('Bearer ')) {
return [Link](401).json({ error: 'Missing authentication token' }); }
const token = [Link](' ')[1]; try { const decoded =
[Link](token, PUBLIC_KEY, { algorithms: ['RS256'],
issuer: '[Link] audience:
'[Link] }); [Link] = decoded;
next(); } catch (err) { if ([Link] === 'TokenExpiredError') {
return [Link](401).json({ error: 'Token expired' }); }
return [Link](401).json({ error: 'Invalid token' }); } }

RBAC (Role-Based Access Control) Middleware


JAVASCRIPT

function authorize(...requiredRoles) { return (req, res, next) => {


if (![Link]) { return [Link](401).json({ error: 'Not
authenticated' }); } const hasRole = [Link](role
=> [Link](role)); if (!hasRole) { return
[Link](403).json({ error: 'Forbidden',
message: `Required roles: ${[Link](', ')}` });
} next(); }; } // Usage in routes
[Link]('/api/v1/users/:id', authenticate, authorize('admin'),
deleteUser); [Link]('/api/v1/users', authenticate, authorize('admin',
'manager'), listUsers); [Link]('/api/v1/users/me', authenticate,
getMyProfile); // Any authenticated user

✅BEST PRACTICE:

Keep access tokens short-lived (5–15 minutes) and use refresh tokens for renewal. Store refresh
tokens securely (HTTP-only cookies for web apps, secure storage for mobile). Implement token
revocation by maintaining a blocklist of revoked tokens or using token versioning. Never store JWTs
in localStorage — it's vulnerable to XSS attacks.

8.5 Chapter 8 Quiz


Q1. What is the difference between authentication and authorization?

Q2. Name the three parts of a JWT and describe what each contains.

Q3. Why is RS256 preferred over HS256 for JWT signing in microservices?

Q4. Explain the OAuth 2.0 Authorization Code + PKCE flow step by step.

Q5. Why should you never store JWTs in localStorage?

Chapter 9: Rate Limiting & Quotas


9.1 Rate Limiting Algorithms

Algorithm How It Works Pros Cons

Fixed Window Counter per time window (e.g., 100 Simple, low Burst at window
req/min). Resets at window memory edges (can get 2x
boundary. limit)

Sliding Store timestamp of each request. Accurate, no burst High memory (stores
Window Log Count requests in sliding window. issue all timestamps)

Sliding Weighted average of current and Low memory, Approximate (not


Window previous window counters. smooth rate 100% accurate)
Counter limiting

Token Bucket Bucket fills with tokens at fixed Allows controlled Slightly more complex
rate. Each request consumes a bursts, smooth
token.

Leaky Bucket Requests enter a queue processed Smooth output Requests may be
at fixed rate. Overflow is dropped. rate, prevents delayed or dropped
bursts

Token Bucket Implementation — [Link] with Redis


JAVASCRIPT

const Redis = require('ioredis'); const redis = new Redis(); async function


tokenBucketLimiter(key, maxTokens, refillRate) { const now = [Link]();
const bucketKey = `ratelimit:${key}`; // Lua script for atomic token
bucket operation const luaScript = ` local key = KEYS[1]
local max_tokens = tonumber(ARGV[1]) local refill_rate =
tonumber(ARGV[2]) local now = tonumber(ARGV[3])
local bucket = [Link]('HMGET', key, 'tokens', 'last_refill')
local tokens = tonumber(bucket[1]) or max_tokens local last_refill =
tonumber(bucket[2]) or now -- Calculate tokens to add since
last refill local elapsed = (now - last_refill) / 1000 tokens
= [Link](max_tokens, tokens + (elapsed * refill_rate)) if
tokens >= 1 then tokens = tokens - 1
[Link]('HMSET', key, 'tokens', tokens, 'last_refill', now)
[Link]('EXPIRE', key, [Link](max_tokens / refill_rate) + 1)
return {1, [Link](tokens)} else [Link]('HMSET',
key, 'tokens', tokens, 'last_refill', now) return {0,
[Link](tokens)} end `; const [allowed, remaining] =
await [Link]( luaScript, 1, bucketKey, maxTokens, refillRate, now
); return { allowed: allowed === 1, remaining }; } // Express
middleware function rateLimitMiddleware(maxTokens = 100, refillRate = 10) {
return async (req, res, next) => { const key = [Link]; // or
[Link]?.id or API key const result = await tokenBucketLimiter(key,
maxTokens, refillRate); [Link]('X-RateLimit-Limit', maxTokens);
[Link]('X-RateLimit-Remaining', [Link]); if
(![Link]) { [Link]('Retry-After', [Link](1 /
refillRate)); return [Link](429).json({
error: 'Too Many Requests', message: 'Rate limit exceeded.
Please retry later.', retry_after: [Link](1 / refillRate)
}); } next(); }; }

TIP:

Always include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset


headers in every response (not just 429 responses). This allows well-behaved clients to proactively
slow down before hitting the limit, resulting in a better experience for everyone.

Chapter 10: Versioning & Lifecycle

10.1 API Versioning Strategies

Strategy Example Pros Cons

URI Path /api/v1/users Explicit, easy to Pollutes URIs, can


understand, easy to break HATEOAS
route

Query /api/users?version=1 Optional, backward- Easy to forget, can


Parameter compatible default break caching

Custom X-API-Version: 1 Clean URIs, explicit Hidden, harder to


Header test in browser

Content Accept: RESTful, media type Complex, not widely


Negotiation application/[Link].v1+json driven understood

10.2 Breaking vs Non-Breaking Changes


Non-Breaking (Safe) ✓ Breaking (Dangerous) ✗

Adding a new optional field to request/response Removing a field from the response

Adding a new endpoint Renaming an existing endpoint

Adding a new optional query parameter Changing a field's data type

Adding a new enum value Making a previously optional field required

Relaxing a validation constraint Tightening a validation constraint

Adding a new HTTP method to an existing resource Changing the meaning of an existing field

Increasing a rate limit Decreasing a rate limit

10.3 API Lifecycle


75. Design: Write OpenAPI spec, review with stakeholders, mock and test

76. Develop: Implement the API, write tests, generate documentation

77. Test: Unit, integration, contract, performance, and security testing

78. Deploy: Deploy to staging, then production with canary/blue-green

79. Monitor: Track latency, errors, usage, SLOs

80. Evolve: Add features with non-breaking changes, bump minor version

81. Deprecate: Announce deprecation, set Sunset header, provide migration guide

82. Sunset: Remove the old version after sufficient notice period (minimum 6–12 months)

✅BEST PRACTICE:

When deprecating an API version, use the Sunset header (RFC 8594) and Deprecation header.
Send proactive email notifications to API consumers 6 months, 3 months, 1 month, and 1 week
before sunset. Provide a detailed migration guide and offer support during the transition.
Chapter 11: Documentation & Developer
Experience

11.1 Why Documentation Matters


Studies consistently show that documentation quality is the #1 factor developers consider when
choosing an API. Poor documentation leads to increased support costs, slower adoption, higher churn,
and frustrated developers.

Great API Docs Include


● Getting Started guide — First successful API call in under 5 minutes

● Authentication guide — How to obtain and use credentials

● Endpoint reference — Every endpoint with parameters, request/response examples

● Error reference — All possible errors with troubleshooting guides

● Code examples — In at least 4 popular languages

● Interactive playground — "Try it" functionality with sandbox environment

● SDKs & libraries — Official client libraries for popular languages

● Changelog — What changed in each version

● Rate limit documentation — Limits, headers, and how to handle 429s

Documentation Tools Comparison

Tool Type Pricing Key Features

Swagger UI Open Source Free Interactive docs from OpenAPI spec, try-it-out

Redoc Open Source Free / Pro Beautiful three-panel docs, responsive, fast

Stoplight Platform Freemium Visual API design + docs + mocking

ReadMe Platform Paid Developer hub, API metrics, personalized docs

Mintlify Platform Freemium Beautiful docs, AI-powered search, MDX


Chapter 12: Testing & Automation

12.1 The API Testing Pyramid

Level Scope Speed Quantity Tools

Unit Tests Individual functions, Very Fast Many (70%) Jest, pytest, JUnit, Go
validators, services testing

Integration API endpoints with real Medium Moderate Supertest, httpx,


Tests database (20%) MockMvc

Contract Tests Consumer-provider contract Fast Few per Pact, Spring Cloud
verification consumer Contract

E2E Tests Full flow across services Slow Few (10%) Newman, k6, custom
scripts

Performance Load, stress, spike testing Slow Few k6, Artillery, Locust,
Tests JMeter

Integration Test Example — [Link] (Jest + Supertest)


JAVASCRIPT

const request = require('supertest'); const app = require('../src/app');


const { connectDB, closeDB, clearDB } = require('./helpers/db');
describe('POST /api/v1/users', () => { beforeAll(() => connectDB());
afterEach(() => clearDB()); afterAll(() => closeDB()); it('should
create a user with valid data', async () => { const res = await
request(app) .post('/api/v1/users') .send({ name:
'Sasank', email: 'sasank@[Link]' }) .set('Authorization',
`Bearer ${testToken}`) .expect('Content-Type', /json/)
.expect(201); expect([Link]).toMatchObject({ name:
'Sasank', email: 'sasank@[Link]' });
expect([Link]).toHaveProperty('id');
expect([Link]).toMatch(/\/api\/v1\/users\/\w+/); });
it('should return 422 for invalid email', async () => { const res =
await request(app) .post('/api/v1/users') .send({
name: 'Test', email: 'not-an-email' }) .set('Authorization',
`Bearer ${testToken}`) .expect(422);
expect([Link]).toContainEqual( [Link]({
field: 'email' }) ); }); it('should return 409 for duplicate
email', async () => { // Create first user await
request(app).post('/api/v1/users') .send({ name: 'User1', email:
'dup@[Link]' }) .set('Authorization', `Bearer
${testToken}`); // Try to create duplicate const res = await
request(app) .post('/api/v1/users') .send({ name:
'User2', email: 'dup@[Link]' }) .set('Authorization',
`Bearer ${testToken}`) .expect(409);
expect([Link]).toContain('already exists'); }); });

Performance Test — k6
JAVASCRIPT

import http from 'k6/http'; import { check, sleep } from 'k6'; import { Rate,
Trend } from 'k6/metrics'; const errorRate = new Rate('errors'); const
apiDuration = new Trend('api_duration'); export const options = {
stages: [ { duration: '1m', target: 50 }, // Ramp up to 50 users
{ duration: '3m', target: 50 }, // Stay at 50 users { duration:
'1m', target: 200 }, // Spike to 200 users { duration: '2m', target:
200 }, // Stay at 200 users { duration: '1m', target: 0 }, //
Ramp down ], thresholds: { http_req_duration: ['p(95)<500'],
// 95% of requests under 500ms errors: ['rate<0.01'], //
Error rate under 1% }, }; export default function () { const res =
[Link]('[Link] { headers: {
Authorization: `Bearer ${__ENV.API_TOKEN}` }, }); check(res, {
'status is 200': (r) => [Link] === 200, 'response time < 500ms':
(r) => [Link] < 500, }); [Link]([Link] !==
200); [Link]([Link]); sleep(1); }

TIP:

Run performance tests against a staging environment that mirrors production (same database size,
same infrastructure). Testing against an empty database with a single instance gives misleading
results. Include realistic data volumes and concurrent users in your performance test scenarios.

Chapter 13: API Security

13.1 OWASP API Security Top 10 (2023)


# Vulnerability Description Mitigation

1 Broken Object Level User can access other users' Always verify the
Authorization (BOLA) objects by changing the ID in the authenticated user owns
URL the requested resource

2 Broken Authentication Weak auth mechanisms, no brute- Strong auth, rate limiting on
force protection, exposed tokens login, short-lived tokens

3 Broken Object API exposes object properties the Allowlist response fields,
Property Level Auth user shouldn't see/modify (mass validate input against
assignment) schema

4 Unrestricted Resource No limits on requests, file sizes, Rate limiting, pagination


Consumption batch operations, query limits, input size limits
complexity

5 Broken Function Level Regular user can access admin RBAC, deny-by-default,
Authorization (BFLA) endpoints check roles on every request

6 Unrestricted Access to Automated abuse of business logic Bot detection, CAPTCHA,


Sensitive Business (ticket scalping, content scraping) behavioral analysis
Flows

7 Server-Side Request API fetches user-provided URLs, Validate/allowlist URLs,


Forgery (SSRF) enabling access to internal deny private IP ranges
services

8 Security Default configs, verbose errors, Hardened configs, disable


Misconfiguration unnecessary features enabled debug, security headers

9 Improper Inventory Forgotten APIs, undocumented API inventory, automated


Management endpoints, old versions still discovery, version lifecycle
running management

10 Unsafe Consumption Blindly trusting data from third- Validate all external API
of APIs party APIs without validation responses, timeout, circuit
breaking

BOLA Prevention Example


JAVASCRIPT

// VULNERABLE — any authenticated user can access any order


[Link]('/api/v1/orders/:id', authenticate, async (req, res) => { const
order = await [Link]([Link]); [Link](order); // No
ownership check! }); // SECURE — verify the authenticated user owns the
resource [Link]('/api/v1/orders/:id', authenticate, async (req, res) => {
const order = await [Link]([Link]); if (!order) {
return [Link](404).json({ error: 'Order not found' }); } //
CRITICAL: Check ownership if ([Link]() !== [Link] &&
![Link]('admin')) { return [Link](403).json({
error: 'Access denied' }); } [Link](order); });
WARNING:

BOLA (Broken Object Level Authorization) is the #1 API vulnerability year after year. It's deceptively
simple: if your API has an endpoint like GET /orders/123, can user A access user B's order by
simply changing the ID? Every endpoint that returns user-specific data MUST verify ownership. This
check should be implemented at the service/middleware layer, not left to individual developers to
remember.

13.2 Security Headers


JAVASCRIPT — Setting Security Headers with Helmet

const helmet = require('helmet'); [Link](helmet({


contentSecurityPolicy: { directives: { defaultSrc:
["'self'"], scriptSrc: ["'self'"], } }, hsts: {
maxAge: 31536000, includeSubDomains: true, preload: true },
referrerPolicy: { policy: 'strict-origin-when-cross-origin' } })); //
Additional custom security headers [Link]((req, res, next) => {
[Link]('X-Content-Type-Options', 'nosniff'); [Link]('X-Frame-Options',
'DENY'); [Link]('Permissions-Policy', 'camera=(), microphone=(),
geolocation=()'); next(); });

Chapter 14: API Gateways & Service Mesh

14.1 What Is an API Gateway?


An API Gateway is a server that sits between clients and backend services, acting as a reverse proxy to
route requests, enforce policies, and aggregate results. It serves as the single entry point for all API
traffic.
Figure 14.1 — API gateway as a single entry point for microservices

API Gateway Functions


● Request routing — Route requests to appropriate backend services

● Authentication — Verify tokens, API keys at the edge

● Rate limiting — Throttle requests per consumer

● Load balancing — Distribute traffic across service instances

● Caching — Cache responses to reduce backend load

● Request/Response transformation — Modify headers, body, protocol translation

● Logging & monitoring — Centralized access logging and metrics

● Circuit breaking — Prevent cascade failures

API Gateway Comparison

Gateway Type Protocol Key Strength Pricing

Kong Open Source / HTTP, gRPC, Plugin ecosystem, Lua Free /


Enterprise WebSocket extensibility Enterprise

AWS API Managed Cloud HTTP, Serverless integration, Pay-per-


Gateway WebSocket Lambda request

Azure API Managed Cloud HTTP, Enterprise features, policy Tiered


Management WebSocket engine
Gateway Type Protocol Key Strength Pricing

Apigee Managed Cloud HTTP Analytics, monetization, Enterprise


(Google) developer portal

Tyk Open Source / HTTP, gRPC, Go-based, GraphQL-native Free / Paid


Cloud GraphQL

NGINX Open Source / HTTP, gRPC, Performance, battle- Free / Plus


Plus TCP/UDP tested

14.2 Service Mesh


A service mesh provides infrastructure-layer networking for service-to-service communication. It
handles concerns like traffic management, security (mTLS), and observability without requiring changes
to application code.

Feature API Gateway Service Mesh

Position Edge (client → services) Internal (service → service)

Focus North-south traffic East-west traffic

Auth Client authentication Service-to-service mTLS

Examples Kong, AWS API GW, Apigee Istio, Linkerd, Consul Connect

Chapter 15: Monitoring & Observability

15.1 The Three Pillars of Observability


Figure 15.1 — The three pillars of system observability: Logs, Metrics, and Traces

Pillar What It Captures Best For Tools

Metrics Numeric measurements over Dashboards, alerting, trends, Prometheus,


time (counters, gauges, capacity planning Datadog,
histograms) CloudWatch

Logs Timestamped text records of Debugging, audit trail, error ELK Stack, Loki,
discrete events investigation Splunk

Traces End-to-end journey of a request Latency analysis, dependency Jaeger, Zipkin,


across services mapping, root cause analysis Honeycomb

15.2 Key API Metrics

Metric What It Measures Target Example

Latency (p50) Median response time < 100ms


Metric What It Measures Target Example

Latency (p95) 95th percentile response time < 300ms

Latency (p99) 99th percentile response time < 1000ms

Error Rate Percentage of 5xx responses < 0.1%

Throughput (RPS) Requests per second Varies by service

Availability Uptime percentage 99.9% (three nines)

Saturation CPU, memory, connection pool utilization < 70%

SLA/SLO/SLI Definitions

Term Definition Example

SLI (Service Level A quantitative metric measuring service p95 latency, error rate,
Indicator) performance availability

SLO (Service Level A target value for an SLI that the team "p95 latency < 300ms over 30-
Objective) commits to day window"

SLA (Service Level A contractual commitment with "99.9% uptime or 10% credit
Agreement) consequences for SLO breach refund"

Structured Logging Example — [Link]


JAVASCRIPT

const pino = require('pino'); const logger = pino({ level:


[Link].LOG_LEVEL || 'info', formatters: { level: (label) =>
({ level: label }), }, timestamp: () => `,"timestamp":"${new
Date().toISOString()}"`, }); // Request logging middleware [Link]((req,
res, next) => { const requestId = [Link]['x-request-id'] ||
[Link](); [Link] = [Link]({ requestId, method:
[Link], path: [Link] }); const start = [Link]();
[Link]('finish', () => { [Link]({ statusCode:
[Link], duration: [Link]() - start,
userAgent: [Link]['user-agent'], ip: [Link] },
'Request completed'); }); next(); });

✅BEST PRACTICE:
Always generate a unique X-Request-ID (correlation ID) for each incoming request and propagate
it through all downstream service calls. This allows you to trace a single user request across dozens
of microservices and log entries, dramatically reducing debugging time.

Chapter 16: Performance & Caching

16.1 Caching Strategies

Layer Technology TTL Best For

Client-side Browser cache (Cache-Control Minutes to hours Static responses, user-specific


headers) data

CDN CloudFront, Cloudflare, Akamai Seconds to hours Public data, geographic


distribution

API Kong, NGINX, AWS API GW Seconds to Frequently-requested


Gateway minutes endpoints

Application Redis, Memcached Seconds to hours Computed results, DB query


results

Database Query cache, materialized Varies Expensive queries,


views aggregations

Redis Caching Pattern — Cache-Aside


JAVASCRIPT

const Redis = require('ioredis'); const redis = new Redis(); async function


getUserWithCache(userId) { const cacheKey = `user:${userId}`; //
1. Try cache first const cached = await [Link](cacheKey); if
(cached) { return [Link](cached); // Cache HIT } //
2. Cache MISS — fetch from database const user = await
[Link](userId); if (user) { // 3. Store in cache
with TTL await [Link](cacheKey, [Link](user), 'EX', 3600);
// 1 hour } return user; } // Cache invalidation on update
async function updateUser(userId, updates) { const user = await
[Link](userId, updates); // Invalidate cache
await [Link](`user:${userId}`); return user; }
16.2 HTTP Caching Headers
JAVASCRIPT

// Public data — cacheable by CDN and browser [Link]('/api/v1/products',


(req, res) => { [Link]('Cache-Control', 'public, max-age=300, s-
maxage=600'); [Link]('Vary', 'Accept-Encoding'); [Link](products);
}); // Private data — cacheable by browser only [Link]('/api/v1/users/me',
authenticate, (req, res) => { [Link]('Cache-Control', 'private, max-
age=60'); [Link]([Link]); }); // Never cache — sensitive/dynamic
data [Link]('/api/v1/orders/pending', authenticate, (req, res) => {
[Link]('Cache-Control', 'no-store'); [Link](pendingOrders); });

TIP:

Use stale-while-revalidate for API responses that can tolerate slightly stale data. The
directive Cache-Control: public, max-age=60, stale-while-revalidate=300 means:
serve from cache for 60 seconds, then for the next 300 seconds serve stale data while revalidating in
the background. The user never waits for the slow backend.

Chapter 17: Building APIs — Projects

This chapter contains four complete, production-quality API projects. Each builds on the concepts from
previous chapters and introduces new skills.

Project 1: RESTful Task Management API


([Link]/Express)
Architecture Overview

Component Technology

Runtime [Link] 20 + Express 4

Database MongoDB + Mongoose ODM


Component Technology

Authentication JWT (RS256) + Refresh Tokens

Validation Joi / Zod

Testing Jest + Supertest

Documentation OpenAPI 3.1 + Swagger UI

Containerization Docker + Docker Compose

Features
● User registration and login with JWT + refresh tokens

● Role-based access control (admin, manager, user)

● Full CRUD on tasks with categories and tags

● Pagination (cursor-based), filtering, sorting, full-text search

● File upload for task attachments (S3-compatible)

● Rate limiting (token bucket with Redis)

● Structured JSON logging with correlation IDs

● Health check endpoint

● Comprehensive test suite (80%+ coverage)

Database Schema
JAVASCRIPT — Mongoose Models

// models/[Link] const userSchema = new [Link]({ name: { type:


String, required: true, trim: true, maxlength: 100 }, email: { type:
String, required: true, unique: true, lowercase: true }, password: {
type: String, required: true, minlength: 8 }, role: { type: String, enum:
['admin', 'manager', 'user'], default: 'user' }, refreshTokenVersion: {
type: Number, default: 0 }, isActive: { type: Boolean, default: true } },
{ timestamps: true }); // models/[Link] const taskSchema = new
[Link]({ title: { type: String, required: true, maxlength: 200
}, description: { type: String, maxlength: 5000 }, status: {
type: String, enum: ['todo', 'in_progress', 'review', 'done',
'cancelled'], default: 'todo' }, priority: { type: String,
enum: ['low', 'medium', 'high', 'urgent'], default: 'medium' }, dueDate:
Date, tags: [{ type: String, lowercase: true, trim: true }],
category: { type: [Link], ref: 'Category' },
assignee: { type: [Link], ref: 'User' },
createdBy: { type: [Link], ref: 'User', required:
true }, attachments: [{ filename: String, url: String,
mimeType: String, size: Number, uploadedAt: { type: Date,
default: [Link] } }] }, { timestamps: true }); [Link]({
title: 'text', description: 'text' }); [Link]({ createdBy: 1,
status: 1 }); [Link]({ dueDate: 1 });

Docker Compose
YAML — [Link]

version: '3.8' services: api: build: . ports: - "3000:3000"


environment: - NODE_ENV=production -
MONGODB_URI=mongodb://mongo:27017/taskapi -
REDIS_URL=redis://redis:6379 -
JWT_PRIVATE_KEY_PATH=/run/secrets/jwt_private -
JWT_PUBLIC_KEY_PATH=/run/secrets/jwt_public depends_on: - mongo
- redis mongo: image: mongo:7 volumes: - mongo_data:/data/db
ports: - "27017:27017" redis: image: redis:7-alpine ports:
- "6379:6379" volumes: mongo_data:

Project 2: E-Commerce GraphQL API (Python/FastAPI)


Architecture Overview

Component Technology

Runtime Python 3.12 + FastAPI

GraphQL Strawberry GraphQL

Database PostgreSQL + SQLAlchemy

Cache Redis

Testing pytest + httpx

GraphQL Schema
PYTHON

import strawberry from typing import Optional from datetime import datetime
@[Link] class Product: id: int name: str description:
Optional[str] price: float stock: int category: 'Category'
images: list[str] created_at: datetime @[Link] class CartItem:
product: Product quantity: int subtotal: float @[Link]
class Order: id: int items: list['OrderItem'] total_amount: float
status: str created_at: datetime @[Link] class Query:
@[Link] async def products( self, category_id:
Optional[int] = None, search: Optional[str] = None,
min_price: Optional[float] = None, max_price: Optional[float] = None,
limit: int = 25, offset: int = 0, ) -> list[Product]:
"""Search and filter products.""" return await [Link](
category_id=category_id, search=search, min_price=min_price,
max_price=max_price, limit=limit, offset=offset )
@[Link] class Mutation: @[Link] async def
add_to_cart(self, product_id: int, quantity: int = 1) -> CartItem:
"""Add a product to the shopping cart.""" return await
CartService.add_item(product_id, quantity) @[Link]
async def place_order(self, payment_method_id: str) -> Order:
"""Convert cart to an order and process payment.""" return await
OrderService.create_from_cart(payment_method_id)

Project 3: Real-Time Chat API (Go/Gin + gRPC)


Architecture Overview

Component Technology

Runtime Go 1.22

HTTP API Gin framework

Real-time gRPC bidirectional streaming

Pub/Sub Redis Streams

Database PostgreSQL + Redis

Proto Definition
PROTOBUF

syntax = "proto3"; package chat; service ChatService { // Join a room


and receive messages in real-time rpc JoinRoom (stream ClientMessage)
returns (stream ServerMessage); // Get room history rpc
GetHistory (GetHistoryRequest) returns (GetHistoryResponse); } message
ClientMessage { oneof payload { JoinRequest join = 1;
TextMessage text = 2; TypingIndicator typing = 3; } } message
ServerMessage { oneof payload { TextMessage message = 1;
UserJoined user_joined = 2; UserLeft user_left = 3;
TypingIndicator typing = 4; } } message TextMessage { string id = 1;
string room_id = 2; string user_id = 3; string content = 4; int64
timestamp = 5; }

Project 4: Microservices API Platform (Java/Spring


Boot)
Architecture
Service Port Database Purpose

API Gateway 8080 — Routing, auth, rate limiting

User Service 8081 PostgreSQL User management, authentication

Product Service 8082 MongoDB Product catalog, search

Order Service 8083 PostgreSQL Order management, saga orchestration

Config Server 8888 Git Centralized configuration

Eureka Server 8761 — Service discovery

Spring Cloud Gateway Configuration


YAML — [Link]

spring: cloud: gateway: routes: - id: user-service


uri: lb://user-service predicates: -
Path=/api/v1/users/**, /api/v1/auth/** filters: -
RewritePath=/api/v1/(?<segment>.*), /${segment} - name:
CircuitBreaker args: name: userServiceCB
fallbackUri: forward:/fallback/users - name: RequestRateLimiter
args: [Link]: 10
[Link]: 20 - id: product-
service uri: lb://product-service predicates:
- Path=/api/v1/products/** filters: -
RewritePath=/api/v1/(?<segment>.*), /${segment} - id: order-service
uri: lb://order-service predicates: -
Path=/api/v1/orders/** filters: -
RewritePath=/api/v1/(?<segment>.*), /${segment} - name:
CircuitBreaker args: name: orderServiceCB

TIP:

When building microservices, start with a monolith and extract services as needed. The "monolith
first" approach (advocated by Martin Fowler and Sam Newman) lets you discover the right service
boundaries through experience rather than guessing upfront. Premature decomposition into
microservices is one of the most expensive architectural mistakes.

Chapter 18: Advanced Topics


18.1 Event-Driven Architecture
Event Sourcing
Instead of storing the current state, event sourcing stores a sequence of state-changing events. The
current state is derived by replaying all events. This provides a complete audit trail and enables
temporal queries.

JAVASCRIPT — Event Sourcing Example

// Events (immutable facts) const events = [ { type: 'OrderCreated',


data: { orderId: '123', items: [...], total: 99.99 } }, { type:
'PaymentReceived', data: { orderId: '123', amount: 99.99 } }, { type:
'OrderShipped', data: { orderId: '123', trackingNumber: 'UPS123' } }, {
type: 'OrderDelivered', data: { orderId: '123', deliveredAt: '2026-04-20' }
}, ]; // Derive current state by replaying events function
deriveOrderState(events) { return [Link]((state, event) => {
switch ([Link]) { case 'OrderCreated': return
{ ...state, ...[Link], status: 'created' }; case
'PaymentReceived': return { ...state, status: 'paid', paidAt:
[Link] }; case 'OrderShipped': return {
...state, status: 'shipped', trackingNumber: [Link] };
case 'OrderDelivered': return { ...state, status: 'delivered'
}; default: return state; } }, {}); }

18.2 Serverless APIs

Platform Runtime Cold Start Max Duration Pricing

AWS Lambda [Link], Python, Java, 100ms–2s 15 min $0.20 per 1M


Go, .NET, Ruby requests + compute
time

Azure [Link], Python, Java, 200ms–3s 10 min $0.20 per 1M


Functions C#, PowerShell (consumption) requests + compute
time

Cloudflare JavaScript/WASM <1ms (V8 30s (free) / 15 min $0.50 per 1M


Workers isolates) (paid) requests

Google Cloud [Link], Python, Java, 100ms–2s 9 min (1st gen) / $0.40 per 1M
Functions Go, .NET, Ruby, PHP 60 min (2nd gen) requests + compute
time

AWS Lambda API Example


JAVASCRIPT

// [Link] — AWS Lambda function for API Gateway export const handler =
async (event) => { const { httpMethod, pathParameters, body,
queryStringParameters } = event; try { switch (httpMethod) {
case 'GET': if (pathParameters?.id) {
const user = await [Link]([Link]);
return response(200, user); } const users =
await [Link](queryStringParameters); return
response(200, users); case 'POST': const newUser
= await [Link]([Link](body)); return
response(201, newUser); default: return
response(405, { error: 'Method not allowed' }); } } catch (error)
{ [Link]('Error:', error); return response(500, {
error: 'Internal server error' }); } }; function response(statusCode,
body) { return { statusCode, headers: {
'Content-Type': 'application/json', 'Access-Control-Allow-
Origin': '*' }, body: [Link](body) }; }

18.3 AI/ML APIs


Serving machine learning models as APIs is a growing pattern. Key considerations include streaming
inference for LLMs, model versioning, A/B testing between model versions, and managing GPU
resources.

✅BEST PRACTICE:

When serving ML models as APIs, use streaming responses (Server-Sent Events) for large language
models to provide progressive output. Implement model versioning so you can run A/B tests
between model versions. Always set timeouts for inference — GPU workloads can hang, and you
don't want to block your API server.

Chapter 19: API Business Models

19.1 API Monetization Models

Model Description Examples Revenue Potential

Freemium Free tier with limited usage; paid Google Maps, Medium (requires
tiers for more OpenWeatherMap volume)
Model Description Examples Revenue Potential

Pay-per-call Charge per API request (metered AWS services, Twilio High (scales with
billing) usage)

Subscription Fixed monthly fee for a tier of Stripe, SendGrid High (predictable
access revenue)

Revenue Take a percentage of transactions Stripe (2.9% + 30¢), Very High


Sharing processed PayPal

Indirect / API is free; monetized through Facebook Graph API, Indirect (platform
Free ecosystem growth Twitter API value)

Marketplace Third-party APIs sold through RapidAPI, AWS Commission-based


marketplace Marketplace

19.2 Case Study: Stripe's API Business Model


Stripe is widely regarded as having the best API in the industry. Their success is built on:

● Developer-first: Exceptional documentation, interactive tutorials, clear error messages

● Revenue sharing model: 2.9% + 30¢ per transaction — aligned incentives (they earn when you
earn)

● API design: Consistent naming, idempotency keys, comprehensive webhooks, expandable


responses

● SDKs: Official libraries in 7+ languages, actively maintained

● Versioning: Dated API versions (e.g., 2024-04-10), backward compatibility for years

Chapter 20: Case Studies & System Design

20.1 System Design Interview Framework


83. Clarify Requirements (5 min): Functional requirements, non-functional requirements, scale
estimates
84. High-Level Design (10 min): Core components, data flow, API endpoints

85. Detailed Design (15 min): Database schema, API contracts, algorithms

86. Scalability & Trade-offs (10 min): Bottlenecks, scaling strategies, trade-offs

20.2 Case Study: Design Twitter/X API


Requirements
● Functional: Post tweets, follow users, timeline (home + user), search, like/retweet, notifications

● Non-functional: 500M daily active users, 600K tweets/second (read), timeline in <200ms

Core API Endpoints


REST API DESIGN

# Tweets POST /api/v1/tweets # Create tweet GET


/api/v1/tweets/:id # Get tweet DELETE /api/v1/tweets/:id
# Delete tweet POST /api/v1/tweets/:id/like # Like tweet DELETE
/api/v1/tweets/:id/like # Unlike tweet POST
/api/v1/tweets/:id/retweet # Retweet # Timeline GET
/api/v1/timeline/home # Home timeline (followed users) GET
/api/v1/timeline/user/:userId # User's tweets # Users POST
/api/v1/users/:id/follow # Follow user DELETE
/api/v1/users/:id/follow # Unfollow user GET
/api/v1/users/:id/followers # Get followers GET
/api/v1/users/:id/following # Get following # Search GET
/api/v1/search?q=term&type=tweets # Search tweets, users, hashtags

Timeline Generation Strategy

Approach How It Works Pros Cons

Fan-out on When user posts, immediately Fast reads Slow writes for celebrity
Write push tweet to all followers' (<50ms), simple users (millions of followers),
timeline caches read path storage overhead

Fan-out on When user opens timeline, pull Simple writes, Slow reads (must query many
Read tweets from all followed users no storage users), high compute
and merge overhead

Hybrid Fan-out on write for most Balances Complex, requires user


(Twitter's users; fan-out on read for read/write classification
approach) celebrities (>5K followers) performance
20.3 Case Study: Design Stripe Payment API
Key Design Decisions
● Idempotency: Every payment request requires an Idempotency-Key header. If a network
failure causes a retry, the same payment is not processed twice.

● Webhooks: Payment events (succeeded, failed, refunded) are delivered via webhooks with
HMAC signature verification.

● PCI Compliance: Card numbers never touch the merchant's server. [Link]/Elements tokenize
card data in the browser, and the server only receives a token.

● Two-phase payment: Authorize first, then capture later (enables holds for hotels, car rentals).

20.4 Case Study: Design Uber/Lyft API


Core Challenges
● Real-time location tracking: WebSocket or gRPC streaming for driver/rider position updates

● Matching algorithm: Match riders with nearby available drivers based on ETA, not distance

● Surge pricing: Dynamic pricing API based on supply-demand ratio in geographic cells

● Geospatial queries: Use geohashing (S2 cells) for efficient nearby driver lookups

20.5 Case Study: Design Netflix API


API Architecture
● Zuul Gateway: Netflix's custom API gateway handling 50B+ requests/day

● Backend for Frontend (BFF): Separate API layers for web, mobile, TV (each device has different
capabilities)

● Personalization API: ML-powered recommendations served through a real-time inference API

● Streaming API: Adaptive bitrate streaming with manifest files (DASH/HLS) served through CDN
TIP:

In system design interviews, always start with a clear statement of the scale: "We need to handle
10K requests per second for timeline reads." Then work backward from the performance
requirements to justify your architecture decisions. Interviewers want to see that you can reason
about trade-offs at scale.

Appendix A: 100+ Corporate Interview


Questions

A.1 API Fundamentals (20 Questions)


Q1. What is an API, and why are APIs important in modern software development?

Model Answer: An API (Application Programming Interface) is a set of defined rules and protocols that
allows different software applications to communicate with each other. APIs are important because they
enable modularity, reusability, and interoperability. They allow teams to build systems independently
(frontend/backend separation), enable third-party integrations (Stripe for payments, Twilio for
messaging), and power the modern cloud-native architecture where distributed services communicate
through well-defined interfaces.

What Interviewers Look For:

Clear definition, real-world examples, understanding of why APIs matter for business (not just
technical). Mention of decoupling, scalability, and ecosystem value.

Q2. Explain the difference between REST and SOAP.


Model Answer: REST is an architectural style that uses HTTP methods and JSON for lightweight,
stateless communication. SOAP is a protocol with strict standards using XML, WSDL, and WS-*
specifications. REST is simpler, faster, and more widely adopted for web/mobile APIs. SOAP is preferred
in enterprise environments requiring formal contracts, WS-Security, and reliable messaging (banking,
healthcare). REST uses HTTP status codes for errors; SOAP uses XML fault elements. REST is cacheable by
default; SOAP is not.

What Interviewers Look For:

Not just listing differences but explaining when you'd choose each. Understanding that SOAP is still
relevant in specific domains.

Q3. What makes an API "RESTful"?

Model Answer: A RESTful API follows the six constraints defined by Roy Fielding: client-server
separation, statelessness (no session state on server), cacheability (responses define their cache
behavior), uniform interface (resources identified by URIs, manipulated through representations),
layered system (intermediaries like CDNs/load balancers), and optional code-on-demand. Most APIs
claim to be RESTful but only implement Level 2 of the Richardson Maturity Model (proper HTTP
methods with resources). True REST (Level 3) includes HATEOAS.

Q4. What is the difference between PUT and PATCH?

Model Answer: PUT replaces the entire resource with the provided representation. All fields must be
included; omitted fields are set to null/default. PATCH applies a partial update — only the included fields
are modified. PUT is idempotent by definition. PATCH can be idempotent (JSON Merge Patch) or non-
idempotent (if using relative operations like "increment count by 1"). Use PUT when the client has the
complete resource; use PATCH for partial updates.

Q5. Explain HTTP status code categories and give two examples from each.

Model Answer: 1xx Informational (100 Continue, 101 Switching Protocols), 2xx Success (200 OK, 201
Created), 3xx Redirection (301 Moved Permanently, 304 Not Modified), 4xx Client Errors (400 Bad
Request, 404 Not Found), 5xx Server Errors (500 Internal Server Error, 503 Service Unavailable). The
status code is the first thing automated systems check — load balancers, monitoring, and client libraries
all depend on correct status codes.

Q6. What is idempotency and why does it matter for APIs?

Q7. How would you design pagination for an API that serves millions of records?

Q8. What is content negotiation in REST APIs?

Q9. Explain the concept of API versioning. What strategies exist?

Q10. What is HATEOAS and why do many APIs choose not to implement it?

Q11. How do WebSockets differ from HTTP? When would you use each?

Q12. What is the difference between synchronous and asynchronous APIs?

Q13. Explain the difference between an API and an SDK.

Q14. What are webhooks and how do they differ from polling?

Q15. What is an API gateway and what problems does it solve?

Q16. Explain the difference between API keys, OAuth tokens, and JWTs.

Q17. What is rate limiting and why is it important?

Q18. How do you handle errors in API design?

Q19. What is the difference between 401 and 403 status codes?

Q20. What tools do you use for API development and testing?

A.2 API Design & Architecture (20 Questions)


Q21. How would you design a REST API for a social media platform?

Model Answer: I'd start by identifying the core resources: Users, Posts, Comments, Likes, Follows,
Notifications. Each resource gets standard CRUD endpoints. For the timeline, I'd use a dedicated
endpoint (GET /timeline/home) with cursor-based pagination. Relationships are expressed through sub-
resources (GET /users/:id/posts). I'd use query parameters for filtering and sorting. Authentication
would be JWT-based with OAuth 2.0 for third-party access. Real-time features (notifications, typing
indicators) would use WebSocket connections. Rate limiting per user and per API key.

What Interviewers Look For:

Systematic approach to resource identification, proper REST conventions, consideration of


performance (pagination), security (auth), and real-time requirements.

Q22. How do you handle breaking changes in an API?

Q23. Explain the API-first design approach.

Q24. How would you design an API for a multi-tenant SaaS application?

Q25. What is the Backend for Frontend (BFF) pattern?

Q26. How do you handle file uploads in a REST API?

Q27. Explain the difference between GraphQL and REST. When would you choose each?

Q28. What is gRPC and when is it preferred over REST?

Q29. How would you design an API for a payment processing system?

Q30. What is the Saga pattern in microservices?

Q31. How do you handle partial failures in distributed APIs?

Q32. Explain the circuit breaker pattern.

Q33. How do you design APIs for backward compatibility?

Q34. What is an OpenAPI specification and how do you use it?

Q35. How do you handle long-running operations in an API?

Q36. Explain the event-driven architecture pattern for APIs.

Q37. What are the trade-offs between monolith and microservice APIs?
Q38. How do you design an API that needs to support both mobile and web clients?

Q39. What is API composition and when do you need it?

Q40. How do you handle cross-cutting concerns in a microservices API?

A.3 Security & Authentication (15 Questions)


Q41. Explain OAuth 2.0 Authorization Code flow with PKCE.

Model Answer: The flow proceeds as follows: (1) Client generates a random code_verifier and derives a
code_challenge using SHA-256. (2) Client redirects user to the authorization server with the
code_challenge. (3) User authenticates and consents. (4) Authorization server redirects back with an
authorization code. (5) Client exchanges the code + code_verifier for tokens. (6) Authorization server
verifies the code_verifier matches the original code_challenge. PKCE prevents authorization code
interception attacks — even if an attacker captures the code, they cannot exchange it without the
code_verifier.

What Interviewers Look For:

Complete understanding of the flow, why PKCE exists (security), and awareness that it's now
required for all clients (not just public clients) per OAuth 2.1.

Q42. How do you securely store and transmit API keys?

Q43. Explain JWT structure and security considerations.

Q44. What is the OWASP API Security Top 10?

Q45. How do you prevent BOLA (Broken Object Level Authorization)?

Q46. Explain mutual TLS (mTLS) and when you'd use it.

Q47. How do you handle CORS in API development?

Q48. What is token revocation and how do you implement it with JWTs?
Q49. How do you prevent SQL injection in APIs?

Q50. What is the difference between RBAC and ABAC?

Q51. How do you implement API rate limiting to prevent DDoS?

Q52. What security headers should every API response include?

Q53. How do you handle sensitive data (PII) in API responses?

Q54. What is SSRF and how do you prevent it in APIs?

Q55. How do you implement API key rotation without downtime?

A.4 Performance & Scalability (15 Questions)


Q56. How would you optimize a slow API endpoint?

Q57. Explain caching strategies for APIs.

Q58. How does HTTP/2 improve API performance?

Q59. What is connection pooling and why does it matter?

Q60. How do you handle the N+1 query problem?

Q61. Explain cursor-based pagination vs offset-based.

Q62. How do you implement cache invalidation?

Q63. What is the difference between horizontal and vertical scaling for APIs?

Q64. How do you handle thundering herd problems?

Q65. What load testing tools and strategies do you use?

Q66. How would you design an API for global distribution?

Q67. Explain database indexing strategies for API performance.

Q68. What is ETags and how do they improve API performance?


Q69. How do you handle large response payloads?

Q70. Explain async processing patterns for APIs (queues, workers).

A.5 System Design (20 Questions)


Q71. Design a URL shortening service API (like [Link]).

Q72. Design a real-time notification system API.

Q73. Design a file storage and sharing API (like Dropbox).

Q74. Design a chat messaging API (like Slack).

Q75. Design an e-commerce product search API.

Q76. Design a ride-sharing API (like Uber).

Q77. Design a social media feed/timeline API (like Twitter).

Q78. Design a video streaming API (like Netflix).

Q79. Design a payment processing API (like Stripe).

Q80. Design a booking/reservation API (like Airbnb).

Q81–Q90. Additional system design scenarios (collaborative editing, IoT telemetry, API analytics
platform, food delivery, rate limiting service, content moderation, recommendation engine, multi-region
API deployment, API marketplace, event ticketing).

A.6 Behavioral & Scenario-Based (10 Questions)


Q91. You discover that your API has been returning incorrect data for 2 hours. What do you do?

Model Answer: First, assess the impact: which endpoints, how many users affected, what data was
incorrect. Communicate immediately with stakeholders — post in the incident channel, notify affected
teams. Fix the root cause as the priority — deploy a hotfix or rollback if possible. Once fixed, assess the
data damage: do we need to reprocess or notify affected users? Write a post-mortem covering timeline,
root cause, impact, what we learned, and action items to prevent recurrence. Improve
monitoring/alerting to catch this faster next time.
What Interviewers Look For:

Structured incident response thinking, emphasis on communication, and learning from failures
(post-mortem culture).

Q92. A partner complains your API is too slow. How do you investigate?

Q93. Your team wants to rewrite the API from scratch. How do you evaluate this decision?

Q94. How do you handle a situation where two teams disagree on API design?

Q95. Describe a time you improved API performance significantly.

Q96. How would you migrate from a monolith to microservices APIs?

Q97. A critical API dependency is experiencing an outage. What do you do?

Q98. How do you ensure API quality when shipping quickly?

Q99. How do you handle a security vulnerability discovered in production?

Q100. Describe your approach to API documentation.

Appendix B:Glossary of API Terms

Term Definition

ABAC Attribute-Based Access Control — authorization based on attributes of the user,


resource, and environment.

API Gateway A server that acts as the single entry point for API requests, handling routing,
auth, rate limiting, and monitoring.

API Key A unique string identifier used to authenticate and identify an API consumer.
Term Definition

AsyncAPI A specification for documenting event-driven and asynchronous APIs,


analogous to OpenAPI for REST.

Authentication The process of verifying the identity of a client or user ("Who are you?").
(AuthN)

Authorization The process of determining what actions an authenticated user is allowed to


(AuthZ) perform ("What can you do?").

Base URL The root URL of an API upon which all endpoint paths are built (e.g.,
[Link]

Bearer Token An access token sent in the Authorization header to authenticate API requests.

BFF Backend for Frontend — a dedicated API layer tailored for a specific client type
(web, mobile, TV).

BOLA Broken Object Level Authorization — a vulnerability where users can access
other users' resources by manipulating IDs.

Cache-Control An HTTP header that specifies caching directives for requests and responses.

Callback URL A URL that a server sends data to when an event occurs (used by webhooks and
OAuth).

CDN Content Delivery Network — a geographically distributed network of servers


that caches and serves content closer to users.

Circuit Breaker A resilience pattern that stops calling a failing service after a threshold, allowing
it time to recover.

Client Any software that makes requests to an API (browser, mobile app, another
server).

Consumer A developer, application, or organization that uses an API.

Content The mechanism by which client and server agree on the data format (via Accept
Negotiation and Content-Type headers).

Contract Testing Testing that verifies the API implementation matches the API
specification/contract.

CORS Cross-Origin Resource Sharing — a browser security mechanism that controls


which domains can access an API.

CRUD Create, Read, Update, Delete — the four basic operations on data, mapped to
POST, GET, PUT/PATCH, DELETE.

CQRS Command Query Responsibility Segregation — separating read and write


models for performance and scalability.

Cursor An opaque token used in cursor-based pagination to identify a position in a


dataset.
Term Definition

DataLoader A utility for batching and caching data lookups, commonly used in GraphQL to
solve the N+1 problem.

Deprecation The process of marking an API version or feature as outdated, with a planned
removal date.

DNS Domain Name System — resolves human-readable domain names to IP


addresses.

DPoP Demonstrating Proof of Possession — a mechanism to bind access tokens to a


specific client key pair.

Endpoint A specific URL path where an API resource can be accessed (e.g.,
/api/v1/users).

Error Budget The allowed amount of unreliability based on SLO targets (e.g., if SLO is 99.9%,
error budget is 0.1%).

ETag Entity Tag — an HTTP header containing a version identifier for a resource,
used for caching and concurrency control.

Event Sourcing A pattern where state changes are stored as a sequence of immutable events
rather than overwriting current state.

Fan-out The process of distributing a message or data to multiple recipients or services.

GraphQL A query language for APIs that lets clients request exactly the data they need
through a strongly typed schema.

gRPC Google Remote Procedure Call — a high-performance RPC framework using


Protocol Buffers and HTTP/2.

HAL Hypertext Application Language — a JSON format for representing hypermedia


links in API responses.

HATEOAS Hypermedia as the Engine of Application State — REST principle where


responses include links to related resources.

Health Check An endpoint (typically /health) that reports the operational status of a
service.

HMAC Hash-based Message Authentication Code — used to verify message integrity


and authenticity.

HTTP Hypertext Transfer Protocol — the application-layer protocol used for web and
API communication.

Idempotency The property of an operation where performing it multiple times produces the
same result as performing it once.

Idempotency Key A unique client-generated key sent with non-idempotent requests to enable
safe retries.
Term Definition

Introspection In GraphQL, the ability to query the schema itself to discover available types,
fields, and operations.

JSON JavaScript Object Notation — a lightweight data-interchange format widely


used in API payloads.

JSON Schema A specification for defining the structure and validation rules of JSON data.

JWT JSON Web Token — a compact, URL-safe token format containing signed claims
for authentication.

Latency The time elapsed between sending a request and receiving a response, often
measured at p50, p95, p99.

Load Balancer A component that distributes incoming traffic across multiple server instances.

Middleware Software that intercepts and processes requests/responses in a pipeline (auth,


logging, validation).

Mutation In GraphQL, an operation that modifies server-side data (analogous to


POST/PUT/DELETE in REST).

mTLS Mutual TLS — both client and server present certificates to authenticate each
other.

N+1 Problem A performance issue where N additional database queries are made for N items
in a collection.

OAuth 2.0 An authorization framework that enables third-party applications to access


resources on behalf of a user.

OIDC OpenID Connect — an identity layer on top of OAuth 2.0 that provides user
authentication.

OpenAPI A specification (formerly Swagger) for describing REST API contracts in YAML or
JSON format.

OpenTelemetry An open-source observability framework for generating, collecting, and


exporting telemetry data.

Pagination Dividing a large dataset into smaller pages to reduce response size and improve
performance.

Payload The data sent in the body of an HTTP request or response.

PKCE Proof Key for Code Exchange — an OAuth 2.0 extension that prevents
authorization code interception attacks.

Preflight Request An HTTP OPTIONS request sent by the browser before a cross-origin request to
check CORS permissions.

Protocol Buffers Google's binary serialization format used by gRPC — more compact and faster
than JSON.
Term Definition

Provider The server-side system that hosts and serves the API.

Query In GraphQL, an operation that reads data without modifying it (analogous to


GET in REST).

Rate Limiting Restricting the number of API requests a client can make within a time window.

RBAC Role-Based Access Control — authorization based on predefined roles assigned


to users.

Resolver In GraphQL, a function that fetches the data for a specific field in the schema.

Resource An entity or object that an API manages, identified by a URI (e.g., user, product,
order).

REST Representational State Transfer — an architectural style for distributed systems


using HTTP.

RFC Request for Comments — documents published by the IETF defining internet
standards and protocols.

Saga Pattern A pattern for managing distributed transactions across microservices using a
sequence of local transactions.

Schema A formal definition of data structure, types, and validation rules for an API.

SDK Software Development Kit — pre-built libraries that wrap API calls in a
language-specific interface.

Serialization The process of converting data structures into a transmittable format (JSON,
XML, Protobuf).

Service Mesh Infrastructure layer handling service-to-service communication (mTLS, traffic


management, observability).

SLA Service Level Agreement — a contractual commitment for service performance


with consequences for breach.

SLI Service Level Indicator — a quantitative metric measuring service performance


(latency, error rate).

SLO Service Level Objective — a target value for an SLI that the team commits to
meeting.

SOAP Simple Object Access Protocol — an XML-based messaging protocol with formal
WS-* standards.

SSE Server-Sent Events — a standard for one-way server-to-client streaming over


HTTP.

Stateless A design principle where the server retains no session state between requests.

Subscription In GraphQL, a mechanism for receiving real-time updates when data changes.
Term Definition

Sunset The planned removal of a deprecated API version, communicated via the
Sunset HTTP header (RFC 8594).

Swagger The original name for OpenAPI; now refers to tools (Swagger UI, Swagger
Editor) around the specification.

Throttling Slowing down or queuing excess requests rather than rejecting them outright.

TLS Transport Layer Security — cryptographic protocol that provides encryption for
data in transit (HTTPS).

Token Bucket A rate limiting algorithm where tokens are added at a fixed rate and consumed
by each request.

Trace A record of a request's journey across multiple services, used for debugging
distributed systems.

URI Uniform Resource Identifier — a string that identifies a resource (includes URLs
and URNs).

Webhook A callback mechanism where a server pushes data to a client's URL when a
specific event occurs.

WebSocket A protocol providing full-duplex, bidirectional communication over a single TCP


connection.

WSDL Web Services Description Language — XML document describing a SOAP web
service's interface.

Appendix C: CLI Cheatsheets

C.1 curl Commands

Action Command

GET request curl [Link]

GET with headers curl -H "Authorization: Bearer TOKEN"


[Link]

POST JSON curl -X POST -H "Content-Type: application/json" -d


'{"name":"Sasank"}' [Link]
Action Command

PUT request curl -X PUT -H "Content-Type: application/json" -d


'{"name":"Updated"}' [Link]

PATCH request curl -X PATCH -H "Content-Type: application/json" -d


'{"email":"new@[Link]"}' [Link]

DELETE request curl -X DELETE [Link]

Show response curl -i [Link]


headers

Show only headers curl -I [Link]

Verbose output curl -v [Link]

Follow redirects curl -L [Link]

Upload file curl -X POST -F "file=@[Link]"


[Link]

Set timeout curl --connect-timeout 5 --max-time 30


[Link]

Save response to curl -o [Link] [Link]


file

Basic curl -u username:password [Link]


authentication

Pretty print JSON curl -s [Link] | python -m


[Link]

C.2 httpie Commands

Action Command

GET request http GET [Link]

POST JSON http POST [Link] name=Sasank


email=s@[Link]

PUT request http PUT [Link]


name=Updated

DELETE request http DELETE [Link]

Custom header http GET [Link]


Authorization:"Bearer TOKEN"

Query parameters http GET [Link] page==2


per_page==25
Action Command

Upload file http -f POST [Link]


file@[Link]

Download file http --download


[Link]

Show only headers http --headers GET [Link]

Session (persist cookies) http --session=mysession POST


[Link]

C.3 Docker CLI for API Deployment

Action Command

Build image docker build -t my-api:1.0 .

Run container docker run -d -p 3000:3000 --name api my-api:1.0

Run with env vars docker run -d -p 3000:3000 -e DB_URL=... my-api:1.0

View logs docker logs -f api

Stop container docker stop api

Remove container docker rm api

Compose up docker compose up -d

Compose down docker compose down -v

List containers docker ps

Exec into container docker exec -it api /bin/sh

Push to registry docker push [Link]/my-api:1.0

C.4 kubectl for API Deployment

Action Command

Apply manifests kubectl apply -f k8s/

Get pods kubectl get pods -n api-namespace

Get services kubectl get svc -n api-namespace


Action Command

View pod logs kubectl logs -f deployment/api-server -n api-namespace

Describe pod kubectl describe pod api-server-abc123 -n api-namespace

Port forward kubectl port-forward svc/api-server 3000:3000 -n api-


namespace

Scale deployment kubectl scale deployment api-server --replicas=5

Rolling update kubectl set image deployment/api-server api=my-api:2.0

Rollback kubectl rollout undo deployment/api-server

Get config maps kubectl get configmap -n api-namespace

Appendix D: OpenAPI/Swagger Complete


Examples

D.1 Pet Store API (OpenAPI 3.1)


YAML

openapi: 3.1.0 info: title: Pet Store API version: 1.0.0 description: A
sample Pet Store API demonstrating OpenAPI 3.1 features. contact: name:
API Support email: support@[Link] license: name:
Apache 2.0 servers: - url: [Link]
description: Production - url: [Link]
description: Staging paths: /pets: get: operationId: listPets
summary: List all pets tags: [Pets] parameters: - name:
species in: query schema: type: string
enum: [dog, cat, bird, fish] - name: limit in: query
schema: type: integer default: 25
maximum: 100 - name: cursor in: query schema:
type: string responses: '200': description: A
paginated list of pets content: application/json:
schema: type: object properties:
data: type: array items:
$ref: '#/components/schemas/Pet' next_cursor:
type: string nullable: true post: operationId:
createPet summary: Create a pet tags: [Pets] security:
- bearerAuth: [] requestBody: required: true content:
application/json: schema: $ref:
'#/components/schemas/CreatePetRequest' responses: '201':
description: Pet created headers: Location:
schema: type: string content:
application/json: schema: $ref:
'#/components/schemas/Pet' '422': description: Validation
error content: application/json: schema:
$ref: '#/components/schemas/Error' /pets/{petId}: get:
operationId: getPet summary: Get a pet by ID tags: [Pets]
parameters: - name: petId in: path required: true
schema: type: integer responses: '200':
description: Pet details content: application/json:
schema: $ref: '#/components/schemas/Pet' '404':
description: Pet not found components: schemas: Pet: type:
object required: [id, name, species] properties: id:
type: integer name: type: string species:
type: string enum: [dog, cat, bird, fish] breed:
type: string age: type: integer adopted:
type: boolean default: false created_at: type:
string format: date-time CreatePetRequest: type: object
required: [name, species] properties: name: type:
string minLength: 1 maxLength: 100 species:
type: string enum: [dog, cat, bird, fish] breed:
type: string age: type: integer minimum: 0
Error: type: object properties: type: type:
string title: type: string status: type:
integer detail: type: string errors:
type: array items: type: object properties:
field: type: string message:
type: string securitySchemes: bearerAuth: type: http
scheme: bearer bearerFormat: JWT

Appendix E: Protocol Buffers Examples

E.1 Complete Proto File — User Service


PROTOBUF

syntax = "proto3"; package userservice.v1; option go_package =


"[Link]/myapp/proto/userservice/v1"; option java_package =
"[Link].v1"; import "google/protobuf/[Link]";
import "google/protobuf/field_mask.proto"; // User represents a registered
user in the system. message User { int64 id = 1; string name = 2;
string email = 3; UserRole role = 4; bool is_active = 5;
[Link] created_at = 6; [Link]
updated_at = 7; map<string, string> metadata = 8; } enum UserRole {
USER_ROLE_UNSPECIFIED = 0; USER_ROLE_USER = 1; USER_ROLE_ADMIN = 2;
USER_ROLE_MANAGER = 3; } // --- Requests and Responses --- message
CreateUserRequest { string name = 1; string email = 2; string
password = 3; UserRole role = 4; } message GetUserRequest { int64 id
= 1; } message UpdateUserRequest { int64 id = 1; User user = 2;
[Link] update_mask = 3; } message DeleteUserRequest {
int64 id = 1; } message ListUsersRequest { int32 page_size = 1;
string page_token = 2; string filter = 3; // e.g., "role=ADMIN"
string order_by = 4; // e.g., "created_at desc" } message ListUsersResponse
{ repeated User users = 1; string next_page_token = 2; int32
total_count = 3; } // --- Service Definition --- service UserService {
rpc CreateUser (CreateUserRequest) returns (User); rpc GetUser
(GetUserRequest) returns (User); rpc UpdateUser (UpdateUserRequest)
returns (User); rpc DeleteUser (DeleteUserRequest) returns
([Link]); rpc ListUsers (ListUsersRequest) returns
(ListUsersResponse); }

E.2 Proto Best Practices


● Use field numbers 1–15 for frequently accessed fields (1-byte encoding)

● Never reuse or reassign field numbers after deployment

● Use reserved keyword for removed fields to prevent accidental reuse

● Prefix enum values with the enum name (e.g., USER_ROLE_ADMIN)

● Always include an UNSPECIFIED = 0 value for enums

● Use [Link] for partial updates

● Use [Link] for datetime fields

● Version your packages (e.g., userservice.v1)

Appendix F: Security Checklist

# Category Check Item Priority

1 Transport All traffic uses HTTPS (TLS 1.2+) Critical

2 Transport HSTS header enabled with long max-age High

3 Transport TLS certificate is valid and auto-renewed Critical

4 Authentication Passwords hashed with bcrypt/argon2 (never Critical


MD5/SHA1)

5 Authentication JWT tokens have short expiration (5–15 min) High

6 Authentication Refresh tokens are stored securely and can be revoked High

7 Authentication API keys can be rotated without downtime Medium


# Category Check Item Priority

8 Authentication Failed login rate limiting (e.g., 5 attempts/minute) High

9 Authentication Multi-factor authentication available for admin accounts High

10 Authorization Object-level authorization on every endpoint (BOLA Critical


prevention)

11 Authorization Function-level authorization (BFLA prevention) Critical

12 Authorization Role-based access control implemented and tested High

13 Authorization Mass assignment protection (allowlist request fields) High

14 Input All input validated (type, length, format, range) Critical

15 Input Parameterized queries (prevent SQL/NoSQL injection) Critical

16 Input Request body size limits enforced High

17 Input File upload type and size validation High

18 Input URL parameters sanitized (prevent path traversal) High

19 Output Sensitive data excluded from responses (passwords, Critical


internal IDs)

20 Output Stack traces and debug info disabled in production Critical

21 Output PII data minimized in responses High

22 Output Response headers don't leak server technology Medium

23 Headers X-Content-Type-Options: nosniff High

24 Headers X-Frame-Options: DENY Medium

25 Headers Content-Security-Policy configured Medium

26 Headers Referrer-Policy: strict-origin-when-cross-origin Medium

27 Rate Limiting Rate limiting implemented on all endpoints High

28 Rate Limiting Stricter limits on auth endpoints (login, register) High

29 Rate Limiting 429 response includes Retry-After header Medium

30 CORS Origins explicitly allowlisted (no wildcard with High


credentials)

31 CORS Allowed methods and headers explicitly configured Medium

32 Secrets No secrets in source code or environment variables in Critical


code
# Category Check Item Priority

33 Secrets Secrets stored in vault (AWS SM, Azure KV, HashiCorp High
Vault)

34 Secrets Secrets rotated regularly Medium

35 Logging All authentication events logged (success and failure) High

36 Logging All authorization failures logged High

37 Logging Sensitive data excluded from logs (passwords, tokens, Critical


PII)

38 Logging Audit trail for data modifications Medium

39 Dependencies Dependencies scanned for known vulnerabilities (npm High


audit, Snyk)

40 Dependencies Dependencies pinned to specific versions Medium

41 Infrastructure API endpoints not exposing debug/admin interfaces in Critical


production

42 Infrastructure Database not accessible from public internet Critical

43 Infrastructure WAF (Web Application Firewall) in place Medium

44 Infrastructure DDoS protection enabled Medium

45 Compliance GDPR: data deletion/export endpoints available High

46 Compliance Data encryption at rest High

47 Compliance Privacy policy and terms of service documented Medium

48 Testing Automated security testing in CI/CD pipeline High

49 Testing Regular penetration testing (at least annually) Medium

50 Testing OWASP API Top 10 reviewed for each endpoint High

Appendix G: Testing Checklist

# Category Test Item

1 Functional All CRUD operations return correct status codes


# Category Test Item

2 Functional GET endpoints return correct data format and structure

3 Functional POST creates resource and returns 201 with Location header

4 Functional PUT replaces the full resource correctly

5 Functional PATCH applies partial updates correctly

6 Functional DELETE removes resource and returns 204

7 Functional Pagination returns correct page size and total count

8 Functional Filtering returns only matching records

9 Functional Sorting returns records in correct order

10 Functional Search returns relevant results

11 Validation Required fields enforced (422 when missing)

12 Validation Field type validation (string, number, email, etc.)

13 Validation Field length/range limits enforced

14 Validation Invalid JSON body returns 400

15 Validation Unsupported Content-Type returns 415

16 Auth Unauthenticated requests return 401

17 Auth Invalid tokens return 401

18 Auth Expired tokens return 401

19 Auth Unauthorized role access returns 403

20 Auth User cannot access other users' resources (BOLA)

21 Error 404 returned for non-existent resources

22 Error 405 returned for unsupported HTTP methods

23 Error 409 returned for conflicts (duplicate data)

24 Error 429 returned when rate limit exceeded

25 Error Error responses follow consistent format (RFC 7807)

26 Error No stack traces or internal details in error responses

27 Performance Response times within SLO targets under normal load

28 Performance API handles expected concurrent user load

29 Performance No memory leaks under sustained load


# Category Test Item

30 Performance Database connection pool properly configured

31 Edge Cases Empty collections return 200 with empty array (not 404)

32 Edge Cases Large payloads handled correctly or rejected with 413

33 Edge Cases Special characters in input handled correctly

34 Edge Cases Concurrent updates handled (optimistic locking)

35 Edge Cases Idempotency keys prevent duplicate operations

36 Integration Database operations succeed with real database

37 Integration External API calls are mocked in tests

38 Integration Webhook delivery tested

39 Contract API responses match OpenAPI specification

40 Contract Consumer contracts verified

Appendix H: CI/CD Pipeline Examples

H.1 GitHub Actions — [Link] API


YAML — .github/workflows/[Link]

name: API CI/CD Pipeline on: push: branches: [main, develop]


pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest
services: mongodb: image: mongo:7 ports:
['27017:27017'] redis: image: redis:7-alpine ports:
['6379:6379'] steps: - uses: actions/checkout@v4 - uses:
actions/setup-node@v4 with: node-version: '20'
cache: 'npm' - run: npm ci - run: npm run lint - run: npm
run test:unit - run: npm run test:integration env:
MONGODB_URI: mongodb://localhost:27017/test REDIS_URL:
redis://localhost:6379 - run: npm run test:coverage - uses:
actions/upload-artifact@v4 with: name: coverage-report
path: coverage/ security: runs-on: ubuntu-latest steps: -
uses: actions/checkout@v4 - run: npm audit --audit-level=high -
uses: aquasecurity/trivy-action@master with: scan-type:
'fs' severity: 'HIGH,CRITICAL' deploy: needs: [test,
security] if: [Link] == 'refs/heads/main' runs-on: ubuntu-latest
steps: - uses: actions/checkout@v4 - uses: docker/login-action@v3
with: registry: [Link] username: ${{ [Link] }}
password: ${{ secrets.GITHUB_TOKEN }} - uses: docker/build-push-
action@v5 with: push: true tags: [Link]/${{
[Link] }}:${{ [Link] }}

H.2 GitHub Actions — Python API


YAML

name: Python API CI on: [push, pull_request] jobs: test: runs-on:


ubuntu-latest services: postgres: image: postgres:16
env: POSTGRES_DB: testdb POSTGRES_USER: test
POSTGRES_PASSWORD: test ports: ['5432:5432'] steps: -
uses: actions/checkout@v4 - uses: actions/setup-python@v5 with:
python-version: '3.12' - run: pip install -r [Link] -
run: ruff check . - run: mypy src/ - run: pytest tests/ -v --
cov=src --cov-report=xml env: DATABASE_URL:
postgresql://test:test@localhost:5432/testdb

Appendix I: Sample API Contracts

I.1 REST API Contract Template


YAML

openapi: 3.1.0 info: title: [Service Name] API version: 1.0.0


description: "[Brief description of what this API does]" contact: name:
[Team Name] email: [team-email@[Link]] servers: - url:
[Link] description: Production - url:
[Link] description: Staging security: -
bearerAuth: [] paths: /[resources]: get: summary: List
[resources] parameters: - $ref:
'#/components/parameters/PageSize' - $ref:
'#/components/parameters/Cursor' responses: '200':
description: Success '401': $ref:
'#/components/responses/Unauthorized' components: parameters:
PageSize: name: page_size in: query schema: type:
integer default: 25 maximum: 100 Cursor: name:
cursor in: query schema: type: string responses:
Unauthorized: description: Authentication required content:
application/json: schema: $ref:
'#/components/schemas/Error' schemas: Error: type: object
properties: type: { type: string } title: { type: string }
status: { type: integer } detail: { type: string }
securitySchemes: bearerAuth: type: http scheme: bearer
bearerFormat: JWT

I.2 AsyncAPI Contract Template


YAML
asyncapi: 2.6.0 info: title: Order Events API version: 1.0.0
description: Asynchronous events for order lifecycle servers: production:
url: kafka://[Link] protocol: kafka channels:
[Link]: publish: summary: Order created event
message: $ref: '#/components/messages/OrderCreated'
[Link]: publish: summary: Order shipped event
message: $ref: '#/components/messages/OrderShipped' components:
messages: OrderCreated: payload: type: object
properties: order_id: type: string
customer_id: type: string items: type:
array total_amount: type: number created_at:
type: string format: date-time OrderShipped: payload:
type: object properties: order_id: type: string
tracking_number: type: string carrier:
type: string shipped_at: type: string
format: date-time

Appendix J: Quiz Answers & Solutions

Chapter 1 Answers
Q1. API stands for Application Programming Interface. Its primary purpose is to enable different
software applications to communicate with each other through a defined set of rules and protocols.

Q2. (1) Restaurant waiter — takes your order (request) to the kitchen (server) and brings back food
(response). (2) Electrical outlet — provides a standard interface for accessing electricity without needing
to understand the power grid. (3) Universal remote — sends standard commands to different devices
using a defined protocol.

Q3. Public APIs are available to any developer (e.g., Google Maps). Private APIs are used only within an
organization. Partner APIs are shared with specific business partners under formal agreements.

Q4. 2000.

Q5. Method (verb), URL (endpoint), Headers, Body (optional).

Q6. curl and httpie.

Q7. 200 OK.

Q14. JSON. It's lighter than XML, human-readable, natively supported by JavaScript, and has simpler
parsing in all languages.

Q15. curl -H "Accept: application/json" [Link]


Chapter 2 Answers
Q1. HTTP/2 introduces multiplexing (multiple streams over one connection), header compression
(HPACK), server push, and binary framing. HTTP/1.1 uses text-based protocol with head-of-line blocking.

Q3. 401 means "not authenticated" (credentials missing or invalid). 403 means "authenticated but not
authorized" (you are who you say, but you don't have permission).

Q5. 201 Created, with a Location header pointing to the newly created resource.

Chapter 3 Answers
Q1. Client-Server, Stateless, Cacheable, Uniform Interface, Layered System, Code on Demand (optional).

Q2. The Richardson Maturity Model measures REST compliance across 4 levels (0–3). Most real-world
APIs are at Level 2 (resources + HTTP verbs).

Q5. gRPC uses Protocol Buffers, a binary serialization format. Binary encoding is more compact than
JSON text, and proto schemas enable faster parsing through code generation rather than runtime
reflection.

Chapter 4 Answers
Q1. API-First means designing the API specification before writing code. Advantages: (1) parallel
frontend/backend development, (2) better design through early review, (3) automatic documentation
generation from the spec.

Q3. Cursor-based pagination scales better. Offset-based requires the database to scan and skip rows
(O(n)), becoming slow on large datasets. Cursor-based uses indexed lookups (O(log n)).

For complete solutions to all exercises including full source code, refer to the companion code repository
referenced in the Back Matter section.

References

Books
● Fielding, R.T. (2000). Architectural Styles and the Design of Network-based Software
Architectures. Doctoral dissertation, UC Irvine.

● Richardson, L. & Ruby, S. (2013). RESTful Web APIs. O'Reilly Media.

● Lauret, A. (2019). The Design of Web APIs. Manning Publications.

● Siriwardena, P. (2020). Advanced API Security: OAuth 2.0 and Beyond. Apress.

● Newman, S. (2021). Building Microservices, 2nd Edition. O'Reilly Media.

● Kleppmann, M. (2017). Designing Data-Intensive Applications. O'Reilly Media.

● Burns, B. (2018). Designing Distributed Systems. O'Reilly Media.

● Geewax, J. (2021). API Design Patterns. Manning Publications.

RFCs & Specifications


● RFC 7231 — HTTP/1.1 Semantics and Content

● RFC 7807 — Problem Details for HTTP APIs

● RFC 8594 — The Sunset HTTP Header Field

● RFC 6749 — The OAuth 2.0 Authorization Framework

● RFC 7519 — JSON Web Token (JWT)

● RFC 6902 — JavaScript Object Notation (JSON) Patch

● RFC 7396 — JSON Merge Patch

● RFC 9110 — HTTP Semantics (supersedes 7231)

● OpenAPI Specification 3.1.0 — [Link]

● GraphQL Specification — [Link]

● AsyncAPI Specification — [Link]

● Protocol Buffers Language Guide — [Link]

Online Resources
● OWASP API Security Top 10 — [Link]/API-Security
● Google API Design Guide — [Link]/apis/design

● Microsoft REST API Guidelines — [Link]/microsoft/api-guidelines

● Stripe API Reference — [Link]/docs/api (gold standard for API documentation)

● Postman Learning Center — [Link]

● ByteByteGo System Design — [Link]

● gRPC Documentation — [Link]/docs

● Kubernetes API Conventions — [Link]/docs

Acknowledgements
This guide was created to help Sasank and fellow developers master the art and science of API
development. Special thanks to the open-source communities behind OpenAPI, GraphQL, gRPC, and the
countless developers who contribute to the tools, frameworks, and standards that make modern API
development possible.

The API ecosystem thrives because of a culture of sharing knowledge, writing documentation, and
building tools that make other developers' lives easier. This guide is a contribution to that tradition.

Index

Term Chapter(s)

API-First Design 1, 4

API Gateway 14

API Key 8

AsyncAPI 3, 18, App I

Authentication 8

Authorization 8, 13
Term Chapter(s)

BOLA 13

Cache-Control 2, 16

Caching 5, 16

Circuit Breaker 14, 17

CORS 2

curl 1, App C

Cursor Pagination 4, 5

DataLoader 6

Docker 1, 17, App C

Error Handling 4

ETag 2, 5, 16

Event Sourcing 18

FastAPI 5, 17

GraphQL 3, 6, 17

gRPC 3, 7, 17

HATEOAS 3, 4

Health Check 15

HTTP Methods 2

HTTP Status Codes 2

HTTP/2 2, 7

HTTP/3 2

Idempotency 4

JWT 8

k6 12

Kong 14

Kubernetes 17, App C

Load Testing 12

Logging 15
Term Chapter(s)

Microservices 14, 17, 18

Monitoring 15

mTLS 8, 14

N+1 Problem 6

OAuth 2.0 8

Observability 15

OpenAPI 4, 11, App D

OpenTelemetry 15

OWASP API Top 10 13

Pagination 4, 5

Performance 16

PKCE 8

Postman 1

Protocol Buffers 7, App E

Rate Limiting 9

RBAC 8

Redis 9, 16

REST 3, 5

RFC 7807 4

Richardson Maturity Model 3, 5

Saga Pattern 18

Security 8, 13, App F

Serverless 18

Service Mesh 14

SLA/SLO/SLI 15

SOAP 3

Spring Boot 5, 17

SSE 2
Term Chapter(s)

Stripe 1, 19, 20

System Design 20

Testing 12, App G

TLS/HTTPS 2

Token Bucket 9

Tracing 15

Versioning 10

Webhooks 3, 5

WebSocket 2, 3

API Study Guide — Beginner to Expert


Prepared for Sasank | Version 1.0 | April 2026
© 2026 — All rights reserved.

You might also like