REST APIs communicate almost exclusively in JSON. Understanding the patterns, conventions, and common structures makes building and consuming APIs significantly faster.

Anatomy of a JSON API request

POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Accept: application/json

{
  "name": "Alice Johnson",
  "email": "alice@example.com",
  "role": "user"
}

Standard response structure

// Success response (201 Created)
{
  "data": {
    "id": "usr_abc123",
    "name": "Alice Johnson",
    "email": "alice@example.com",
    "createdAt": "2023-11-14T22:13:20Z"
  },
  "meta": {
    "requestId": "req_xyz789"
  }
}

// Error response (422 Unprocessable Entity)
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Validation failed",
    "details": [
      { "field": "email", "message": "Invalid email format" }
    ]
  }
}

HTTP methods and their JSON patterns

// GET — retrieve data (no body)
GET /api/v1/users/123
Response: { "data": { "id": "123", "name": "Alice" } }

// POST — create resource
POST /api/v1/users
Body: { "name": "Alice", "email": "alice@example.com" }
Response (201): { "data": { "id": "usr_new", ...created fields } }

// PUT — replace entire resource
PUT /api/v1/users/123
Body: { "name": "Alice Updated", "email": "alice@example.com" }

// PATCH — partial update
PATCH /api/v1/users/123
Body: { "name": "Alice Updated" }  // only changed fields

// DELETE — remove resource (usually no body)
DELETE /api/v1/users/123
Response (204): no body

Pagination JSON pattern

GET /api/v1/users?page=2&per_page=20

{
  "data": [...20 users...],
  "pagination": {
    "page": 2,
    "per_page": 20,
    "total": 150,
    "total_pages": 8,
    "has_next": true,
    "has_prev": true,
    "next_url": "/api/v1/users?page=3&per_page=20"
  }
}

Consuming a REST API in JavaScript

class APIClient {
  constructor(baseURL, token) {
    this.baseURL = baseURL;
    this.headers = {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    };
  }

  async get(path) {
    const res = await fetch(this.baseURL + path, { headers: this.headers });
    if (!res.ok) throw await this.parseError(res);
    return res.json();
  }

  async post(path, body) {
    const res = await fetch(this.baseURL + path, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify(body)
    });
    if (!res.ok) throw await this.parseError(res);
    return res.json();
  }

  async parseError(res) {
    const json = await res.json().catch(() => ({}));
    return new Error(json.error?.message || `HTTP ${res.status}`);
  }
}

const client = new APIClient('https://api.example.com', token);
const { data: user } = await client.get('/v1/users/123');
const { data: newUser } = await client.post('/v1/users', { name: 'Alice' });

Try it free — JSON Formatter

Inspect and format your API responses instantly.

Open tool →