API Communication

REST

  • Introduction to REST: REST (Representational State Transfer) is a software architectural style that defines a set of constraints for creating stateless web services.

    • It is based on stateless communication between clients and servers using HTTP.

    • A RESTful service exposes resources (data objects) identified by URIs.

    • Clients interact with resources using HTTP methods/HTTP Verbs (GET, POST, PUT, DELETE).

    • Resource representations are typically in JSON, but XML or HTML can also be used.

  • Typical REST Workflow:

    • Client sends an HTTP request to the server.

    • Server processes the request.

    • Server returns a representation of the resource (e.g., JSON).

    • Client performs CRUD operations based on the resource.

  • REST Principles

    • Resource-Oriented:Everything in REST is a resource (e.g., users, posts, images).

      • Each resource is uniquely identified by a URL.

    • Representation: Can have multiple representations (e.g., JSON, XML).

    • Identifier (URI): A Uniform Resource Identifier (URI) is a unique address to access a resource. Example: /users/123

    • Metadata: Additional information about resources such as:

      • Content-Type: Specifies the format (JSON, XML, etc.).

      • Last-Modified: Indicates when the resource was last updated.

      • Content-Type: application/json

      • Cache-Control: no-cache

    • Control Data: Used to manage caching, authentication, and modification policies.

      • Example: Cache-Control: max-age=3600 allows a resource to be cached for 1 hour.

  • HTTP Methods in REST: REST APIs use HTTP methods to perform operations on resources.

HTTP Method

Purpose

Example

GET

Retrieve a resource

GET /users/123

POST

Create a new resource

POST /users

PUT

Update an existing resource

PUT /users/123

PATCH

Modify part of a resource

PATCH /users/123

DELETE

Remove a resource

DELETE /users/123

HEAD

Fetch metadata only (no body)

HEAD /users/123

OPTIONS

Retrieve allowed methods for a resource

OPTIONS /users

  • REST Constraints: To be RESTful, a web service must follow these six constraints:

    • Client-Server Separation: The client and server must be independent.

      • The client only requests data, and the server responds with it.

    • Stateless: The server does not store any information about the client between requests.

      • Each request must contain all required authentication and state information.

    • Cacheable: Responses should be cacheable to reduce server load.

      • Example: If an API response contains a Cache-Control header, the client can cache it.

    • Uniform Interface: The API should have a consistent structure:

      • Identification of resources via URIs.

      • Manipulation of resources via HTTP methods.

      • Self-descriptive messages including metadata.

      • HATEOAS (Hypermedia as the Engine of Application State): API responses include links to related resources.

    • Layered System: The architecture can have multiple layers (e.g., security, caching, load balancing).

      • The client should not know how many layers exist between it and the actual server.

    • Code-on-Demand: The server can send executable code (JavaScript) to the client.

  • REST API Design Best Practices:

    • Use Nouns in URIs: /users instead of /getUsers

    • Use Plural Nouns for Collections: /books instead of /book

    • Use Sub-Resources for Relationships:

      • /users/123/orders instead of /orders?user=123

      • /customers/1/orders → orders for a customer

      • /orders/99/products → products in order 99

      • Collections should be exposed as top-level resources.

      • Don’t go too deep with nesting (e.g., /a/b/c/d/e)—it becomes hard to consume and maintain.

    • Use HTTP Headers for Format Negotiation:

      • Accept: application/json

      • Content-Type: application/xml

    • Provide Filtering & Pagination:

      • /orders?minCost=50&limit=10&offset=20

    • Use Versioning: /v1/users or version in headers/query parameters.

    • Meaningful Errors:

      • 401 Unauthorized

      • 404 Not Found (Resource does not exist)

  • REST is not about tables or fields, but about:

    • Conceptual resources

    • Use cases

    • Client usability

    • Example: An Order resource may be composed from multiple database tables (customer, item, shipment) but is represented as a single, unified JSON object to the client.

  • API Versioning: API versioning allows multiple versions of an API to coexist, so that changes don't break existing clients.

    • APIs evolve. But changes can break existing client apps. Versioning ensures:

      • Old clients still work.

      • New clients can use new features.

      • The API contract remains reliable.

    • Versioning Strategies

      • URL Path Versioning: The version number is part of the URL.

        • GET /v1/users/123, GET /v2/users/123

      • Custom Header Versioning: Clean URLs; Version information is sent in the HTTP header.

        • X-API-Version: 2

      • Query Parameter Versioning: Version is specified as a query string.

        • GET /users/123?version=1

      • Content Negotiation: When media types change across versions

        • Accept: application/vnd.example.v1+json

    • Change Management Strategy:

