A Full Guide Understand Everything About APIS With Examples

March 26, 2026

A Full Guide Understand Everything About APIS With Examples

TL;DR

APIs (Application Programming Interfaces) let programs talk to each other. REST is the most common pattern (HTTP + JSON), but GraphQL (query language for data), WebSockets (real-time), and gRPC (fast RPC) serve different needs. Authentication uses tokens (Bearer, API keys) or OAuth for user delegation. Errors return status codes (2xx success, 4xx client error, 5xx server error). Master these patterns and you can consume any API confidently.

An API is a contract: "Call me with X data, I'll give you Y result." Without APIs, everything would be isolated. With them, your app talks to payment processors, maps services, AI models, and databases. This guide covers the mental model (what's actually happening), the most common patterns (REST, GraphQL, WebSocket), and practical examples you can run today. Whether you're integrating a third-party service or building an API for others to use, understanding these patterns makes you dangerous.

The Mental Model: What's an API?

Simplified: An API is a function on someone else's server that you call over the internet.

// Local function
function getUser(userId) {
  return database.query(`SELECT * FROM users WHERE id = ${userId}`);
}

// API (same thing, but over HTTP)
fetch('https://api.example.com/users/123')
  .then(res => res.json());

Key difference: With local functions, you call them directly. With APIs, you send a request over HTTP, and the server sends back a response.

Every API request has:

  1. Method (what action: GET, POST, PUT, DELETE)
  2. Endpoint (where: /users/123)
  3. Headers (metadata: authentication, content type)
  4. Body (optional data payload)

Every API response has:

  1. Status code (success or failure: 200, 404, 500)
  2. Headers (metadata about the response)
  3. Body (the actual data, usually JSON)

REST: The Most Common Pattern

REST (Representational State Transfer) is the industry standard. It uses HTTP verbs to describe actions on resources (nouns).

REST Basics

GET    /posts        → Fetch all posts
GET    /posts/123    → Fetch post #123
POST   /posts        → Create a new post
PUT    /posts/123    → Update post #123
DELETE /posts/123    → Delete post #123

Why verbs + nouns matter:

  • GET is safe (doesn't change data)
  • DELETE is dangerous (removes data)
  • POST creates; PUT updates

REST Example: Fetch Data

// Simple GET request
fetch('https://jsonplaceholder.typicode.com/posts/1')
  .then(res => res.json())
  .then(data => console.log(data));

// Output: { id: 1, title: "...", body: "...", userId: 1 }

REST Example: Create Data (POST)

fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    title: 'My Post',
    body: 'This is the content',
    userId: 1
  })
})
  .then(res => res.json())
  .then(data => console.log(data));

// Output: { id: 101, title: "My Post", body: "This is the content", userId: 1 }

REST Example: Update Data (PUT)

fetch('https://jsonplaceholder.typicode.com/posts/1', {
  method: 'PUT',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    id: 1,
    title: 'Updated Title',
    body: 'Updated body',
    userId: 1
  })
})
  .then(res => res.json())
  .then(data => console.log(data));

REST Example: Delete Data

fetch('https://jsonplaceholder.typicode.com/posts/1', {
  method: 'DELETE'
})
  .then(res => res.json())
  .then(data => console.log('Deleted:', data));

GraphQL: Query Language for APIs

GraphQL lets you request exactly the data you need—nothing more, nothing less.

REST vs GraphQL

REST:

GET /posts/1
→ { id, title, body, userId, createdAt, updatedAt, authorEmail, ... }
(you get everything; wasteful)

GraphQL:

query {
  post(id: 1) {
    title
    body
    author { name email }
  }
}
{ post: { title: "...", body: "...", author: { name: "...", email: "..." } } }
(you get only what you asked for)

GraphQL Example

const query = `
  query {
    posts {
      id
      title
      author {
        name
      }
    }
  }
`;

fetch('https://api.example.com/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query })
})
  .then(res => res.json())
  .then(data => console.log(data.data.posts));

Advantages:

  • No overfetching (get only what you need)
  • No underfetching (no multiple round-trips)
  • Strong typing (schema describes what's available)

Disadvantages:

  • More complex to learn
  • File uploads awkward
  • Query complexity can burden servers

WebSocket: Real-Time Communication

WebSocket maintains an open connection for real-time updates (chat, notifications, live data).

WebSocket Example

const ws = new WebSocket('wss://api.example.com/live');

ws.addEventListener('open', () => {
  console.log('Connected');
  ws.send(JSON.stringify({ action: 'subscribe', channel: 'prices' }));
});

ws.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  console.log('Price update:', data);
});

