ResourcesAPI Terminologies

API Terminologies

A comprehensive guide to common API terminologies and concepts for developers working with web APIs.

Core Concepts

API (Application Programming Interface)

A set of rules and protocols that allows different software applications to communicate with each other. APIs define the methods and data formats that applications can use to request and exchange information.

// Example: Using a simple API
fetch('https://api.example.com/users')
  .then(response => response.json())
  .then(data => console.log(data))

APIs act as intermediaries between different software systems, enabling them to work together without needing to know each other’s internal implementation details.

REST (Representational State Transfer)

An architectural style for designing networked applications. RESTful APIs use HTTP requests to perform CRUD operations (Create, Read, Update, Delete) on resources.

Key principles of REST:

  • Stateless: Each request contains all information needed to process it
  • Client-Server: Separation of concerns between UI and data storage
  • Cacheable: Responses can be cached to improve performance
  • Uniform Interface: Consistent way to interact with resources
  • Layered System: Architecture can be composed of multiple layers
// RESTful API example
// GET    /api/users       - Get all users
// GET    /api/users/1     - Get specific user
// POST   /api/users       - Create new user
// PUT    /api/users/1     - Update entire user
// PATCH  /api/users/1     - Partially update user
// DELETE /api/users/1     - Delete user

Endpoint

A specific URL where an API can be accessed. Each endpoint corresponds to a specific resource or action in the API.

// Example endpoints
const baseURL = 'https://api.example.com'
 
// User endpoints
const getAllUsers = `${baseURL}/users`
const getUser = `${baseURL}/users/:id`
const createUser = `${baseURL}/users`
 
// Product endpoints
const getAllProducts = `${baseURL}/products`
const getProduct = `${baseURL}/products/:id`

HTTP Methods

HTTP methods (also called verbs) indicate the desired action to be performed on a resource.

GET

Retrieve data from the server. GET requests should be safe (no side effects) and idempotent (same result when called multiple times).

// GET request example
fetch('https://api.example.com/users/123')
  .then(response => response.json())
  .then(user => console.log(user))
 
// Expected response
// {
//   "id": 123,
//   "name": "John Doe",
//   "email": "john@example.com"
// }

Characteristics:

  • Does not modify data
  • Can be cached
  • Parameters sent in URL query string
  • Should be idempotent

POST

Create a new resource on the server. POST requests are not idempotent - calling them multiple times creates multiple resources.

// POST request example
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Jane Doe',
    email: 'jane@example.com',
  }),
})
  .then(response => response.json())
  .then(newUser => console.log(newUser))
 
// Expected response
// {
//   "id": 124,
//   "name": "Jane Doe",
//   "email": "jane@example.com",
//   "createdAt": "2024-01-15T10:30:00Z"
// }

Characteristics:

  • Creates new resources
  • Not idempotent
  • Data sent in request body
  • Returns newly created resource

PUT

Replace an entire resource with new data. PUT requests are idempotent - calling them multiple times with the same data produces the same result.

// PUT request example - replaces entire user
fetch('https://api.example.com/users/123', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'John Smith',
    email: 'john.smith@example.com',
    phone: '+1234567890',
  }),
})
  .then(response => response.json())
  .then(updatedUser => console.log(updatedUser))

Characteristics:

  • Replaces entire resource
  • Idempotent
  • Requires all fields
  • Creates resource if it doesn’t exist (optional)

PATCH

Partially update a resource. Only the fields provided in the request are updated.

// PATCH request example - updates only specified fields
fetch('https://api.example.com/users/123', {
  method: 'PATCH',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    email: 'newemail@example.com', // Only update email
  }),
})
  .then(response => response.json())
  .then(updatedUser => console.log(updatedUser))
 
// Other fields (name, phone, etc.) remain unchanged

Characteristics:

  • Partially updates resource
  • Only specified fields are modified
  • More efficient than PUT for small changes
  • May or may not be idempotent

DELETE

Remove a resource from the server.

// DELETE request example
fetch('https://api.example.com/users/123', {
  method: 'DELETE',
})
  .then(response => {
    if (response.ok) {
      console.log('User deleted successfully')
    }
  })
 
// Typically returns 204 No Content or 200 OK

Characteristics:

  • Removes resources
  • Idempotent (deleting same resource multiple times has same effect)
  • May return deleted resource or empty response
  • Returns 404 if resource doesn’t exist

Request & Response

Request Headers

Metadata sent with HTTP requests to provide additional context about the request or the client.