Principle

Description

Add, don’t remove

Introduce new fields, don’t break old ones

Sunset obsolete parts

Phase out with proper warnings

Track change scope

Use tree analogy

  • Tree Analogy of API Change Scope: As you move from leaf to root, changes become more global and disruptive.

Level

Description

Leaf

Minor isolated endpoint change

Branch

Changes across related resources

Trunk

System-wide schema change

Root

Impacts all API versions and resources

  • Types of Breaking Changes:

Change Type

Example

Format change

XML → JSON

Field rename

name → productName

Data type change

int → float

Add required field

Adding email to required inputs

Remove field

Removing description from response

  • Semantic Versioning for APIs:

    • Format: MAJOR.MINOR.PATCH

      • But in APIs, often simplified to: BREAKING.NONBREAKING

        • BREAKING: Any change that could break existing clients

        • NONBREAKING: Additions, enhancements, backward-compatible changes

    • Example: Version 2.1 means: second major version, first set of safe enhancements.

    • This versioning strategy helps consumers know how risky it is to adopt a newer version.

  • API Documentation: API documentation tells developers what endpoints are available, what data they need, and what to expect in return.

    • Explains how to use and integrate with an API.

    • Helps developers adopt, test, and trust your API.

    • Should be clear, accurate, interactive, and up-to-date.

    • OpenAPI Specification (OAS): Formerly Swagger Spec, now maintained by the Linux Foundation; Industry standard tools to define, document, and test APIs interactively.

      • Written in YAML or JSON.

      • OAS Describes:

        • All endpoints (e.g., /users, /products)

        • Methods per endpoint (GET, POST, etc.)

        • Input/output schemas

        • Security/auth methods

        • Metadata like contact info, license

      • Can be used to auto-generate:

        • API docs (Swagger UI)

        • Client SDKs

        • Server code

      • Swagger Tools (Now OpenAPI Tools):

Tool

Use

Swagger Editor

Create & edit OpenAPI specs

Swagger UI

Render interactive API docs

Swagger Codegen

Generate client/server code

SwaggerHub

Collaborative API design

  • Good API Docs Should Include:

    • Clear endpoint descriptions

    • Sample requests/responses

    • Status codes

    • Authentication details

    • Required/optional parameters

  • API Documentation Formats:

Format

Maintained By

Language

RAML (RESTful API Modeling Language)

MuleSoft (Salesforce)

YAML

API Blueprint

Apiary (Oracle)

Markdown

OpenAPI (formerly Swagger)

Linux Foundation

YAML/JSON

  • REST Maturity Model: The REST Maturity Model helps evaluate how RESTful an API is, based on four levels (0 to 3). Each level builds upon the previous one, improving the use of REST principles.

    • Level 0 –

      • All requests are sent to a single endpoint (e.g., /api) using a single HTTP method (often POST).

      • No use of resources or proper HTTP methods.

    • Level 1 – Resources

      • Introduces the idea of resources (e.g., /users, /orders). Each resource has a unique URI.

      • Still usually uses only one HTTP method (like POST).

    • Level 2 – HTTP Methods

      • Uses standard HTTP methods correctly. Improves clarity and aligns with REST principles.

    • Level 3 – (HATEOAS) - Hypermedia As The Engine Of Application State

      • Includes links in responses to related actions/resources. Enables navigation.

  • Implementing REST APIs in Frameworks: Common backend frameworks (Spring Boot, Express.js, Django REST, etc.) offer:

    • Routing and URL mapping

    • Request parsing and response formatting

    • Model binding and ORM integration

    • Using Express.js (Node.js Example):

    • const express = require('express'); const app = express(); app.get('/products/:id', (req, res) => { res.json({ id: req.params.id, name: 'Pen', price: 10 }); }); app.listen(3000, () => console.log('Server running on port 3000'));

  • Common HTTP Status Codes:

Code

Status Text

Meaning

200

OK

The request has succeeded.

201

Created

A new resource has been successfully created.

202

Accepted

The request has been accepted for processing, but the process is not completed yet.

204

No Content

The request was successful but there is no response body.

206

Partial Content

Used when serving partial GET requests (e.g., for large file downloads).

301

Moved Permanently

Resource has a new permanent URI.

302

Found

Temporarily moved.

304

Not Modified

Use cached response; server content hasn't changed.

400

Bad Request

The server cannot process the request due to client-side errors (malformed syntax).

401

Unauthorized

Authentication is required or has failed.

403

Forbidden

The client is authenticated but not authorized to access the resource.

404

Not Found

The requested resource could not be found on the server.

405

Method Not Allowed

The requested method (e.g., PUT) is not allowed on this resource.

406

Not Acceptable

The resource exists, but it can't be returned in a format acceptable to the client (based on the Accept header).

409

Conflict

Request conflicts with server state (e.g., trying to create a duplicate resource).

415

Unsupported Media Type

Client sends data in an unsupported format (e.g., Content-Type: text/plain when API expects JSON).

422

Unprocessable Entity

Semantic errors in the request (used in validation).

429

Too Many Requests

Rate-limiting: client has sent too many requests in a short time.

500

Internal Server Error

A generic error indicating a server-side problem.

502

Bad Gateway

Server acting as a gateway received an invalid response from the upstream server.

503

Service Unavailable

Server is overloaded or under maintenance.

504

Gateway Timeout

Server acting as a gateway didn’t get a response in time.

GRPC

  • Traditional RPC approaches had problems:

    • Tight coupling with specific languages.

    • Low performance with text-based formats (like XML or JSON).

    • Lack of interoperability in distributed microservices.

  • gRPC in High Level:

Feature

Benefit

Uses Protocol Buffers

Compact and fast binary serialization

Built on HTTP/2

Multiplexed streams, low latency

Cross-platform

Works across multiple languages

Supports Streaming

Real-time communication

Contract-first approach

Defined via .proto files

Auto code generation

