← Back to Guides

Using JSON in REST APIs: Best Practices

· Tags: json, rest-api, api-design, json-best-practices, pagination, web-development

JSON in REST APIs

JSON and REST APIs are a match made in heaven. JSON's lightweight syntax, native array support, and universal language support make it the default format for modern web APIs. But simply using JSON in your API is not enough -- following established conventions and best practices ensures your API is consistent, intuitive, and easy to integrate.

Request and Response Format

Consistent Envelope Structure

Adopt a consistent JSON envelope for all API responses. This makes client-side processing predictable and simplifies error handling.

{
  "status": "success",
  "data": {
    "user": {
      "id": 123,
      "name": "Alice",
      "email": "alice@example.com"
    }
  },
  "meta": {
    "requestId": "req-a1b2c3d4",
    "timestamp": "2026-07-19T10:30:00Z"
  }
}

Snake Case vs Camel Case

Choose one naming convention and stick with it across your entire API:

  • Camel Case (createdAt, firstName): Common in JavaScript/TypeScript ecosystems
  • Snake Case (created_at, first_name): Common in Python, Ruby, and PHP ecosystems

Whichever you choose, document it clearly and consider using a transformation layer if your backend language uses a different convention.

HTTP Status Codes with JSON

Proper HTTP status codes complement your JSON responses. Use them consistently:

| Status Code | Meaning | When to Use | |-------------|---------|-------------| | 200 OK | Success | GET, PUT, PATCH success | | 201 Created | Resource created | POST success | | 204 No Content | Deletion success | DELETE success (no JSON body) | | 400 Bad Request | Invalid JSON syntax | Malformed request body | | 401 Unauthorized | Authentication required | Missing or invalid token | | 403 Forbidden | Insufficient permissions | Valid auth but not allowed | | 404 Not Found | Resource doesn't exist | Invalid ID or path | | 422 Unprocessable Entity | Validation failure | Semantic errors in valid JSON | | 429 Too Many Requests | Rate limit hit | Client exceeding limits | | 500 Internal Server Error | Server-side failure | Unexpected errors |

Standard Error Response Format

{
  "status": "error",
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request body contains invalid fields",
    "details": [
      {
        "field": "email",
        "message": "Must be a valid email address",
        "code": "INVALID_FORMAT"
      },
      {
        "field": "age",
        "message": "Must be a positive integer",
        "code": "OUT_OF_RANGE"
      }
    ]
  }
}

Nested Resources

Representing Relationships

REST APIs frequently need to represent related resources. Here are common patterns:

Embedded (eager loading):

{
  "order": {
    "id": 5001,
    "total": 29.99,
    "customer": {
      "id": 123,
      "name": "Alice",
      "email": "alice@example.com"
    },
    "items": [
      {
        "productId": 42,
        "name": "Widget",
        "quantity": 2,
        "price": 14.99
      }
    ]
  }
}

Referenced (lazy loading) -- use IDs and provide separate endpoints:

{
  "order": {
    "id": 5001,
    "total": 29.99,
    "customerId": 123,
    "itemIds": [101, 102]
  }
}

Rule of thumb: Embed related data that is always needed together. Reference data that is retrieved conditionally or at a different time.

Pagination Patterns

When returning lists of resources, pagination is essential. Use a consistent pagination format:

Offset-Based Pagination

{
  "status": "success",
  "data": [
    { "id": 1, "name": "User 1" },
    { "id": 2, "name": "User 2" }
  ],
  "pagination": {
    "page": 1,
    "perPage": 20,
    "totalItems": 156,
    "totalPages": 8,
    "links": {
      "first": "/api/users?page=1&perPage=20",
      "prev": null,
      "next": "/api/users?page=2&perPage=20",
      "last": "/api/users?page=8&perPage=20"
    }
  }
}

Cursor-Based Pagination (Recommended for Large Datasets)

{
  "status": "success",
  "data": [
    { "id": 100, "name": "User 100" },
    { "id": 101, "name": "User 101" }
  ],
  "pagination": {
    "nextCursor": "eyJpZCI6MTAxfQ==",
    "hasMore": true
  }
}

Cursor-based pagination is more reliable for real-time data where new records could shift page boundaries.

JSON in API Requests

POST / PUT Request Bodies

Accept JSON with the Content-Type: application/json header:

{
  "title": "New Blog Post",
  "content": "This is the content...",
  "tags": ["json", "rest-api"],
  "published": false
}

Partial Updates with PATCH

Use PATCH for partial updates. Accept only the fields that should change:

// PATCH /api/users/123
{
  "email": "newemail@example.com"
}

Filtering, Sorting, and Searching

Use query parameters for data manipulation, keeping the JSON body clean:

GET /api/users?filter[role]=admin&sort=-createdAt&search=alice
{
  "status": "success",
  "data": [ /* filtered, sorted results */ ]
}

Rate Limiting

Include rate limit information in response headers and optionally in the JSON body:

{
  "status": "error",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests. Please try again later."
  },
  "meta": {
    "rateLimit": {
      "limit": 100,
      "remaining": 0,
      "resetAt": "2026-07-19T11:00:00Z"
    }
  }
}

JSON Best Practices Checklist

  • [ ] Use consistent key naming (camelCase or snake_case throughout)
  • [ ] Return appropriate HTTP status codes with every response
  • [ ] Include a consistent error format with machine-readable error codes
  • [ ] Paginate list endpoints with a standardized pagination object
  • [ ] Use JSON Schema to document and validate request/response structures
  • [ ] Set Content-Type: application/json on all JSON endpoints
  • [ ] Compress JSON responses with gzip or brotli in production
  • [ ] Enforce maximum payload size limits (e.g., 1MB default)
  • [ ] Use HTTPS to encrypt JSON data in transit
  • [ ] Structure error details to help clients debug without exposing internals

Validating Your API JSON

Run your API responses through a JSON validator to catch formatting errors before they reach clients. Consistent, valid JSON responses make your API reliable and developer-friendly. Use our JSON Formatter & Validator tool to test your payloads during development.