
Rest Api Design
- 1.8k installs
- 305 repo stars
- Updated March 4, 2026
- aj-geddes/useful-ai-prompts
rest-api-design is an agent skill for
About
The rest-api-design skill documents agent workflows from the repository SKILL.md. It covers when to Use when-to-use. Key workflows include quick Start quick-start. Design REST APIs that are intuitive, consistent, and follow industry best practices for resource-oriented architecture. Developers invoke rest-api-design when the task matches the triggers and reference files in SKILL.md for grounded, stepwise execution. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation. Reference files and progressive disclosure keep context focused while preserving concrete commands, configuration fields, and validation checks copied from the upstream documentation.
- When to Use when-to-use
- Quick Start quick-start
- Reference Guides reference-guides
- Best Practices best-practices
- Designing new RESTful APIs
Rest Api Design by the numbers
- 1,828 all-time installs (skills.sh)
- +54 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #304 of 2,203 Security skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
rest-api-design capabilities & compatibility
- Capabilities
- when to use when to use · quick start quick start · reference guides reference guides · best practices best practices · designing new restful apis
- Use cases
- security audit · testing · debugging
What rest-api-design says it does
Design RESTful APIs following best practices for resource modeling, HTTP
methods, status codes, versioning, and documentation. Use when creating new
npx skills add https://github.com/aj-geddes/useful-ai-prompts --skill rest-api-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.8k |
|---|---|
| repo stars | ★ 305 |
| Security audit | 3 / 3 scanners passed |
| Last updated | March 4, 2026 |
| Repository | aj-geddes/useful-ai-prompts ↗ |
What problem does rest-api-design solve for developers using the documented workflows?
The rest-api-design skill documents agent workflows from the repository SKILL.md. It covers when to Use when-to-use. Key workflows include quick Start quick-start. Design REST APIs that are intuitive
Who is it for?
Developers working with rest-api-design patterns described in the skill documentation.
Skip if: Skip when docs are empty or the task is outside the skill documented scope.
When should I use this skill?
Use when
What you get
Actionable rest-api-design guidance grounded in SKILL.md workflows and reference files.
- Express route handlers
- pagination response objects
- validation and error-handling snippets
By the numbers
- Includes a complete Express.js pagination example with page, limit, offset, and totalPages fields
Files
REST API Design
Table of Contents
Overview
Design REST APIs that are intuitive, consistent, and follow industry best practices for resource-oriented architecture.
When to Use
- Designing new RESTful APIs
- Creating endpoint structures
- Defining request/response formats
- Implementing API versioning
- Documenting API specifications
- Refactoring existing APIs
Quick Start
Minimal working example:
✅ Good Resource Names (Nouns, Plural)
GET /api/users
GET /api/users/123
GET /api/users/123/orders
POST /api/products
DELETE /api/products/456
❌ Bad Resource Names (Verbs, Inconsistent)
GET /api/getUsers
POST /api/createProduct
GET /api/user/123 (inconsistent singular/plural)Reference Guides
Detailed implementations in the references/ directory:
| Guide | Contents |
|---|---|
| Resource Naming | Resource Naming, HTTP Methods & Operations |
| Request Examples | Request Examples |
| Query Parameters | Query Parameters |
| Response Formats | Response Formats |
| HTTP Status Codes | HTTP Status Codes, API Versioning, Authentication & Security, Rate Limiting Headers |
| OpenAPI Documentation | OpenAPI Documentation |
| Complete Example: Express.js | const express = require("express"); |
Best Practices
✅ DO
- Use nouns for resources, not verbs
- Use plural names for collections
- Be consistent with naming conventions
- Return appropriate HTTP status codes
- Include pagination for collections
- Provide filtering and sorting options
- Version your API
- Document thoroughly with OpenAPI
- Use HTTPS
- Implement rate limiting
- Provide clear error messages
- Use ISO 8601 for dates
❌ DON'T
- Use verbs in endpoint names
- Return 200 for errors
- Expose internal IDs unnecessarily
- Over-nest resources (max 2 levels)
- Use inconsistent naming
- Forget authentication
- Return sensitive data
- Break backward compatibility without versioning
Complete Example: Express.js
const express = require("express");
const app = express();
app.use(express.json());
// List users with pagination
app.get("/api/v1/users", async (req, res) => {
try {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 20;
const offset = (page - 1) * limit;
const users = await User.findAndCountAll({
limit,
offset,
attributes: ["id", "email", "firstName", "lastName"],
});
res.json({
data: users.rows,
pagination: {
page,
limit,
total: users.count,
totalPages: Math.ceil(users.count / limit),
},
});
} catch (error) {
res.status(500).json({
error: {
code: "INTERNAL_ERROR",
message: "An error occurred while fetching users",
},
});
}
});
// Get single user
app.get("/api/v1/users/:id", async (req, res) => {
try {
const user = await User.findByPk(req.params.id);
if (!user) {
return res.status(404).json({
error: {
code: "NOT_FOUND",
message: "User not found",
},
});
}
res.json({ data: user });
} catch (error) {
res.status(500).json({
error: {
code: "INTERNAL_ERROR",
message: "An error occurred",
},
});
}
});
// Create user
app.post("/api/v1/users", async (req, res) => {
try {
const { email, firstName, lastName } = req.body;
// Validation
if (!email || !firstName || !lastName) {
return res.status(400).json({
error: {
code: "VALIDATION_ERROR",
message: "Missing required fields",
details: [
!email && { field: "email", message: "Email is required" },
!firstName && {
field: "firstName",
message: "First name is required",
},
!lastName && {
field: "lastName",
message: "Last name is required",
},
].filter(Boolean),
},
});
}
const user = await User.create({ email, firstName, lastName });
res.status(201).location(`/api/v1/users/${user.id}`).json({ data: user });
} catch (error) {
if (error.name === "SequelizeUniqueConstraintError") {
return res.status(409).json({
error: {
code: "CONFLICT",
message: "Email already exists",
},
});
}
res.status(500).json({
error: {
code: "INTERNAL_ERROR",
message: "An error occurred",
},
});
}
});
app.listen(3000);HTTP Status Codes
HTTP Status Codes
Success:
200 OK - Successful GET, PATCH, DELETE
201 Created - Successful POST (resource created)
204 No Content - Successful DELETE (no response body)
Client Errors:
400 Bad Request - Invalid request format/data
401 Unauthorized - Missing or invalid authentication
403 Forbidden - Authenticated but not authorized
404 Not Found - Resource doesn't exist
409 Conflict - Resource conflict (e.g., duplicate email)
422 Unprocessable - Validation errors
429 Too Many Requests - Rate limit exceeded
Server Errors:
500 Internal Server Error - Generic server error
503 Service Unavailable - Temporary unavailabilityAPI Versioning
# URL Path Versioning (Recommended)
GET /api/v1/users
GET /api/v2/users
# Header Versioning
GET /api/users
Accept: application/vnd.myapi.v1+json
# Query Parameter (Not recommended)
GET /api/users?version=1Authentication & Security
# JWT Bearer Token
GET /api/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# API Key
GET /api/users
X-API-Key: your-api-key-here
# Always use HTTPS in production
https://api.example.com/v1/usersRate Limiting Headers
HTTP/1.1 200 OK
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 995
X-RateLimit-Reset: 1642262400OpenAPI Documentation
OpenAPI Documentation
openapi: 3.0.0
info:
title: User API
version: 1.0.0
description: User management API
paths:
/users:
get:
summary: List all users
parameters:
- name: page
in: query
schema:
type: integer
default: 1
- name: limit
in: query
schema:
type: integer
default: 20
responses:
"200":
description: Successful response
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: "#/components/schemas/User"
post:
summary: Create a new user
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UserInput"
responses:
"201":
description: User created
content:
application/json:
schema:
$ref: "#/components/schemas/User"
"400":
description: Invalid input
"409":
description: Email already exists
components:
schemas:
User:
type: object
properties:
id:
type: string
email:
type: string
format: email
firstName:
type: string
lastName:
type: string
createdAt:
type: string
format: date-time
UserInput:
type: object
required:
- email
- firstName
- lastName
properties:
email:
type: string
format: email
firstName:
type: string
lastName:
type: stringQuery Parameters
Query Parameters
# Filtering
GET /api/products?category=electronics&inStock=true
# Sorting
GET /api/users?sort=lastName,asc
# Pagination
GET /api/users?page=2&limit=20
# Field Selection
GET /api/users?fields=id,email,firstName
# Search
GET /api/products?q=laptop
# Multiple filters combined
GET /api/orders?status=pending&customer=123&sort=createdAt,desc&limit=50Request Examples
Request Examples
Creating a Resource
POST /api/users
Content-Type: application/json
{
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "admin"
}
Response: 201 Created
Location: /api/users/789
{
"id": "789",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"role": "admin",
"createdAt": "2025-01-15T10:30:00Z",
"updatedAt": "2025-01-15T10:30:00Z"
}Updating a Resource
PATCH /api/users/789
Content-Type: application/json
{
"firstName": "Jonathan"
}
Response: 200 OK
{
"id": "789",
"email": "john@example.com",
"firstName": "Jonathan",
"lastName": "Doe",
"role": "admin",
"updatedAt": "2025-01-15T11:00:00Z"
}Resource Naming
Resource Naming
✅ Good Resource Names (Nouns, Plural)
GET /api/users
GET /api/users/123
GET /api/users/123/orders
POST /api/products
DELETE /api/products/456
❌ Bad Resource Names (Verbs, Inconsistent)
GET /api/getUsers
POST /api/createProduct
GET /api/user/123 (inconsistent singular/plural)HTTP Methods & Operations
# CRUD Operations
GET /api/users # List all users (Read collection)
GET /api/users/123 # Get specific user (Read single)
POST /api/users # Create new user (Create)
PUT /api/users/123 # Replace user completely (Update)
PATCH /api/users/123 # Partial update user (Partial update)
DELETE /api/users/123 # Delete user (Delete)
# Nested Resources
GET /api/users/123/orders # Get user's orders
POST /api/users/123/orders # Create order for user
GET /api/users/123/orders/456 # Get specific orderResponse Formats
Response Formats
Success Response
{
"data": {
"id": "123",
"email": "user@example.com",
"firstName": "John"
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"version": "1.0"
}
}Collection Response with Pagination
{
"data": [
{ "id": "1", "name": "Product 1" },
{ "id": "2", "name": "Product 2" }
],
"pagination": {
"page": 2,
"limit": 20,
"total": 145,
"totalPages": 8,
"hasNext": true,
"hasPrev": true
},
"links": {
"self": "/api/products?page=2&limit=20",
"first": "/api/products?page=1&limit=20",
"prev": "/api/products?page=1&limit=20",
"next": "/api/products?page=3&limit=20",
"last": "/api/products?page=8&limit=20"
}
}Error Response
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid input data",
"details": [
{
"field": "email",
"message": "Email format is invalid"
},
{
"field": "age",
"message": "Must be at least 18"
}
]
},
"meta": {
"timestamp": "2025-01-15T10:30:00Z",
"requestId": "abc-123-def"
}
}#!/bin/bash
# validate-api.sh - Validate API specification
# Usage: ./validate-api.sh <openapi_spec>
set -euo pipefail
SPEC_FILE="${{1:?Usage: $0 <openapi_spec>}}"
echo "Validating API spec: $SPEC_FILE"
# TODO: Add API validation
# - Validate OpenAPI/Swagger syntax
# - Check endpoint naming conventions
# - Verify response schemas
# - Check for required headers
# - Validate authentication definitions
echo "API validation complete."
# API Endpoint Scaffold
# TODO: Customize for your API framework
openapi: "3.0.3"
info:
title: "API Service"
version: "1.0.0"
paths:
/api/v1/resource:
get:
summary: "List resources"
# TODO: Define parameters and responses
responses:
"200":
description: "Success"
post:
summary: "Create resource"
# TODO: Define request body and responses
responses:
"201":
description: "Created"
Related skills
How it compares
Choose rest-api-design when you need Express route boilerplate and REST conventions; prefer OpenAPI-first generators when schema-driven codegen is already your source of truth.
FAQ
Who is rest-api-design for?
Developers and software engineers working with rest-api-design patterns described in the skill documentation.
When should I use rest-api-design?
When .
Is rest-api-design safe to install?
Review the Security Audits panel on this page before installing in production.