Developer productivity and consistency

  • gRPC Overview: Stands for Google Remote Procedure Call , although the "g" has flexible interpretations.

    • A modern, open-source, high-performance RPC (Remote Procedure Call) framework.

    • gRPC enables clients to call functions on remote servers as if they were local method calls.

    • Example: A mobile app that needs to get the current stock price of a company, instead of making a direct HTTP request to a web server and parsing JSON, It uses gRPC to call a GetStockPrice function on a remote stock price service (server). gRPC handles the networking details, and the app receives the stock price in a structured format.

  • gRPC Architecture & Workflow: This involves defining a service, generating server and client code, and the server handling requests.

    • Service Definition (.proto file): Defines the API contract using Protocol Buffers.

      • Specifies methods (e.g., GetStockPrice) and data structures (e.g., StockRequest, StockResponse).

      • service StockService { rpc GetStockPrice (StockRequest) returns (StockResponse); } message StockRequest { string symbol = 1; // Field ID 1: Stock symbol (e.g., "AAPL") } message StockResponse { float price = 1; // Field ID 1: Current stock price (e.g., 175.32) }

      • Both client and server agree on this schema.

    • Code Generation: Using the .proto file, we run a tool called protoc(the Protocol Buffer Compiler), and it generates code for both client and server.

      • Generates server-side code (e.g., in Java) with an interface to implement the GetStockPrice function, and client-side code with a stub to call that function.

    • Server Implementation: The server implements the defined service (e.g., fetching stock price data).

    • Client Call: The client invokes the method (e.g., GetStockPrice("GOOG")) using the generated stub. gRPC delivers it to the server, which processes it and returns the result.

  • Steps to Use a gRPC Service

    • Define service in .proto file.

    • Use protoc to generate client/server code.

    • Implement server logic by overriding the generated base class.

    • Use the client stub to call remote methods like local ones.

  • Protocol Buffers(Protobuf): Defines structure of data exchanged between client and server.

    • Protocol Buffers are the default Interface Definition Language (IDL) and serialization format used by gRPC.

      • Messages = Data structures with fields.

      • Services = Collections of RPC methods.

    • Much faster and more compact than JSON or XML.

    • Example: In the StockService, StockRequest and StockResponse are defined using Protocol Buffers. This ensures that both the client and server agree on the format of the stock symbol and price.

  • Advantages of gRPC

    • Efficiency: Uses HTTP/2 with multiplexing and header compression.

    • Strong Typing: Enforced by Protobuf schema.

    • Contract-First: Interface is defined before implementation.

    • Polyglot Support: Works with many languages.

    • Streaming Support: Bidirectional streaming for real-time use cases.

    • Rich Tooling: Includes protoc and debugging tools.

  • Disadvantages of gRPC

    • Not Ideal for External APIs: Browsers work better with REST + JSON.

    • Setup Complexity: More complex than basic HTTP APIs.

    • Service Definition Changes: Require regen and redistribution.

    • Still Evolving: Tooling and ecosystem less mature than REST.

  • Message Encoding(via Protocol Buffers):Data is encoded as a binary format, not text.

    • Each field is represented by a tag number, not the name.

    • Much faster to transmit and parse.

    • Example: symbol = "GOOG" is encoded using its tag and value in binary.

  • Message Framing: gRPC sends multiple messages over a single connection (via HTTP/2).

    • "Message framing" is the technique gRPC uses to separate these messages, so the receiver knows where one message ends and the next one begins.

    • Steps:

      • Encode the message using Protobuf.

      • Compute the message size in bytes.

      • It sends this binary representation of the size first.

      • Then, it sends the actual encoded message data.

      • Example: If message size = 25 bytes

        • gRPC sends: [binary(25)] [actual 25-byte message]

        • Receiver reads length, then reads the next 25 bytes as the message.

  • gRPC and HTTP/2: gRPC uses HTTP/2, enabling:

    • Multiplexing: Multiple messages over one connection.

    • Binary framing.

    • Header compression.

    • Example: Multiple concurrent stock price requests via a single HTTP/2 connection.

  • gRPC Communication Patterns: These are the different ways a client and server can interact.

    • Unary RPC: A single request, single response.

      • Example: The client sends a stock symbol using GetStockPrice, and the server sends back the price.

    • Server-Streaming RPC: Single request, stream of responses.

      • Example: A GetStockPriceHistory function. The client sends a stock symbol, and the server sends back a stream of historical prices for that stock over a period of time.

    • Client-Streaming RPC: Stream of requests, single response.

      • Example: An UpdateStockPrices function. The client sends a stream of stock symbols and their latest prices, and the server sends back a single response indicating success or failure of the update.

    • Bidirectional-Streaming RPC: Stream of requests, stream of responses.

      • Example: A real-time stock trading service. The client sends a stream of buy/sell orders, and the server sends back a stream of updates on order execution, price changes, etc.

  • Tools:

Tool/Resource

Description

grpc.io

Official docs and tutorials

protoc

Compiler for .proto files

Postman with gRPC

Supports gRPC testing (beta)

BloomRPC

GUI tool for gRPC like Postman

  • Define Service in a .proto file (stock.proto)

    • syntax = "proto3"; package stock; // The request message containing the stock symbol message StockRequest { string symbol = 1; } // The response message containing the stock price message StockResponse { double price = 1; } // The Stock service definition service StockService { rpc GetStockPrice (StockRequest) returns (StockResponse); }

GraphQL

  • GraphQL is a query language for APIs and a server-side runtime for executing those queries.

  • Developed by Facebook in 2012 and open-sourced in 2015.

  • It allows clients to precisely specify the data they need—nothing more, nothing less.

  • Key Characteristics:

    • Declarative: You ask for what you want.

    • Hierarchical: Mirrors your front-end view structure.

    • Strongly typed: Backed by a strict type system (schemas).

    • GraphQL uses a single endpoint for all data needs.

  • REST Limitation:

    • Overfetching: You get more data than needed. Example: /users returns full user details when you just need names.

    • Underfetching: You get less than needed and must make multiple requests.

    • Too many endpoints: Every new client requirement may need a new endpoint (/user-basic, /user-details).

    • GraphQL solves this with a single query that returns exactly what is needed.

  • A GraphQL operation can be:

    • Query – to read/fetch data

    • Mutation – to write/modify data

    • Subscription – to receive real-time data

  • Lifecycle:

    • The GraphQL service receives a request.

    • It validates the query against its schema.

    • It resolves the query using functions (called resolvers).

    • Returns data in JSON format.

    • Example:

      • query { posts { title author { name email } } }

    • Response:

      • {
            "data": {
                "posts": [
                    {
                        "title": "Introduction to GraphQL",
                        "author": {
                            "name": "John Doe",
                            "email": "john.doe@example.com"
                        }
                    }
                ]
            }
        }

  • Queries with Arguments and Variables: GraphQL queries support arguments and variables to customize data fetching.

    • Example:

      • query getPerson($personid: ID!) {
            human(id: $personid) {
                name
                height(unit: FOOT)
            }
        }
      • Variables:

        • {
          "personid": "1000"
          }
  • Queries - Advanced Features

    • Default Values: Set fallback values for variables.

    • Directives: Dynamic behavior like @include or @skip.

    • Fragments: Reusable sets of fields to reduce duplication.

      • Example:

      • fragment userInfo on User {
            name
            email
        }
  • Mutations: Modifying Data:

    • Just like queries, but used for write operations.

    • GraphQL gives full control over what is returned after a write.

    • Each mutation defines:

      • Input arguments

      • Returned data (you define what you want back)

    • Example:

      • mutation {
            addUser(name: "Alice", age: 30) {
                id
                name
                age
            }
        }
  • Schema and Types: The schema is the contract between the frontend and backend.

    • Schema defines:

      • Types of data (e.g., User, Post)

      • Relationships between types

      • Entry points: Query, Mutation, and optionally Subscription

      • ! indicates non-nullable.

      • ID, String, Int, Boolean, Float are scalar types.

      • Example:

        • type User {
              id: ID!
              name: String!
              age: Int
          }
    • Query and Mutation Types: Every GraphQL schema defines two special types:

      • Query: Entry point for data fetching

      • Mutation: Entry point for data modification

      • Example:

        • const schema = buildSchema(`
              type User {
                  id: ID!
                  name: String!
                  age: Int
              }
              type Query {
                  getUser(id: ID!): User
                  getUsers: [User]
              }
              type Mutation {
                  addUser(name: String!, age: Int!): User
              }
          `);
  • Resolvers: Connecting Schema to Data: Resolvers are backend functions that define how to fetch or modify data for a type/field.

    • Each field in a schema has a resolver function.

    • Resolvers can pull data from:

      • Databases (SQL, MongoDB, etc.)

      • REST APIs

      • External services

    • Example:

    • const resolvers = {
          Query: {
              getUser: (_, { id }) => db.findUserById(id),
          },
          Mutation: {
              addUser: (_, { name, age }) => db.addUser(name, age),
          }
      };
  • GraphQL as a Graph

    • GraphQL is based on graphs: nodes (types) and edges (relationships).

    • Think of the schema as a map of your entire data model.

    • Example:

      • User → Posts

      • Post → Comments

      • Comment → Author

    • GraphQL lets you traverse the graph in a single query.

  • GraphQL Document Language: GraphQL queries and mutations are written in a specific document language.

    • A document can contain:

      • One or more operations

      • Fragments

      • Variables

    • Example:

    • query GetUser {
          user(id: "1") {
              ...userInfo
          }
      }
      fragment userInfo on User {
          name
          email
      }
  • Tools for Working with GraphQL:

Tool

Purpose

GraphiQL

In-browser IDE for GraphQL

Apollo Client/Server

End-to-end GraphQL solution

GraphQL Playground

Feature-rich tool for testing GraphQL queries

Hasura

Instant GraphQL APIs on Postgres

Postman

Also supports GraphQL APIs for testing

  • Facebook’s social graph is a literal graph of people and their relationships.

    • GraphQL mirrors this structure, making it ideal for social networks, eCommerce, dashboards, etc.

Concept

Description

GraphQL

A query language for APIs

Operations

Query (read), Mutation (write), Subscription (live updates)

Schema

Blueprint of types and fields

Types

Define shape of data (User, Post, etc.)

Resolvers

Connect schema fields to real data

Advantages

Precise queries, fewer endpoints, flexible responses

Core Concepts

Arguments, variables, fragments, directives

Last updated