Skill Featured

Design REST APIs with Best Practices

Skill for REST API design - resource URIs, HTTP methods and status codes, OpenAPI specs, and security headers.

Works with github

Maintainer of this project? Claim this page to edit the listing.


91
Spark score
out of 100
Status Verified Official
Updated 7 months ago
Version 1.0.0
Models

Add to Favorites

Why it matters

Design robust, scalable, and maintainable RESTful APIs that adhere to industry standards. Ensure your APIs are well-structured, secure, and easy to integrate.

Outcomes

What it gets done

01

Define resource-based URIs and leverage HTTP methods correctly.

02

Implement versioning strategies (URL path, header, or query parameters).

03

Structure request and response bodies for clarity and consistency.

04

Incorporate security best practices and error handling mechanisms.

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/vb-rest-api-designer | bash

Overview

REST API Designer

A skill for REST API design - resource-based URI structure, HTTP methods and status codes, versioning, an OpenAPI 3.0.3 specification example, and security, rate-limiting, and caching headers. Use it for RESTful HTTP API design and documentation, not GraphQL or gRPC API design.

What it does

This skill designs well-structured, scalable REST APIs - resource-based URI design, HTTP method and status-code conventions, versioning strategy, request/response structure, security, and OpenAPI documentation. Resource-based design favors nouns over verbs and hierarchical URIs (GET /api/v1/users/123/orders/456 over GET /api/v1/getUserOrder/123/456), with consistent plural-noun collection naming, filtering and pagination query parameters (?page=2&limit=20&sort=created_at:desc), and URL-path versioning (/api/v1/users, /api/v2/users) as the recommended strategy over header or query-parameter versioning.

HTTP methods map to specific status codes: GET returns 200/404, POST returns 201/400, PUT returns 200/201/404, and PATCH/DELETE return 200/204/404. Response structure wraps data in a data envelope with links and meta (version, timestamp, or pagination totals), while errors follow a structured format:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "Email format is invalid"
      }
    ]
  },
  "meta": {
    "request_id": "req_123456789",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}

Security guidance covers Bearer-token authentication as the recommended pattern (versus API keys or Basic Auth over HTTPS only), and required security headers (X-Content-Type-Options: nosniff, X-Frame-Options: DENY, X-XSS-Protection, Strict-Transport-Security). An OpenAPI 3.0.3 specification example documents a /users GET (paginated, capped at a maximum limit of 100) and POST endpoint with request/response schemas and a Bearer JWT security scheme. Further best practices cover content negotiation (Content-Type and Accept headers, supporting JSON and XML), rate-limiting headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, a 429 response with retry_after), caching headers (Cache-Control, ETag, Last-Modified, conditional requests via If-None-Match/If-Modified-Since), and documentation/testing practices - comprehensive docs with request/response samples, /health and /status endpoints, consistent error codes, and correlation IDs for logging.

Authentication-header examples show the concrete format for each scheme: Authorization: Bearer eyJhbGci... for Bearer tokens, X-API-Key: your-api-key-here for API keys, and Authorization: Basic dXNlcjpwYXNz for Basic Auth (flagged HTTPS-only). Request-body examples show a nested POST /api/v1/users payload with a user object carrying email, first_name, last_name, and a preferences sub-object, and a PATCH example updating only first_name and preferences.newsletter to illustrate partial updates.

When to use - and when NOT to

Use it when designing or reviewing a REST API's resource structure, versioning, request/response format, security headers, rate limiting, caching, or OpenAPI specification. It is not a GraphQL or gRPC API-design guide - it is scoped specifically to RESTful HTTP API conventions.

Inputs and outputs

Given an API domain and its resources, it produces resource URI structures and a collection-response shape wrapping a data array alongside meta totals (total, page, per_page, total_pages) and links for self/next/last pagination, plus the security, rate-limiting, and caching headers to apply.

Integrations

The OpenAPI 3.0.3 example reuses schemas via $ref components (UserListResponse, CreateUserRequest) rather than inlining them per endpoint, and declares its Bearer scheme under securitySchemes as an HTTP bearer scheme with bearerFormat: JWT - letting the same schema and security definitions be referenced across multiple endpoints in one spec.

Who it's for

Backend and API developers designing or documenting a RESTful HTTP API.

Source README

REST API Designer Expert

You are an expert in REST API design with deep knowledge of HTTP protocols, RESTful principles, API architecture patterns, and modern web service best practices. You excel at creating well-structured, scalable, and maintainable API designs that follow industry standards and conventions.

Core REST Principles

Resource-Based Design

  • Design around resources (nouns), not actions (verbs)
  • Use hierarchical URI structures to represent relationships
  • Apply consistent naming conventions (plural nouns for collections)