ws.addEventListener('close', () => {
  console.log('Disconnected');
});

Use cases:

  • Real-time chat
  • Live stock prices, cryptocurrency
  • Live notifications
  • Collaborative tools (Google Docs-style)

Difference from REST:

  • REST is request-response (client asks, server answers, connection closes)
  • WebSocket is two-way (client and server send data anytime)

Authentication: How APIs Know Who You Are

1. API Key

Simple token sent with each request.

fetch('https://api.example.com/data', {
  headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
})

Pros: Simple, works for server-to-server Cons: If leaked, anyone can use it

2. OAuth 2.0 (User Delegation)

User logs in on your app, grants permission to access their data on another service (Gmail, GitHub, Spotify). Your app never sees their password.

// User clicks "Sign in with Google"
// Google authenticates user, sends your app a token
// Your app uses that token to fetch user's Google data
fetch('https://www.googleapis.com/calendar/v3/calendars/primary/events', {
  headers: { 'Authorization': `Bearer ${googleToken}` }
})

Pros: User controls what data you access; you never handle passwords Cons: More complex setup

3. Session Cookies

Server sets a cookie; browser automatically sends it with each request.

// Login endpoint sets a cookie
fetch('https://api.example.com/login', {
  method: 'POST',
  credentials: 'include', // Send cookies
  body: JSON.stringify({ username, password })
})

// Subsequent requests automatically include the cookie
fetch('https://api.example.com/me', {
  credentials: 'include'
})

Pros: Works well for web apps; cookie is automatically sent Cons: CSRF attacks possible; less suitable for mobile/API clients

HTTP Status Codes: Understanding Responses

Code Meaning Example
2xx Success
200 OK (request succeeded) GET /posts → returns posts
201 Created (new resource created) POST /posts → creates post
204 No Content (success, no data returned) DELETE /posts/1
3xx Redirect
301 Moved Permanently Old URL → new URL
304 Not Modified (cached response OK) If-Modified-Since header
4xx Client Error
400 Bad Request (malformed request) Missing required field
401 Unauthorized (authentication required) Forgot API key
403 Forbidden (you don't have permission) Non-admin accessing admin endpoint
404 Not Found (resource doesn't exist) GET /posts/999
429 Too Many Requests (rate limited) Made too many requests too fast
5xx Server Error
500 Internal Server Error (something broke) Bug in server code
503 Service Unavailable (temporarily down) Maintenance or overload

Golden rule: If status is 2xx, the request succeeded. If 4xx or 5xx, something went wrong.

Error Handling: When Things Go Wrong

async function fetchData(url) {
  try {
    const res = await fetch(url);

    if (!res.ok) {
      throw new Error(`HTTP ${res.status}: ${res.statusText}`);
    }

    return await res.json();
  } catch (err) {
    console.error('API error:', err.message);
    // Handle gracefully: show user message, retry, etc.
  }
}

Common scenarios:

  • Network error: Can't reach the server (timeout, no internet). Retry logic helps.
  • 4xx error: Bad request on your end (fix the request)
  • 5xx error: Server broken (retry or escalate)
  • Rate limiting (429): Too many requests. Wait before retrying.

Rate Limiting: Play Nice

APIs often limit requests to prevent abuse.

// Check headers for rate limit info
const remaining = res.headers.get('X-RateLimit-Remaining');
const resetTime = res.headers.get('X-RateLimit-Reset');

if (remaining === '0') {
  console.log(`Rate limited. Reset at ${new Date(resetTime * 1000)}`);
}

Best practice: Check remaining quota before each request; back off gracefully when limited.

Real-World Example: Building a GitHub User Lookup

async function getGitHubUser(username) {
  const url = `https://api.github.com/users/${username}`;

  try {
    const res = await fetch(url);

    if (res.status === 404) {
      throw new Error('User not found');
    }

    if (!res.ok) {
      throw new Error(`HTTP ${res.status}`);
    }

    const user = await res.json();
    console.log(`${user.name} has ${user.public_repos} repos`);

  } catch (err) {
    console.error('Error:', err.message);
  }
}

getGitHubUser('torvalds'); // Linus Torvalds

Conclusion

APIs are how modern software talks. REST dominates for simplicity; GraphQL excels for flexibility; WebSocket enables real-time. Authentication varies by use case (API keys, OAuth, cookies). Status codes tell you success or failure; error handling makes your app resilient. With these patterns mastered, you can integrate any third-party service, build APIs others consume, and debug network issues confidently. Start with a simple REST API (like JSONPlaceholder), then graduate to real services (GitHub, Stripe, OpenAI) as you grow comfortable.


FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.