// Common request headers
const headers = {
  'Content-Type': 'application/json', // Data format being sent
  'Accept': 'application/json', // Expected response format
  'Authorization': 'Bearer eyJhbGc...', // Authentication token
  'User-Agent': 'MyApp/1.0', // Client application info
  'Accept-Language': 'en-US', // Preferred language
  'Cache-Control': 'no-cache', // Caching directives
}
 
fetch('https://api.example.com/data', {
  method: 'GET',
  headers: headers,
})

Important headers:

  • Content-Type: Format of data in request body (e.g., application/json, application/xml)
  • Accept: Expected format of response
  • Authorization: Credentials for authentication
  • User-Agent: Information about the client
  • Origin: Domain making the request (CORS)

Response Status Codes

Three-digit codes indicating the result of an HTTP request.

2xx - Success

// 200 OK - Request succeeded
// 201 Created - Resource created successfully
// 204 No Content - Success but no data to return
 
fetch('https://api.example.com/users', {
  method: 'POST',
  body: JSON.stringify(userData),
})
  .then(response => {
    if (response.status === 201) {
      console.log('User created!')
    }
  })

Common 2xx codes:

  • 200 OK: Request successful
  • 201 Created: New resource created
  • 202 Accepted: Request accepted, processing not complete
  • 204 No Content: Success with no response body

3xx - Redirection

// 301 Moved Permanently - Resource permanently moved
// 302 Found - Temporary redirect
// 304 Not Modified - Cached version is still valid

Common 3xx codes:

  • 301 Moved Permanently: Resource has new permanent URL
  • 302 Found: Temporary redirect
  • 304 Not Modified: Use cached version

4xx - Client Errors

// Handle client errors
fetch('https://api.example.com/users/999')
  .then(response => {
    if (response.status === 404) {
      console.error('User not found')
    } else if (response.status === 401) {
      console.error('Unauthorized - please log in')
    } else if (response.status === 400) {
      console.error('Bad request - check your data')
    }
  })

Common 4xx codes:

  • 400 Bad Request: Invalid request syntax or data
  • 401 Unauthorized: Authentication required
  • 403 Forbidden: Authenticated but not authorized
  • 404 Not Found: Resource doesn’t exist
  • 429 Too Many Requests: Rate limit exceeded

5xx - Server Errors

// Handle server errors
fetch('https://api.example.com/data')
  .then(response => {
    if (response.status >= 500) {
      console.error('Server error - try again later')
    }
  })

Common 5xx codes:

  • 500 Internal Server Error: Generic server error
  • 502 Bad Gateway: Invalid response from upstream server
  • 503 Service Unavailable: Server temporarily unavailable
  • 504 Gateway Timeout: Upstream server timeout

Payload

The actual data being sent in an HTTP request or response body.

// Request payload (body)
const requestPayload = {
  name: 'John Doe',
  email: 'john@example.com',
  age: 30,
}
 
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(requestPayload), // Payload
})
 
// Response payload
// {
//   "success": true,
//   "data": {
//     "id": 123,
//     "name": "John Doe",
//     "email": "john@example.com",
//     "age": 30
//   },
//   "message": "User created successfully"
// }

Authentication & Authorization

API Key

A simple authentication method using a unique identifier to authenticate requests.

// API Key in header
fetch('https://api.example.com/data', {
  headers: {
    'X-API-Key': 'your-api-key-here',
  },
})
 
// API Key in query parameter
fetch('https://api.example.com/data?api_key=your-api-key-here')

Characteristics:

  • Simple to implement
  • Less secure than other methods
  • Good for public or low-security APIs
  • Easy to revoke and regenerate
⚠️

Never expose API keys in client-side code or public repositories. Store them securely in environment variables or secrets management systems.

Bearer Token

A token-based authentication method where the token is sent in the Authorization header.

// Bearer token authentication
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
 
fetch('https://api.example.com/protected-resource', {
  headers: {
    'Authorization': `Bearer ${token}`,
  },
})
  .then(response => response.json())
  .then(data => console.log(data))

Common token types:

  • JWT (JSON Web Token): Self-contained token with encoded user information
  • Opaque tokens: Random strings that reference server-side session data

Token workflow:

// 1. Login to get token
fetch('https://api.example.com/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    username: 'user@example.com',
    password: 'password123',
  }),
})
  .then(response => response.json())
  .then(data => {
    // 2. Store token
    const token = data.access_token
    localStorage.setItem('token', token)
  })
 
// 3. Use token in subsequent requests
const token = localStorage.getItem('token')
fetch('https://api.example.com/profile', {
  headers: {
    'Authorization': `Bearer ${token}`,
  },
})

