Claude
Skill
rest-ops
Quick reference for RESTful API design patterns, HTTP semantics, caching, and rate limiting. Triggers on: rest api, http methods, status codes, api design, endpoint design, api versioning, rate limiting, caching headers.
Virus-scanned
Reviewed automatically before listing.
Download
0xdarkmatter-claude-mods-skills_rest-ops-3dfaf0b.zip · 8 KB
Install
skills CLI
npx skills add https://github.com/0xDarkMatter/claude-mods/tree/main/skills/rest-ops
Claude Code
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install 0xdarkmatter-claude-mods@llmmart
Git
git clone https://github.com/0xDarkMatter/claude-mods.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole 0xdarkmatter/claude-mods collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
REST Patterns
Quick reference for RESTful API design patterns and HTTP semantics.
HTTP Methods
| Method | Purpose | Idempotent | Cacheable |
|---|---|---|---|
| GET | Retrieve resource(s) | Yes | Yes |
| POST | Create new resource | No | No |
| PUT | Replace entire resource | Yes | No |
| PATCH | Partial update | Maybe | No |
| DELETE | Remove resource | Yes | No |
Essential Status Codes
| Code | Name | Use |
|---|---|---|
| 200 | OK | Success with body |
| 201 | Created | POST success (add Location header) |
| 204 | No Content | Success, no body |
| 400 | Bad Request | Invalid syntax |
| 401 | Unauthorized | Not authenticated |
| 403 | Forbidden | Not authorized |
| 404 | Not Found | Resource doesn't exist |
| 422 | Unprocessable | Validation error |
| 429 | Too Many Requests | Rate limited |
| 500 | Server Error | Internal failure |
Resource Design
GET /users # List
POST /users # Create
GET /users/{id} # Get one
PUT /users/{id} # Replace
PATCH /users/{id} # Update
DELETE /users/{id} # Delete
# Query parameters
GET /users?page=2&limit=20 # Pagination
GET /users?sort=created_at:desc # Sorting
GET /users?role=admin # Filtering
Security Checklist
- HTTPS/TLS only
- OAuth 2.0 or JWT for auth
- Validate all inputs
- Rate limit per client
- CORS headers configured
- No sensitive data in URLs
- Use
no-storefor sensitive responses
Common Mistakes
| Mistake | Fix |
|---|---|
| Verbs in URLs | /getUsers → /users |
| Deep nesting | Flatten or use query params |
| 200 for errors | Use proper 4xx/5xx |
| No pagination | Always paginate collections |
| Missing rate limits | Protect against abuse |
Quick Reference
| Task | Pattern |
|---|---|
| Paginate | ?page=2&limit=20 |
| Sort | ?sort=field:asc |
| Filter | ?status=active |
| Sparse fields | ?fields=id,name |
| Include related | ?include=orders |
When to Use
- Designing new API endpoints
- Choosing HTTP methods and status codes
- Implementing caching headers
- Setting up rate limiting
- Structuring error responses
Additional Resources
For detailed patterns, load:
./references/status-codes.md- Complete status code reference with examples./references/caching-patterns.md- Cache-Control, ETag, CDN patterns./references/rate-limiting.md- Rate limiting strategies and headers./references/response-formats.md- Errors, versioning, bulk ops, HATEOAS
Files (claude-mods)
-
assets
-
.gitkeep 0 B · in bundle
-
-
references
-
caching-patterns.md 3.4 KB
# Caching Patterns HTTP caching strategies for REST APIs. ## Response Headers ### Cache-Control ```http # Cache for 1 hour Cache-Control: max-age=3600 # Cache, but always revalidate Cache-Control: max-age=0, must-revalidate # Never cache (sensitive data) Cache-Control: no-store # Browser only, not CDN Cache-Control: private, max-age=600 # Shared/CDN caching Cache-Control: public, max-age=3600 # Stale content while revalidating Cache-Control: max-age=3600, stale-while-revalidate=60 ``` ### Validation Headers ```http # Content fingerprint ETag: "abc123" ETag: W/"abc123" # Weak ETag (semantic equivalence) # Last modification time Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT ``` ## Request Headers ### Conditional Requests ```http # Validate ETag If-None-Match: "abc123" # Validate last modified If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT # Only update if ETag matches (optimistic locking) If-Match: "abc123" ``` ### Bypass Cache ```http # Force revalidation Cache-Control: no-cache # Bypass entirely (use sparingly) Cache-Control: no-store Pragma: no-cache ``` ## Caching Strategies by Resource | Resource Type | Strategy | Headers | |---------------|----------|---------| | Static assets (JS, CSS) | Long-lived | `max-age=31536000, immutable` | | Versioned assets | Permanent | `max-age=31536000` with hash in filename | | API responses | Short/revalidate | `max-age=60, must-revalidate` | | User-specific data | Private | `private, max-age=0` | | Sensitive data | Never cache | `no-store` | | Public lists | Shared | `public, max-age=300` | | Search results | Short-lived | `max-age=60` | ## ETag Workflow ### Initial Request ```http GET /users/123 → 200 OK → ETag: "v1-abc123" → Cache-Control: max-age=60 → {"id": 123, "name": "Alice", "updated_at": "..."} ``` ### Revalidation (Cache Valid) ```http GET /users/123 If-None-Match: "v1-abc123" → 304 Not Modified (No body, client uses cached version) ``` ### Revalidation (Cache Stale) ```http GET /users/123 If-None-Match: "v1-abc123" → 200 OK → ETag: "v2-def456" → {"id": 123, "name": "Alice Updated", "updated_at": "..."} ``` ## Optimistic Locking with ETag Prevent concurrent update conflicts: ```http # Get current version GET /users/123 → ETag: "v1" # Update with version check PATCH /users/123 If-Match: "v1" {"name": "New Name"} → 200 OK (if still v1) → 412 Precondition Failed (if changed) ``` ## CDN Caching ### Vary Header Tell CDN which headers affect response: ```http # Different response per Accept-Language Vary: Accept-Language # Different per auth (don't cache auth-dependent responses in CDN) Vary: Authorization Cache-Control: private ``` ### Surrogate Keys For targeted cache invalidation: ```http Surrogate-Key: user-123 users-list homepage ``` ## Cache Invalidation Patterns ### Active Invalidation ```bash # Purge by URL curl -X PURGE https://cdn.example.com/api/users/123 # Purge by surrogate key curl -X PURGE https://cdn.example.com \ -H "Surrogate-Key: user-123" ``` ### Passive Invalidation - Use short `max-age` with `stale-while-revalidate` - Version in URL: `/v2/users` instead of `/users` - Hash in filename for assets ## Common Patterns ### API Responses ```http Cache-Control: private, max-age=0, must-revalidate ETag: "content-hash" ``` ### Authenticated Endpoints ```http Cache-Control: private, no-store ``` ### Public Data (rarely changes) ```http Cache-Control: public, max-age=3600, stale-while-revalidate=60 ETag: "content-hash" ``` -
rate-limiting.md 3.6 KB
# Rate Limiting Patterns Strategies and headers for API rate limiting. ## Standard Headers ### Response Headers ```http X-RateLimit-Limit: 1000 # Max requests per window X-RateLimit-Remaining: 847 # Requests remaining X-RateLimit-Reset: 1698415200 # Unix timestamp when limit resets Retry-After: 60 # Seconds to wait (on 429) ``` ### Rate Limit Response (429) ```json { "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests", "retry_after": 60, "limit": 1000, "remaining": 0, "reset_at": "2024-10-27T12:00:00Z" } } ``` ## Rate Limiting Strategies ### Fixed Window Simple: count requests in fixed time periods. ``` Window: 1 minute (00:00-00:59, 01:00-01:59, ...) Limit: 100 requests Pros: Simple to implement Cons: Burst at window edges (200 in 2 seconds across boundary) ``` ### Sliding Window Smoother: use weighted average across windows. ``` Current window: 50% through Previous window: 60 requests Current window: 40 requests Weighted count = (60 × 0.5) + 40 = 70 Remaining = 100 - 70 = 30 Pros: Smoother limits Cons: More complex, needs previous window data ``` ### Token Bucket Allows bursts with steady refill. ``` Bucket capacity: 100 tokens Refill rate: 10 tokens/second - Start with 100 tokens - Each request costs 1 token - Tokens refill at 10/sec - Burst allowed up to 100, then steady 10/sec Pros: Allows bursts, intuitive Cons: More state to track ``` ### Leaky Bucket Fixed output rate, queue excess. ``` Processing rate: 10 requests/second Queue size: 50 - Requests queue up - Processed at constant rate - Queue overflow = 429 Pros: Smooth output, protects backend Cons: Adds latency ``` ## Rate Limit Tiers ### By User/Plan ```http # Free tier X-RateLimit-Limit: 100 X-RateLimit-Window: 3600 # per hour # Pro tier X-RateLimit-Limit: 10000 X-RateLimit-Window: 3600 ``` ### By Endpoint ```http # Search (expensive) X-RateLimit-Limit: 10 X-RateLimit-Window: 60 # Read (cheap) X-RateLimit-Limit: 1000 X-RateLimit-Window: 60 ``` ### By Operation Type ```http # Writes POST/PUT/DELETE: 100/minute # Reads GET: 1000/minute ``` ## Implementation Headers ### GitHub Style ```http X-RateLimit-Limit: 5000 X-RateLimit-Remaining: 4999 X-RateLimit-Reset: 1372700873 X-RateLimit-Used: 1 X-RateLimit-Resource: core ``` ### RFC Draft (RateLimit Headers) ```http RateLimit-Limit: 100 RateLimit-Remaining: 50 RateLimit-Reset: 60 ``` ## Client Handling ### Retry Logic ```javascript async function fetchWithRetry(url, options, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { const response = await fetch(url, options); if (response.status === 429) { const retryAfter = response.headers.get('Retry-After') || 60; await sleep(retryAfter * 1000); continue; } return response; } throw new Error('Rate limit exceeded after retries'); } ``` ### Proactive Backoff ```javascript function checkRateLimit(response) { const remaining = response.headers.get('X-RateLimit-Remaining'); const reset = response.headers.get('X-RateLimit-Reset'); if (remaining < 10) { const waitMs = (reset - Date.now()) / remaining; // Slow down requests } } ``` ## Best Practices ### Server Side 1. Include rate limit headers in all responses 2. Return 429 with clear error message 3. Always include `Retry-After` 4. Consider different limits per endpoint 5. Log rate limit hits for monitoring ### Client Side 1. Respect `Retry-After` header 2. Implement exponential backoff 3. Monitor remaining quota 4. Cache responses to reduce requests 5. Batch operations when possible -
response-formats.md 4.6 KB
# Response Formats Error responses, versioning, bulk operations, and HATEOAS patterns. ## Error Response Format ### Standard Structure ```json { "error": { "code": "VALIDATION_ERROR", "message": "Invalid input data", "details": [ {"field": "email", "message": "Invalid email format"}, {"field": "age", "message": "Must be 18 or older"} ], "request_id": "abc-123", "documentation_url": "https://api.example.com/docs/errors#validation" } } ``` ### Minimal Error ```json { "error": { "code": "NOT_FOUND", "message": "User not found" } } ``` ### Validation Errors (422) ```json { "error": { "code": "VALIDATION_ERROR", "message": "Validation failed", "details": [ { "field": "email", "code": "INVALID_FORMAT", "message": "Must be a valid email address" }, { "field": "password", "code": "TOO_SHORT", "message": "Must be at least 8 characters" } ] } } ``` ### RFC 7807 Problem Details ```json { "type": "https://api.example.com/errors/validation", "title": "Validation Error", "status": 422, "detail": "The request body contains invalid data", "instance": "/users/123", "errors": [ {"pointer": "/email", "detail": "Invalid format"} ] } ``` --- ## Versioning Strategies ### URI Versioning (Most Common) ```http GET /v1/users GET /v2/users ``` **Pros:** Clear, easy to route, cacheable **Cons:** URL pollution, hard to deprecate ### Header Versioning ```http GET /users Accept: application/vnd.api.v1+json ``` **Pros:** Clean URLs **Cons:** Harder to test, less visible ### Query Parameter ```http GET /users?version=1 GET /users?api-version=2024-01-15 ``` **Pros:** Easy to implement **Cons:** Less RESTful, affects caching ### Date-Based Versioning ```http GET /users API-Version: 2024-01-15 ``` **Pros:** Fine-grained, Stripe-style **Cons:** Complex to maintain --- ## Bulk Operations ### Batch Endpoint ```http POST /batch Content-Type: application/json { "operations": [ {"method": "POST", "path": "/users", "body": {"name": "Alice"}}, {"method": "PATCH", "path": "/users/123", "body": {"status": "active"}}, {"method": "DELETE", "path": "/users/456"} ] } ``` **Response:** ```json { "results": [ {"status": 201, "body": {"id": 789, "name": "Alice"}}, {"status": 200, "body": {"id": 123, "status": "active"}}, {"status": 204, "body": null} ] } ``` ### Bulk Create ```http POST /users/bulk Content-Type: application/json [ {"name": "Alice", "email": "alice@example.com"}, {"name": "Bob", "email": "bob@example.com"} ] ``` **Response:** ```json { "created": 2, "items": [ {"id": 123, "name": "Alice"}, {"id": 124, "name": "Bob"} ] } ``` ### Bulk Create with Partial Failure ```json { "created": 1, "failed": 1, "items": [ {"id": 123, "name": "Alice", "status": "created"} ], "errors": [ {"index": 1, "error": {"code": "DUPLICATE", "message": "Email exists"}} ] } ``` ### Bulk Delete ```http DELETE /users/bulk Content-Type: application/json {"ids": [1, 2, 3, 4, 5]} ``` **Response:** ```json { "deleted": 5 } ``` --- ## HATEOAS Links ### Single Resource ```json { "id": 123, "name": "Alice", "email": "alice@example.com", "_links": { "self": {"href": "/users/123"}, "orders": {"href": "/users/123/orders"}, "profile": {"href": "/users/123/profile"}, "update": {"href": "/users/123", "method": "PATCH"}, "delete": {"href": "/users/123", "method": "DELETE"} } } ``` ### Collection with Pagination ```json { "data": [ {"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"} ], "meta": { "total": 150, "page": 2, "per_page": 20, "total_pages": 8 }, "_links": { "self": {"href": "/users?page=2"}, "first": {"href": "/users?page=1"}, "prev": {"href": "/users?page=1"}, "next": {"href": "/users?page=3"}, "last": {"href": "/users?page=8"} } } ``` ### HAL Format ```json { "_embedded": { "users": [ {"id": 1, "name": "Alice", "_links": {"self": {"href": "/users/1"}}}, {"id": 2, "name": "Bob", "_links": {"self": {"href": "/users/2"}}} ] }, "_links": { "self": {"href": "/users?page=1"}, "next": {"href": "/users?page=2"} }, "page": 1, "total": 100 } ``` ### JSON:API Format ```json { "data": [ { "type": "users", "id": "1", "attributes": {"name": "Alice"}, "relationships": { "orders": {"links": {"related": "/users/1/orders"}} }, "links": {"self": "/users/1"} } ], "links": { "self": "/users?page=1", "next": "/users?page=2" }, "meta": {"total": 100} } ``` -
status-codes.md 4.9 KB
# HTTP Status Codes Reference Complete reference for HTTP status codes in REST APIs. ## Success (2xx) | Code | Name | When to Use | |------|------|-------------| | **200 OK** | Success | GET, PUT, PATCH, DELETE success with body | | **201 Created** | Created | POST success (include `Location` header) | | **202 Accepted** | Accepted | Request queued for async processing | | **204 No Content** | No Content | Success with no response body | | **206 Partial Content** | Partial | Range request fulfilled | ### Usage Examples ```http # 200 OK - Successful GET GET /users/123 → 200 OK → {"id": 123, "name": "Alice"} # 201 Created - Successful POST POST /users → 201 Created → Location: /users/456 → {"id": 456, "name": "Bob"} # 202 Accepted - Async operation POST /jobs → 202 Accepted → {"job_id": "abc123", "status": "pending"} # 204 No Content - Successful DELETE DELETE /users/123 → 204 No Content ``` ## Redirection (3xx) | Code | Name | When to Use | |------|------|-------------| | **301 Moved Permanently** | Moved | Resource permanently relocated | | **302 Found** | Found | Temporary redirect (avoid in APIs) | | **304 Not Modified** | Not Modified | Client cache is valid (ETag match) | | **307 Temporary Redirect** | Temp Redirect | Redirect preserving HTTP method | | **308 Permanent Redirect** | Perm Redirect | Like 301, preserves method | ### 301 vs 308 - **301**: Browser may change POST to GET on redirect - **308**: Guarantees method is preserved ### 304 Workflow ```http # First request GET /users/123 → 200 OK → ETag: "abc123" # Subsequent request with validation GET /users/123 If-None-Match: "abc123" → 304 Not Modified (use cached version) ``` ## Client Errors (4xx) | Code | Name | When to Use | |------|------|-------------| | **400 Bad Request** | Bad Request | Invalid syntax, malformed JSON | | **401 Unauthorized** | Unauthorized | Missing or invalid authentication | | **403 Forbidden** | Forbidden | Authenticated but not authorized | | **404 Not Found** | Not Found | Resource doesn't exist | | **405 Method Not Allowed** | Not Allowed | HTTP method not supported | | **406 Not Acceptable** | Not Acceptable | Can't produce requested content type | | **409 Conflict** | Conflict | State conflict (duplicate, version mismatch) | | **410 Gone** | Gone | Resource permanently removed | | **412 Precondition Failed** | Precondition | If-Match header condition failed | | **413 Payload Too Large** | Too Large | Request body exceeds limit | | **415 Unsupported Media Type** | Bad Media | Content-Type not supported | | **422 Unprocessable Entity** | Unprocessable | Valid syntax, invalid semantics | | **429 Too Many Requests** | Rate Limited | Rate limit exceeded | ### 400 vs 422 - **400**: Malformed request (invalid JSON, wrong types) - **422**: Valid request, but business logic rejects it ```http # 400 - Syntax error POST /users {"name": "Alice", age: 30} # Missing quotes around age → 400 Bad Request → {"error": "Invalid JSON"} # 422 - Validation error POST /users {"name": "Alice", "age": -5} # Age can't be negative → 422 Unprocessable Entity → {"error": {"field": "age", "message": "Must be positive"}} ``` ### 401 vs 403 - **401**: "Who are you?" (not authenticated) - **403**: "I know who you are, but no" (not authorized) ```http # 401 - Missing token GET /admin/users → 401 Unauthorized → {"error": "Authentication required"} # 403 - Valid token, wrong permissions GET /admin/users Authorization: Bearer <user_token> → 403 Forbidden → {"error": "Admin access required"} ``` ### 409 Conflict Examples ```http # Duplicate resource POST /users {"email": "existing@example.com"} → 409 Conflict → {"error": "Email already exists"} # Version mismatch (optimistic locking) PATCH /users/123 If-Match: "old-version" → 409 Conflict → {"error": "Resource was modified"} ``` ## Server Errors (5xx) | Code | Name | When to Use | |------|------|-------------| | **500 Internal Server Error** | Server Error | Generic server failure | | **501 Not Implemented** | Not Implemented | Feature not available | | **502 Bad Gateway** | Bad Gateway | Upstream returned invalid response | | **503 Service Unavailable** | Unavailable | Temporarily unavailable | | **504 Gateway Timeout** | Timeout | Upstream timeout | ### 503 with Retry-After ```http GET /api/resource → 503 Service Unavailable → Retry-After: 300 → {"error": "Service temporarily unavailable", "retry_after": 300} ``` ## Decision Tree ``` Is the request valid? ├─ No → Is it syntax? → 400 Bad Request │ Is it validation? → 422 Unprocessable Entity │ └─ Yes → Is auth provided? ├─ No → 401 Unauthorized └─ Yes → Is authorized? ├─ No → 403 Forbidden └─ Yes → Does resource exist? ├─ No → 404 Not Found └─ Yes → Success! 2xx ```
-
-
scripts
-
.gitkeep 0 B · in bundle
-
-
SKILL.md 2.9 KB
--- name: rest-ops description: "Quick reference for RESTful API design patterns, HTTP semantics, caching, and rate limiting. Triggers on: rest api, http methods, status codes, api design, endpoint design, api versioning, rate limiting, caching headers." license: MIT allowed-tools: "Read Write" metadata: author: claude-mods --- # REST Patterns Quick reference for RESTful API design patterns and HTTP semantics. ## HTTP Methods | Method | Purpose | Idempotent | Cacheable | |--------|---------|------------|-----------| | **GET** | Retrieve resource(s) | Yes | Yes | | **POST** | Create new resource | No | No | | **PUT** | Replace entire resource | Yes | No | | **PATCH** | Partial update | Maybe | No | | **DELETE** | Remove resource | Yes | No | ## Essential Status Codes | Code | Name | Use | |------|------|-----| | **200** | OK | Success with body | | **201** | Created | POST success (add `Location` header) | | **204** | No Content | Success, no body | | **400** | Bad Request | Invalid syntax | | **401** | Unauthorized | Not authenticated | | **403** | Forbidden | Not authorized | | **404** | Not Found | Resource doesn't exist | | **422** | Unprocessable | Validation error | | **429** | Too Many Requests | Rate limited | | **500** | Server Error | Internal failure | ## Resource Design ```http GET /users # List POST /users # Create GET /users/{id} # Get one PUT /users/{id} # Replace PATCH /users/{id} # Update DELETE /users/{id} # Delete # Query parameters GET /users?page=2&limit=20 # Pagination GET /users?sort=created_at:desc # Sorting GET /users?role=admin # Filtering ``` ## Security Checklist - [ ] HTTPS/TLS only - [ ] OAuth 2.0 or JWT for auth - [ ] Validate all inputs - [ ] Rate limit per client - [ ] CORS headers configured - [ ] No sensitive data in URLs - [ ] Use `no-store` for sensitive responses ## Common Mistakes | Mistake | Fix | |---------|-----| | Verbs in URLs | `/getUsers` → `/users` | | Deep nesting | Flatten or use query params | | 200 for errors | Use proper 4xx/5xx | | No pagination | Always paginate collections | | Missing rate limits | Protect against abuse | ## Quick Reference | Task | Pattern | |------|---------| | Paginate | `?page=2&limit=20` | | Sort | `?sort=field:asc` | | Filter | `?status=active` | | Sparse fields | `?fields=id,name` | | Include related | `?include=orders` | ## When to Use - Designing new API endpoints - Choosing HTTP methods and status codes - Implementing caching headers - Setting up rate limiting - Structuring error responses ## Additional Resources For detailed patterns, load: - `./references/status-codes.md` - Complete status code reference with examples - `./references/caching-patterns.md` - Cache-Control, ETag, CDN patterns - `./references/rate-limiting.md` - Rate limiting strategies and headers - `./references/response-formats.md` - Errors, versioning, bulk ops, HATEOAS
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.