REST API Complete Guide
REST API Complete Guide
REST API
Complete Developer Guide
From Zero to Corporate-Grade API Development in C++ & Java
Topics Covered
• All HTTP Methods in depth (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS)
Page 1
REST API REST API Complete Guide
Table of Contents
1. What is an API? What is REST?
2. REST Constraints & Architectural Principles
3. HTTP Protocol Deep Dive
4. HTTP Methods — All 7 in Depth
■ GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
5. Request Anatomy — Headers, Body, Query Params, Path Params
6. Response Anatomy — Status Codes, Headers, Body
7. HTTP Status Codes — Complete Reference
8. Authentication & Authorization
■ API Keys, Basic Auth, Bearer Tokens, OAuth2, JWT
9. Data Formats — JSON, XML, Form Data
10. Advanced Concepts — Pagination, Filtering, Sorting
11. REST API Versioning Strategies
12. Rate Limiting & Throttling
13. REST API Security Best Practices
14. REST API in C++
■ libcurl, nlohmann/json, [Link], full project example
15. REST API in Java
■ HttpClient, OkHttp, Retrofit, Spring Boot REST Client
16. Corporate Best Practices
17. Testing REST APIs
18. Error Handling Patterns
19. Real-World Project — E-Commerce API
20. Quick Reference Card
Page 2
REST API REST API Complete Guide
In the corporate world, APIs power everything: your mobile banking app talks to the bank's server via APIs,
Amazon's checkout uses dozens of internal APIs, Uber's driver-tracking uses real-time APIs. APIs are the
backbone of modern software architecture.
Page 3
REST API REST API Complete Guide
Page 4
REST API REST API Complete Guide
1. Client-Server Separation
The UI/client and data-storage/server are completely separate. This means your React frontend and your
Java Spring backend are independent — they evolve independently. The client only knows the API contract
(endpoints + data shapes), not the implementation.
2. Stateless
Each HTTP request from client to server must contain ALL information needed to understand the request.
The server stores NO session state between requests. Authentication tokens, filters, and parameters must be
resent every time. This enables horizontal scaling — any server can handle any request.
3. Cacheable
Responses must define themselves as cacheable or non-cacheable using HTTP headers like Cache-Control,
ETag, Last-Modified. Caching eliminates redundant calls, reduces server load, and speeds up client apps
dramatically. GET responses are typically cacheable; POST/DELETE are not.
4. Uniform Interface
The most critical constraint. REST defines 4 sub-constraints: resource identification via URIs; manipulation of
resources through representations; self-descriptive messages (Content-Type header tells the receiver how to
parse the body); HATEOAS (responses include links to related actions).
5. Layered System
A client cannot tell whether it is connected directly to the end server or to an intermediary (load balancer,
CDN, API gateway, caching proxy). Each layer only sees the adjacent layer. In AWS, an API Gateway sits in
front of Lambda functions — the client talks to the Gateway.
Page 5
REST API REST API Complete Guide
Page 6
REST API REST API Complete Guide
HTTP/1.1 1997 Keep-alive, chunked transfer, pipelining Most REST APIs today
HTTP/2 2015 Multiplexing, header compression, server push Modern APIs, gRPC
HTTP/3 2022 UDP-based (QUIC), 0-RTT, better mobile perf Cutting-edge services
Breakdown:
Scheme → protocol (https)
Host → domain name
Port → 443 for HTTPS (default, often omitted)
Path → /v2 = version; /users = resource; /42 = path param; /orders = sub-reso
urce
Query → key=value pairs for filtering/pagination
Page 7
REST API REST API Complete Guide
Page 8
REST API REST API Complete Guide
GET Examples:
GET /users → fetch all users
GET /users/42 → fetch user with ID 42
GET /users/42/orders → fetch orders for user 42
GET /products?category=laptop&limit;=20&page;=2 → filtered + paginated
GET /products/search?q=macbook → search
GET /files/[Link] → download file
Page 9
REST API REST API Complete Guide
[ NO REQUEST BODY ]
{
"id": 42,
"name": "Rahul Sharma",
"email": "rahul@[Link]",
"role": "engineer",
"createdAt": "2024-01-15T10:30:00Z"
}
{
"error": "NOT_FOUND",
"message": "User with id 42 does not exist",
"timestamp": "2024-11-20T08:15:00Z"
}
Page 10
REST API REST API Complete Guide
{
"name": "Priya Patel",
"email": "priya@[Link]",
"password": "SecurePass@123",
"role": "engineer",
"department": "backend"
}
{
"id": 43,
"name": "Priya Patel",
"email": "priya@[Link]",
"role": "engineer",
"createdAt": "2024-11-20T09:00:00Z"
Page 11
REST API REST API Complete Guide
}
Corporate tip: Always return the Location header pointing to the newly created resource. Use Idempotency-Key to
prevent duplicate submissions (e.g., network retry).
{
"error": "VALIDATION_ERROR",
"message": "Request body has validation errors",
"details": [
{ "field": "email", "message": "Invalid email format" },
{ "field": "password", "message": "Must be at least 8 characters" }
]
}
Page 12
REST API REST API Complete Guide
{
"name": "Rahul Kumar",
"email": "[Link]@[Link]",
"role": "senior-engineer",
"department": "platform",
"active": true
}
{
"id": 42,
"name": "Rahul Kumar",
"email": "[Link]@[Link]",
"role": "senior-engineer",
"updatedAt": "2024-11-20T10:00:00Z"
}
Page 13
REST API REST API Complete Guide
{
"email": "[Link]@[Link]",
"role": "staff-engineer"
}
// Only email and role change; name, department etc. stay the same
Page 14
REST API REST API Complete Guide
DELETE Request:
DELETE /users/42 HTTP/1.1
Host: [Link]
Authorization: Bearer eyJhbGciOiJSUzI1NiJ9...
Success Responses:
204 No Content → deleted successfully, no body
200 OK → deleted successfully with confirmation body
202 Accepted → deletion queued (async operation)
// OR with body:
HTTP/1.1 200 OK
{ "message": "User 42 deleted successfully", "deletedAt": "2024-11-20T11:00:00Z" }
// Client now knows: file exists, is 5MB, and when it was last modified
// Without downloading the entire file
Page 15
REST API REST API Complete Guide
OPTIONS returns the HTTP methods supported by a resource. Most importantly, browsers automatically
send an OPTIONS preflight request before cross-origin requests (CORS). Understanding OPTIONS is critical
for web API development.
Server Response:
HTTP/1.1 204 No Content
Allow: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: [Link]
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 86400
Page 16
REST API REST API Complete Guide
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
REQUEST LINE
POST /v2/orders?dryRun=true HTTP/1.1
↑ ↑ ↑
Method URI+QueryString HTTP version
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
HEADERS
Host: [Link]
Authorization: Bearer <token>
Content-Type: application/json
Accept: application/json
Accept-Encoding: gzip, deflate
X-Request-Id: req_abc123xyz
X-Correlation-Id: corr_456def
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
BLANK LINE (separator)
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
BODY (only for POST/PUT/PATCH)
{ "productId": 55, "qty": 2, "address": "Mumbai" }
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Page 17
REST API REST API Complete Guide
Page 18
REST API REST API Complete Guide
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
RESPONSE BODY
{ "id": 42, "name": "Rahul", "email": "rahul@[Link]" }
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Last-Modified When resource was last changed Tue, 19 Nov 2024 10:00:00
GMT
Page 19
REST API REST API Complete Guide
Page 20
REST API REST API Complete Guide
1xx — Informational
100 Continue Server received headers, client should proceed with body
2xx — Success
3xx — Redirection
301 Moved Permanently Resource URL changed forever; update your client
307 Temporary Redirect Like 302 but must keep HTTP method
308 Permanent Redirect Like 301 but must keep HTTP method
Page 21
REST API REST API Complete Guide
405 Method Not Allowed HTTP method not supported for this endpoint
429 Too Many Requests Rate limit exceeded; check Retry-After header
500 Internal Server Error Unhandled server exception — log and alert
Page 22
REST API REST API Complete Guide
// Step 1: Login
POST /auth/login HTTP/1.1
Content-Type: application/json
{
"email": "user@[Link]",
"password": "mypassword"
Page 23
REST API REST API Complete Guide
JWT Structure:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9 ← HEADER (base64)
.eyJzdWIiOiI0MiIsInJvbGUiOiJhZG1pbiJ9 ← PAYLOAD (base64)
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ← SIGNATURE
OAuth 2.0 Authorization Code Flow (most secure, used in web apps):
Page 24
REST API REST API Complete Guide
POST [Link]
{ "code": AUTH_CODE, "client_id": ..., "client_secret": ...,
"redirect_uri": ..., "grant_type": "authorization_code" }
Page 25
REST API REST API Complete Guide
// Error response
{
"error": { "code": "VALIDATION_ERROR", "message": "...",
Page 26
REST API REST API Complete Guide
username=rahul&password;=Secret123&remember;=true
------Boundary123
Content-Disposition: form-data; name="title"
My Document
------Boundary123
Content-Disposition: form-data; name="file"; filename="[Link]"
Content-Type: application/pdf
Page 27
REST API REST API Complete Guide
// Page-based pagination
GET /products?page=3&limit;=20
Response:
{
"data": [...],
"pagination": {
"page": 3, "limit": 20, "total": 500, "totalPages": 25,
"hasNext": true, "hasPrev": true,
"next": "/products?page=4&limit;=20",
"prev": "/products?page=2&limit;=20"
}
}
Response:
{
"data": [...],
"cursor": {
"next": "eyJpZCI6MTEwfQ",
"hasMore": true
}
}
Page 28
REST API REST API Complete Guide
// Filtering
GET /users?role=engineer&department;=backend&active;=true
GET /orders?status=pending&createdAfter;=2024-01-01&minTotal;=100
// Sorting
GET /products?sort=price■=asc
GET /products?sort=-price,+name // - for desc, + for asc
// Range queries
GET /products?price[gte]=100&price;[lte]=500
// Search
GET /products?search=wireless+headphones
Page 29
REST API REST API Complete Guide
URI Versioning /v1/users, /v2/users Visible, cacheable, easy to test URL change, not
REST-pure
// Version 1 — original
GET /v1/users/42
Response: { id: 42, name: 'Rahul Sharma' }
Page 30
REST API REST API Complete Guide
{
"error": "RATE_LIMIT_EXCEEDED",
"message": "You have exceeded 1000 requests per hour",
"retryAfter": 120
}
Sliding Window Rolling N requests over last N seconds More accurate, no burst at
window edge
Token Bucket Tokens refill at rate R, burst allowed Allows short bursts, AWS uses
this
Leaky Bucket Requests processed at fixed rate, excess queued Smooth output rate
Page 31
REST API REST API Complete Guide
Page 32
REST API REST API Complete Guide
Short-lived access tokens (15 min - 1 hour) + long-lived refresh tokens. Invalidate refresh tokens on logout.
Rotate refresh tokens on use (token rotation).
Page 33
REST API REST API Complete Guide
// [Link]:
cmake_minimum_required(VERSION 3.16)
project(RestApiClient)
set(CMAKE_CXX_STANDARD 17)
find_package(CURL REQUIRED)
add_executable(client [Link])
target_link_libraries(client CURL::libcurl)
target_include_directories(client PRIVATE ${CMAKE_SOURCE_DIR}/include)
struct HttpResponse {
long statusCode;
std::string body;
Page 34
REST API REST API Complete Guide
bool success;
};
std::string responseBody;
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Accept: application/json");
if (![Link]()) {
std::string authHeader = "Authorization: Bearer " + bearerToken;
headers = curl_slist_append(headers, authHeader.c_str());
}
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return result;
}
int main() {
std::string token = "eyJhbGciOiJSUzI1NiJ9...";
auto resp = httpGet("[Link] token);
if ([Link]) {
json user = json::parse([Link]);
std::cout << "Name: " << user["name"] << std::endl;
Page 35
REST API REST API Complete Guide
std::string responseBody;
std::string jsonStr = [Link]();
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
Page 36
REST API REST API Complete Guide
return result;
}
// Usage:
int main() {
json newUser = {
{"name", "Priya Patel"},
{"email", "priya@[Link]"},
{"role", "engineer"}
};
auto resp = httpPost("[Link]
newUser, "my_token");
if ([Link] == 201) {
json created = json::parse([Link]);
std::cout << "Created user ID: " << created["id"] << std::endl;
}
}
// DELETE
HttpResponse httpDelete(const std::string& url,
const std::string& token) {
CURL* curl = curl_easy_init();
Page 37
REST API REST API Complete Guide
std::string responseBody;
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers,
("Authorization: Bearer " + token).c_str());
class RestClient {
public:
explicit RestClient(const std::string& baseUrl,
const std::string& bearerToken = "");
~RestClient();
struct Response {
int statusCode;
json body;
bool ok;
std::string error;
Page 38
REST API REST API Complete Guide
};
private:
std::string baseUrl_;
std::string token_;
long timeout_ = 30;
std::map<std::string, std::string> extraHeaders_;
// GET user
auto user = [Link]("/users/42");
if ([Link]) std::cout << [Link]["name"] << std::endl;
// PATCH update
auto patched = [Link]("/users/42", {{ "role", "lead" }});
// DELETE
auto deleted = [Link]("/users/99");
if ([Link] == 204)
std::cout << "Deleted successfully" << std::endl;
}
Page 39
REST API REST API Complete Guide
// ■■ GET ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
public JsonNode get(String path) throws Exception {
HttpRequest request = [Link]()
.uri([Link](baseUrl + path))
.header("Authorization", "Bearer " + bearerToken)
.header("Accept", "application/json")
.timeout([Link](30))
.GET()
.build();
HttpResponse<String> response =
[Link](request, [Link]());
Page 40
REST API REST API Complete Guide
if ([Link]() == 200) {
return [Link]([Link]());
} else if ([Link]() == 404) {
throw new ResourceNotFoundException("Not found: " + path);
} else {
throw new ApiException([Link](), [Link]());
}
}
// ■■ POST ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
public JsonNode post(String path, Object body) throws Exception {
String json = [Link](body);
HttpResponse<String> response =
[Link](request, [Link]());
// ■■ PUT ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
public JsonNode put(String path, Object body) throws Exception {
String json = [Link](body);
HttpRequest request = [Link]()
.uri([Link](baseUrl + path))
.header("Authorization", "Bearer " + bearerToken)
.header("Content-Type", "application/json")
.PUT([Link](json))
.build();
HttpResponse<String> r = [Link](request, [Link]());
if ([Link]() == 200) return [Link]([Link]());
throw new ApiException([Link](), [Link]());
}
// ■■ PATCH ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
Page 41
REST API REST API Complete Guide
// ■■ DELETE ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
public boolean delete(String path) throws Exception {
HttpRequest request = [Link]()
.uri([Link](baseUrl + path))
.header("Authorization", "Bearer " + bearerToken)
.DELETE()
.build();
HttpResponse<String> r = [Link](request, [Link]());
return [Link]() == 204 || [Link]() == 200;
}
}
import okhttp3.*;
import [Link];
import [Link];
Page 42
REST API REST API Complete Guide
[Link] = baseUrl;
[Link] = token;
Page 43
REST API REST API Complete Guide
}
}
@GET("users")
Call<List<User>> getUsers(
@Query("page") int page,
@Query("limit") int limit,
@Query("role") String role
);
@GET("users/{id}")
Call<User> getUser(@Path("id") int userId);
@POST("users")
Call<User> createUser(@Body CreateUserRequest request);
@PUT("users/{id}")
Call<User> updateUser(@Path("id") int id, @Body UpdateUserRequest req);
@PATCH("users/{id}")
Call<User> patchUser(@Path("id") int id,
@Body Map<String, Object> fields);
@DELETE("users/{id}")
Call<Void> deleteUser(@Path("id") int userId);
@GET("users/{id}/orders")
Call<List<Order>> getUserOrders(
@Path("id") int userId,
@Header("Authorization") String token
);
}
Page 44
REST API REST API Complete Guide
Page 45
REST API REST API Complete Guide
<dependency>
<groupId>[Link]</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
// [Link] — Model
@Entity
public class User {
@Id @GeneratedValue(strategy = [Link])
private Long id;
private String name;
private String email;
private String role;
// constructors, getters, setters
}
@Autowired
private UserService userService;
Page 46
REST API REST API Complete Guide
// DELETE
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
[Link](id);
return [Link]().build(); // 204
}
}
Page 47
REST API REST API Complete Guide
■ Request tracing
Generate a unique X-Request-Id for every request. Log it with every log line. Return it in response headers.
Use X-Correlation-Id to trace across multiple microservices.
■ Structured logging
Log every request: method, path, status, duration, userId, requestId. Use JSON logs for log aggregation
(ELK stack, Splunk, Datadog).
■ Contract-first development
Write your OpenAPI spec BEFORE writing code. Generate server stubs and client SDKs from the spec.
Prevents mismatches between client and server.
Page 48
REST API REST API Complete Guide
Page 49
REST API REST API Complete Guide
# POST
curl -X POST [Link] \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"name":"Rahul","email":"r@[Link]","role":"engineer"}'
# PUT
curl -X PUT [Link] \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"name":"Rahul Kumar","email":"r@[Link]","role":"lead"}'
# PATCH
curl -X PATCH [Link] \
Page 50
REST API REST API Complete Guide
# DELETE
curl -X DELETE [Link] \
-H 'Authorization: Bearer YOUR_TOKEN' \
-w '\nHTTP Status: %{http_code}\n'
@Test
@WithMockUser(roles = "ADMIN")
void getUser_found_returns200() throws Exception {
[Link](get("/v1/users/42")
.header("Accept", "application/json"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(42))
.andExpect(jsonPath("$.name").isNotEmpty());
}
@Test
@WithMockUser(roles = "ADMIN")
void createUser_validBody_returns201() throws Exception {
CreateUserRequest req = new CreateUserRequest("Priya", "p@[Link]");
[Link](post("/v1/users")
.contentType(MediaType.APPLICATION_JSON)
.content([Link](req)))
.andExpect(status().isCreated())
Page 51
REST API REST API Complete Guide
.andExpect(header().exists("Location"))
.andExpect(jsonPath("$.id").isNumber());
}
@Test
@WithMockUser(roles = "ADMIN")
void getUser_notFound_returns404() throws Exception {
[Link](get("/v1/users/9999"))
.andExpect(status().isNotFound());
}
}
Page 52
REST API REST API Complete Guide
@ExceptionHandler([Link])
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
public ErrorResponse handleValidation(MethodArgumentNotValidException ex) {
List<FieldError> errors = [Link]().getFieldErrors()
.stream().map(e -> new FieldError([Link](), [Link]()))
.collect(toList());
return [Link]()
.code("VALIDATION_ERROR")
.message("Request validation failed")
.details(errors).build();
}
@ExceptionHandler([Link])
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
return [Link]("NOT_FOUND", [Link]());
}
@ExceptionHandler([Link])
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
Page 53
REST API REST API Complete Guide
Page 54
REST API REST API Complete Guide
Page 55
REST API REST API Complete Guide
Page 56
REST API REST API Complete Guide
Page 57
REST API REST API Complete Guide
Page 58
REST API REST API Complete Guide
You now have a complete foundation in REST API design, implementation, and best
practices. Build great APIs — stateless, versioned, secure, and well-documented.
Page 59