OAuth

An authorization framework that allows third-party applications to access user resources without exposing credentials.

// OAuth 2.0 flow example (simplified)
 
// 1. Redirect user to authorization server
const authURL = 'https://oauth.example.com/authorize' +
  '?client_id=your-client-id' +
  '&redirect_uri=https://yourapp.com/callback' +
  '&response_type=code' +
  '&scope=read write'
 
window.location.href = authURL
 
// 2. User authorizes and gets redirected back with code
// https://yourapp.com/callback?code=AUTHORIZATION_CODE
 
// 3. Exchange code for access token
fetch('https://oauth.example.com/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: 'AUTHORIZATION_CODE',
    client_id: 'your-client-id',
    client_secret: 'your-client-secret',
    redirect_uri: 'https://yourapp.com/callback',
  }),
})
  .then(response => response.json())
  .then(data => {
    const accessToken = data.access_token
    const refreshToken = data.refresh_token
    // Use access token for API requests
  })

OAuth 2.0 grant types:

  • Authorization Code: For web applications with backend
  • Implicit: For single-page applications (deprecated)
  • Client Credentials: For server-to-server communication
  • Resource Owner Password: Direct username/password exchange (not recommended)

Data Formats

JSON (JavaScript Object Notation)

A lightweight, text-based data format that’s easy for humans to read and write, and easy for machines to parse and generate.

// JSON example - User object
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com",
  "age": 30,
  "active": true,
  "roles": ["user", "admin"],
  "address": {
    "street": "123 Main St",
    "city": "New York",
    "country": "USA"
  },
  "metadata": null
}

JSON data types:

  • String: "text"
  • Number: 123, 45.67
  • Boolean: true, false
  • Array: [1, 2, 3]
  • Object: {"key": "value"}
  • Null: null

Working with JSON in JavaScript:

// Parse JSON string to object
const jsonString = '{"name":"John","age":30}'
const user = JSON.parse(jsonString)
console.log(user.name) // "John"
 
// Convert object to JSON string
const userData = { name: 'Jane', age: 25 }
const json = JSON.stringify(userData)
console.log(json) // '{"name":"Jane","age":25}'
 
// Pretty-print JSON
const prettyJson = JSON.stringify(userData, null, 2)
// {
//   "name": "Jane",
//   "age": 25
// }

Complex JSON example:

{
  "users": [
    {
      "id": 1,
      "name": "Alice",
      "posts": [
        {
          "id": 101,
          "title": "First Post",
          "tags": ["intro", "welcome"],
          "published": true
        }
      ]
    }
  ],
  "pagination": {
    "page": 1,
    "perPage": 10,
    "total": 100
  }
}

XML (eXtensible Markup Language)

A markup language that uses tags to structure data, commonly used in enterprise systems and SOAP APIs.

<!-- XML example - User object -->
<?xml version="1.0" encoding="UTF-8"?>
<user>
  <id>123</id>
  <name>John Doe</name>
  <email>john@example.com</email>
  <age>30</age>
  <active>true</active>
  <roles>
    <role>user</role>
    <role>admin</role>
  </roles>
  <address>
    <street>123 Main St</street>
    <city>New York</city>
    <country>USA</country>
  </address>
</user>

Comparison: JSON vs XML

FeatureJSONXML
SyntaxMore conciseMore verbose
Data typesNative typesEverything is text
ArraysNative supportRequires wrapper elements
ReadabilityEasier to readMore structured
SizeSmallerLarger
ParsingFasterSlower
Use casesModern web APIsEnterprise, legacy systems

Advanced Concepts

Rate Limiting

Controlling the number of requests a client can make to an API within a specific time period.

// Rate limit headers in response
// X-RateLimit-Limit: 100
// X-RateLimit-Remaining: 95
// X-RateLimit-Reset: 1640000000
 
fetch('https://api.example.com/data')
  .then(response => {
    const limit = response.headers.get('X-RateLimit-Limit')
    const remaining = response.headers.get('X-RateLimit-Remaining')
    const reset = response.headers.get('X-RateLimit-Reset')
 
    console.log(`Limit: ${limit}, Remaining: ${remaining}`)
 
    if (response.status === 429) {
      console.error('Rate limit exceeded. Try again later.')
    }
 
    return response.json()
  })

Common rate limiting strategies:

  • Fixed window: 100 requests per hour, counter resets at hour boundary
  • Sliding window: 100 requests per rolling 60-minute period
  • Token bucket: Tokens replenish over time, requests consume tokens
  • Leaky bucket: Requests processed at steady rate