Good:
GET /api/v1/users/123/orders/456
POST /api/v1/products

Bad:
GET /api/v1/getUserOrder/123/456
POST /api/v1/createProduct

HTTP Methods and Status Codes

  • GET: Retrieve resources (idempotent, safe)
  • POST: Create new resources or non-idempotent operations
  • PUT: Create or completely replace resources (idempotent)
  • PATCH: Partial updates (not necessarily idempotent)
  • DELETE: Remove resources (idempotent)
Resource Operations:
GET /users           → 200 OK, 404 Not Found
POST /users          → 201 Created, 400 Bad Request
GET /users/123       → 200 OK, 404 Not Found
PUT /users/123       → 200 OK, 201 Created, 404 Not Found
PATCH /users/123     → 200 OK, 204 No Content, 404 Not Found
DELETE /users/123    → 200 OK, 204 No Content, 404 Not Found

API Structure and Versioning

URI Design Patterns

Base URI: https://api.example.com/v1

Collections and Resources:
/users                    # Collection of users
/users/123               # Specific user
/users/123/orders        # User's orders (sub-collection)
/users/123/orders/456    # Specific order for user

Filtering and Pagination:
/users?status=active&role=admin
/users?page=2&limit=20&sort=created_at:desc
/products?category=electronics&price_min=100&price_max=500

Versioning Strategy

URL Path Versioning (Recommended):
/api/v1/users
/api/v2/users

Header Versioning:
GET /api/users
Accept: application/vnd.api+json;version=1

Query Parameter (Less preferred):
/api/users?version=1

Request and Response Design

Request Body Structure

// POST /api/v1/users
{
  "user": {
    "email": "user@example.com",
    "first_name": "John",
    "last_name": "Doe",
    "preferences": {
      "newsletter": true,
      "notifications": false
    }
  }
}

// PATCH /api/v1/users/123
{
  "user": {
    "first_name": "Jane",
    "preferences": {
      "newsletter": false
    }
  }
}

Response Structure

// Success Response (200 OK)
{
  "data": {
    "id": 123,
    "email": "user@example.com",
    "first_name": "John",
    "last_name": "Doe",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z",
    "links": {
      "self": "/api/v1/users/123",
      "orders": "/api/v1/users/123/orders"
    }
  },
  "meta": {
    "version": "1.0",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}

// Collection Response
{
  "data": [...],
  "meta": {
    "total": 150,
    "page": 1,
    "per_page": 20,
    "total_pages": 8
  },
  "links": {
    "self": "/api/v1/users?page=1",
    "next": "/api/v1/users?page=2",
    "last": "/api/v1/users?page=8"
  }
}

Error Response Structure

// 400 Bad Request
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "Email format is invalid"
      },
      {
        "field": "password",
        "code": "TOO_SHORT",
        "message": "Password must be at least 8 characters"
      }
    ]
  },
  "meta": {
    "request_id": "req_123456789",
    "timestamp": "2024-01-15T10:30:00Z"
  }
}

Security and Authentication

Authentication Patterns

Bearer Token (Recommended):
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

API Key:
X-API-Key: your-api-key-here

Basic Auth (HTTPS only):
Authorization: Basic dXNlcjpwYXNz

Security Headers

Required Security Headers:
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains

OpenAPI Specification Example

openapi: 3.0.3
info:
  title: User Management API
  version: 1.0.0
  description: RESTful API for managing users
servers:
  - url: https://api.example.com/v1
paths:
  /users:
    get:
      summary: List users
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 20
            maximum: 100
      responses:
        '200':
          description: Users retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserListResponse'
    post:
      summary: Create user
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: User created successfully
        '400':
          description: Validation error
components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
        email:
          type: string
          format: email
        first_name:
          type: string
        created_at:
          type: string
          format: date-time
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

Best Practices

Content Negotiation

  • Always specify Content-Type in requests and responses
  • Support multiple formats when appropriate (JSON, XML)
  • Use Accept headers for client preferences

Rate Limiting

Rate Limit Headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200

Response when exceeded (429 Too Many Requests):
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again later.",
    "retry_after": 3600
  }
}

Caching Strategy

Cache Headers:
Cache-Control: public, max-age=3600
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 15 Jan 2024 10:30:00 GMT

Conditional Requests:
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If-Modified-Since: Wed, 15 Jan 2024 10:30:00 GMT

Documentation and Testing

  • Provide comprehensive API documentation with examples
  • Include request/response samples for all endpoints
  • Implement health check endpoints (/health, /status)
  • Use consistent error codes and messages across all endpoints
  • Implement proper logging with correlation IDs for debugging

FAQ

Common questions

Discussion

Questions & comments · 0

Sign In Sign in to leave a comment.