home / skills / yanko-belov / code-craft / rest-conventions

rest-conventions skill

/skills/rest-conventions

This skill helps you design RESTful endpoints by enforcing correct HTTP methods, avoiding verbs in URLs, and promoting semantic, cache-friendly APIs.

npx playbooks add skill yanko-belov/code-craft --skill rest-conventions

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.6 KB
---
name: rest-conventions
description: Use when designing API endpoints. Use when using wrong HTTP methods. Use when POST is used for reads.
---

# REST Conventions

## Overview

**Use HTTP methods correctly. GET for reads. POST for creates. PUT/PATCH for updates. DELETE for deletes.**

REST conventions exist for caching, bookmarking, and semantic clarity. Violating them breaks HTTP infrastructure.

## When to Use

- Designing any HTTP API endpoint
- Asked to use POST for fetching data
- Naming endpoints with verbs
- Unsure which HTTP method to use

## The Iron Rule

```
NEVER use POST for read operations. NEVER put verbs in URLs.
```

**No exceptions:**
- Not for "it's simpler"
- Not for "we need a body"
- Not for "that's how we do it"
- Not for "GET URLs are limited"

## Detection: REST Violation Smell

If endpoints have verbs or wrong methods, STOP:

```typescript
// ❌ VIOLATIONS
POST /getOrders              // POST for read
POST /users/create           // Verb in URL
GET /deleteUser?id=123       // GET for delete
POST /api/fetchProducts      // Verb + wrong method
```

## The Correct Pattern: RESTful Endpoints

```typescript
// ✅ CORRECT: RESTful design

// Collections: plural nouns
GET    /users          // List users
POST   /users          // Create user
GET    /users/:id      // Get one user
PUT    /users/:id      // Replace user
PATCH  /users/:id      // Update user partially
DELETE /users/:id      // Delete user

// Nested resources
GET    /users/:id/orders     // User's orders
POST   /users/:id/orders     // Create order for user
GET    /orders/:id           // Get specific order

// Filtering via query params
GET    /orders?status=pending&userId=123
GET    /products?category=electronics&limit=20
```

## HTTP Methods Semantics

| Method | Use For | Idempotent | Safe |
|--------|---------|------------|------|
| GET | Read/fetch | Yes | Yes |
| POST | Create | No | No |
| PUT | Replace entirely | Yes | No |
| PATCH | Partial update | Yes | No |
| DELETE | Remove | Yes | No |

**Safe**: Doesn't modify state
**Idempotent**: Same result if called multiple times

## Common Patterns

### Filtering
```typescript
GET /orders?status=pending
GET /products?minPrice=10&maxPrice=100
GET /users?role=admin&active=true
```

### Pagination
```typescript
GET /orders?page=2&limit=20
GET /orders?cursor=abc123&limit=20
```

### Sorting
```typescript
GET /products?sort=price:asc
GET /users?sort=createdAt:desc
```

### Actions on Resources
For actions that don't fit CRUD, use sub-resources:
```typescript
POST /orders/:id/cancel     // Action on order
POST /users/:id/verify      // Action on user
POST /payments/:id/refund   // Action on payment
```

## Pressure Resistance Protocol

### 1. "POST Is Simpler"
**Pressure:** "Just use POST for everything"

**Response:** POST requests aren't cacheable and break HTTP semantics.

**Action:** Use the correct method. It's the same amount of code.

### 2. "We Need a Request Body"
**Pressure:** "GET can't have a body, so we use POST"

**Response:** Use query parameters for filtering. Bodies on GET are non-standard.

**Action:** `GET /orders?userId=123` instead of `POST /getOrders`

### 3. "GET URLs Are Limited"
**Pressure:** "Query string might get too long"

**Response:** If your query is that complex, you might need a search endpoint. Or paginate.

**Action:** For complex searches, `POST /search` is acceptable as an exception.

### 4. "That's How We Do It"
**Pressure:** "Our existing API uses POST for reads"

**Response:** New endpoints should follow conventions. Migrate old ones gradually.

**Action:** Follow REST for new endpoints. Document inconsistencies.

## Red Flags - STOP and Reconsider

- Verbs in URLs (`/getUser`, `/createOrder`)
- POST for fetching data
- GET for mutations
- Action names instead of resources
- Inconsistent URL structure

**All of these mean: Redesign the endpoint.**

## Quick Reference

| Bad | Good |
|-----|------|
| `POST /getOrders` | `GET /orders` |
| `POST /createUser` | `POST /users` |
| `GET /deleteUser/123` | `DELETE /users/123` |
| `POST /updateProduct` | `PATCH /products/:id` |
| `POST /fetchByFilter` | `GET /items?filter=x` |

## Common Rationalizations (All Invalid)

| Excuse | Reality |
|--------|---------|
| "POST is simpler" | Same code, better semantics. |
| "Need request body" | Use query parameters. |
| "GET URLs too long" | Paginate or use search endpoint. |
| "That's how we do it" | New code should be correct. |
| "Doesn't matter" | Caching, bookmarking, tools all depend on it. |

## The Bottom Line

**Nouns in URLs. Correct HTTP methods. Query params for filtering.**

GET reads. POST creates. PUT/PATCH updates. DELETE removes. URLs are nouns (resources), not verbs (actions).

Overview

This skill guides API designers to follow REST conventions when naming endpoints and choosing HTTP methods. It enforces using GET for reads, POST for creates, PUT/PATCH for updates, and DELETE for removals to preserve caching, tooling, and semantic correctness. Follow these rules to avoid broken HTTP behavior and hard-to-maintain APIs.

How this skill works

The skill reviews endpoint definitions and flags violations such as verbs in URLs or incorrect method use (e.g., POST for reads, GET for deletes). It recommends converting verbful routes into resource-based paths, moving filters to query parameters, and using action sub-resources for non-CRUD operations. It also provides patterns for pagination, sorting, and nested resources.

When to use it

  • Designing any HTTP API endpoints or routes
  • When someone suggests using POST to fetch data
  • When unsure which HTTP method suits an operation
  • Reviewing existing APIs for consistency and caching readiness
  • Naming or refactoring endpoints to follow best practices

Best practices

  • Use plural nouns for collections (e.g., /users, /orders) and resource IDs for single items (/users/:id).
  • Use GET for safe reads; POST to create; PUT/PATCH for updates; DELETE to remove. Maintain idempotency expectations.
  • Put filters, sorting, and pagination in query parameters (e.g., /orders?status=pending&page=2).
  • Avoid verbs in URLs—use sub-resources or action endpoints for non-CRUD processes (e.g., POST /orders/:id/cancel).
  • For very complex searches, provide a dedicated POST /search endpoint rather than using POST for ordinary reads. Document any legacy exceptions and migrate gradually.

Example use cases

  • Converting POST /getOrders to GET /orders?userId=123 for caching and bookmarking
  • Replacing POST /users/create with POST /users when creating new accounts
  • Refactoring GET /deleteUser?id=123 into DELETE /users/123 to honor HTTP semantics
  • Creating nested resource routes like GET /users/:id/orders and POST /users/:id/orders to model relationships
  • Adding pagination: GET /products?page=2&limit=20 instead of embedding filters in request bodies

FAQ

Can I ever use POST for read-like operations?

Only rarely: use POST /search for very complex queries that exceed URL limits. For normal filtering and retrieval, use GET with query parameters.

What if my team already uses POST for reads?

Start applying correct conventions for new endpoints and plan a gradual migration. Document exceptions and prioritize endpoints that benefit most from caching and tooling.