Rate limit response:

{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Please try again later.",
  "retryAfter": 3600
}

Pagination

Breaking large result sets into smaller pages for better performance and usability.

Offset-based pagination:

// Page 1: Get first 10 users
fetch('https://api.example.com/users?limit=10&offset=0')
 
// Page 2: Get next 10 users
fetch('https://api.example.com/users?limit=10&offset=10')
 
// Response structure
// {
//   "data": [...],
//   "pagination": {
//     "limit": 10,
//     "offset": 0,
//     "total": 150
//   }
// }

Cursor-based pagination:

// First page
fetch('https://api.example.com/users?limit=10')
  .then(response => response.json())
  .then(data => {
    console.log(data.users)
    const nextCursor = data.pagination.nextCursor
 
    // Next page using cursor
    if (nextCursor) {
      fetch(`https://api.example.com/users?limit=10&cursor=${nextCursor}`)
    }
  })
 
// Response structure
// {
//   "users": [...],
//   "pagination": {
//     "nextCursor": "eyJpZCI6MTB9",
//     "hasMore": true
//   }
// }

Page-based pagination:

// Page 1
fetch('https://api.example.com/users?page=1&per_page=20')
 
// Page 2
fetch('https://api.example.com/users?page=2&per_page=20')
 
// Response structure
// {
//   "data": [...],
//   "page": 1,
//   "perPage": 20,
//   "totalPages": 10,
//   "totalItems": 200
// }

Webhook

A mechanism for an API to send real-time notifications to your application when specific events occur.

// Webhook endpoint in your application
app.post('/webhooks/payment', (req, res) => {
  const event = req.body
 
  // Verify webhook signature (security)
  const signature = req.headers['x-webhook-signature']
  if (!verifySignature(event, signature)) {
    return res.status(401).send('Invalid signature')
  }
 
  // Handle the event
  switch (event.type) {
    case 'payment.succeeded':
      console.log('Payment successful:', event.data)
      // Update order status, send confirmation email, etc.
      break
 
    case 'payment.failed':
      console.log('Payment failed:', event.data)
      // Notify user, retry payment, etc.
      break
 
    default:
      console.log('Unknown event type:', event.type)
  }
 
  // Acknowledge receipt
  res.status(200).send('Webhook received')
})

Webhook payload example:

{
  "id": "evt_123456",
  "type": "payment.succeeded",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "paymentId": "pay_789",
    "amount": 99.99,
    "currency": "USD",
    "customerId": "cus_456"
  }
}

Webhooks vs Polling:

WebhookPolling
Server pushes updatesClient requests updates
Real-time notificationsDelayed by polling interval
Efficient (no unnecessary calls)Wasteful (many empty responses)
Requires public endpointWorks behind firewalls

SDK (Software Development Kit)

A collection of tools, libraries, and documentation that makes it easier to use an API in a specific programming language.

// Without SDK - raw API calls
fetch('https://api.stripe.com/v1/charges', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${apiKey}`,
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: new URLSearchParams({
    amount: '2000',
    currency: 'usd',
    source: 'tok_visa',
  }),
})
 
// With SDK - simplified interface
import Stripe from 'stripe'
const stripe = new Stripe('your-api-key')
 
const charge = await stripe.charges.create({
  amount: 2000,
  currency: 'usd',
  source: 'tok_visa',
})

Benefits of SDKs:

  • Type safety and autocomplete
  • Error handling
  • Authentication management
  • Retry logic
  • Documentation and examples
  • Language-specific best practices

GraphQL

A query language for APIs that allows clients to request exactly the data they need.

# GraphQL query - Request specific fields
query {
  user(id: "123") {
    id
    name
    email
    posts(limit: 5) {
      id
      title
      createdAt
    }
  }
}
// Response - Only requested fields returned
{
  "data": {
    "user": {
      "id": "123",
      "name": "John Doe",
      "email": "john@example.com",
      "posts": [
        {
          "id": "1",
          "title": "First Post",
          "createdAt": "2024-01-15T10:00:00Z"
        }
      ]
    }
  }
}

GraphQL mutations (modify data):

mutation {
  createUser(input: {
    name: "Jane Doe"
    email: "jane@example.com"
  }) {
    id
    name
    email
  }
}

GraphQL vs REST:

FeatureGraphQLREST
Data fetchingRequest exactly what you needFixed structure per endpoint
EndpointsSingle endpointMultiple endpoints
Over-fetchingEliminatedCommon issue
Under-fetchingEliminatedRequires multiple requests
VersioningNot typically neededCommon (v1, v2)
Learning curveSteeperGentler

Best Practices

Use HTTPS for Secure Communication

Always use HTTPS to encrypt data in transit and protect against man-in-the-middle attacks.

// ✅ Good - HTTPS
fetch('https://api.example.com/users')
 
// ❌ Bad - HTTP (insecure)
fetch('http://api.example.com/users')

Why HTTPS matters:

  • Encrypts sensitive data (passwords, tokens, personal info)
  • Prevents eavesdropping and tampering
  • Required for modern authentication methods
  • Builds user trust
  • Better SEO ranking

Implement Proper Error Handling

Provide meaningful error messages and appropriate status codes.

// Client-side error handling
async function fetchUser(userId) {
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`)
 
    if (!response.ok) {
      const error = await response.json()
      throw new Error(error.message || 'Failed to fetch user')
    }
 
    return await response.json()
  } catch (error) {
    if (error.name === 'TypeError') {
      console.error('Network error:', error)
    } else {
      console.error('API error:', error.message)
    }
    throw error
  }
}

Server-side error responses:

// Good error response
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid email address",
    "field": "email",
    "details": "Email must be a valid email address"
  }
}
 
// Include helpful information
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "User not found",
    "resourceId": "123",
    "suggestion": "Check if the user ID is correct"
  }
}

Version APIs

Use versioning to manage changes without breaking existing clients.

// URL versioning
fetch('https://api.example.com/v1/users')
fetch('https://api.example.com/v2/users')
 
// Header versioning
fetch('https://api.example.com/users', {
  headers: {
    'Accept': 'application/vnd.api.v2+json',
  },
})
 
// Query parameter versioning
fetch('https://api.example.com/users?version=2')

Versioning strategies:

  • URL versioning: /v1/users, /v2/users (most common)
  • Header versioning: Custom headers for version
  • Query parameter: ?version=2
  • Content negotiation: Accept header with media type

Document APIs Thoroughly

Provide comprehensive documentation for your API.

Essential documentation elements:

## GET /users/:id
 
Retrieve a specific user by ID.
 
### Authentication
Requires Bearer token
 
### Parameters
- `id` (path, required): User ID
 
### Response
- `200 OK`: User found
- `404 Not Found`: User doesn't exist
- `401 Unauthorized`: Missing or invalid token
 
### Example Request
```bash
curl -X GET https://api.example.com/users/123 \
  -H "Authorization: Bearer YOUR_TOKEN"

Example Response

{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com"
}

**Popular documentation tools:**
- **Swagger/OpenAPI**: Interactive API documentation
- **Postman**: API testing and documentation
- **API Blueprint**: Markdown-based documentation
- **ReadMe**: User-friendly API documentation

### Use Consistent Naming Conventions

Maintain consistent naming across your API.

```typescript
// ✅ Good - Consistent REST conventions
GET    /users           // Get all users
GET    /users/:id       // Get specific user
POST   /users           // Create user
PUT    /users/:id       // Update user
DELETE /users/:id       // Delete user

GET    /users/:id/posts // Get user's posts

// ✅ Good - Consistent JSON naming (camelCase or snake_case)
{
  "userId": 123,
  "firstName": "John",
  "lastName": "Doe",
  "createdAt": "2024-01-15T10:00:00Z"
}

// or

{
  "user_id": 123,
  "first_name": "John",
  "last_name": "Doe",
  "created_at": "2024-01-15T10:00:00Z"
}

// ❌ Bad - Inconsistent naming
{
  "userId": 123,        // camelCase
  "first_name": "John", // snake_case
  "LastName": "Doe",    // PascalCase
  "created-at": "..."   // kebab-case
}

Naming best practices:

  • Use plural nouns for collections: /users, /products
  • Use lowercase in URLs
  • Use hyphens for readability in URLs: /user-profiles
  • Choose one case style for JSON (camelCase or snake_case) and stick to it
  • Use meaningful, descriptive names
  • Avoid abbreviations unless widely understood

Additional Resources

REST API Tutorials

HTTP Status Codes Reference

OAuth 2.0 Documentation

API Design & Best Practices

Tools & Testing

  • Postman - API development and testing platform
  • Insomnia - REST and GraphQL client
  • cURL - Command-line HTTP client
  • HTTPie - User-friendly HTTP client

APIs are the foundation of modern web development. Understanding these terminologies will help you build, consume, and document APIs more effectively.