npx skills add smithery/pluginagentmarketplace --skill rest
pluginagentmarketplace/custom-plugin-api-design · Archived
rest
RESTful API design principles and best practices
Installation
npx skills add pluginagentmarketplace/custom-plugin-api-design --skill rest
Stronger alternatives
This repository is archived — consider an actively maintained alternative.
>- Sets up, manages, queries, and configures Cloud Firestore databases (Standard/Enterprise edi…
107.6K installsSimilar popular skills
Related neighbors and high-traction skills in the same topics — useful to compare before installing.
Browser automation CLI for AI agents. Use when the user needs to interact with websites, includ…
810.4K installsReview UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "chec…
617.3K installsBuild, deploy, evaluate, optimize, fine-tune, and manage Microsoft Foundry agents, models, and …
576.5K installsArchitect and provision enterprise Azure infrastructure from workload descriptions. For cloud a…
402.8K installsMore details
Agent compatibility
Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.
Also listed on
Alternate registries and mirrors of this skill.
Repository health
main
Skill metadata
Parsed from SKILL.md frontmatter.
Package contents
Files included with this skill beyond the listing page.
-
skill md
SKILL.md7,190 B -
docs
SUMMARY.md60 B
History
- First seen on skills.sh
- First recorded snapshot · 1 installs
SKILL.md
REST API Design Skill
Purpose
Design RESTful APIs following industry best practices.
HTTP Methods
| Method | Action | Idempotent | Safe | Request Body | Response Body |
|---|---|---|---|---|---|
| GET | Read | Yes | Yes | No | Yes |
| POST | Create | No | No | Yes | Yes |
| PUT | Replace | Yes | No | Yes | Yes |
| PATCH | Update | No | No | Yes | Yes |
| DELETE | Delete | Yes | No | No | No |
| HEAD | Metadata | Yes | Yes | No | No |
| OPTIONS | Capabilities | Yes | Yes | No | Yes |
Status Codes
Success (2xx)
200 OK → GET, PUT, PATCH success
201 Created → POST success (include Location header)
202 Accepted → Async operation started
204 No Content → DELETE success
Client Errors (4xx)
400 Bad Request → Validation failed
401 Unauthorized → Authentication required
403 Forbidden → Permission denied
404 Not Found → Resource doesn't exist
409 Conflict → State conflict (duplicate, etc.)
422 Unprocessable → Semantic errors
429 Too Many → Rate limit exceeded
Server Errors (5xx)
500 Internal → Unexpected error
502 Bad Gateway → Upstream failed
503 Unavailable → Temporarily down
504 Timeout → Upstream timeout
Resource Design
# Collection operations
GET /api/v1/users → List (paginated)
POST /api/v1/users → Create
# Instance operations
GET /api/v1/users/{id} → Read
PUT /api/v1/users/{id} → Replace
PATCH /api/v1/users/{id} → Update
DELETE /api/v1/users/{id} → Delete
# Nested resources (max 2 levels)
GET /api/v1/users/{id}/orders → User's orders
POST /api/v1/users/{id}/orders → Create user's order
# Sub-resource instance
GET /api/v1/users/{id}/orders/{orderId}
# Actions (when CRUD doesn't fit)
POST /api/v1/orders/{id}/cancel
POST /api/v1/users/{id}/verify
POST /api/v1/reports/{id}/generate
Response Envelope
{
"data": {
"id": "123",
"type": "user",
"attributes": {
"name": "John Doe",
"email": "[email protected]"
}
},
"meta": {
"requestId": "abc-123",
"timestamp": "2024-12-30T10:00:00Z",
"version": "1.0.0"
}
}
Error Response (RFC 7807)
{
"type": "https://api.example.com/errors/validation",
"title": "Validation Failed",
"status": 400,
"detail": "One or more fields have validation errors",
"instance": "/api/v1/users",
"errors": [
{ "field": "email", "message": "Invalid email format" },
{ "field": "password", "message": "Minimum 12 characters" }
]
}
Pagination
Offset-based (Simple)
GET /api/v1/users?page=2&limit=20
Response:
{
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 150,
"totalPages": 8,
"hasNext": true,
"hasPrev": true
}
}
Cursor-based (Recommended)
GET /api/v1/users?cursor=eyJpZCI6MTAwfQ&limit=20
Response:
{
"data": [...],
"pagination": {
"nextCursor": "eyJpZCI6MTIwfQ",
"prevCursor": "eyJpZCI6ODB9",
"hasNext": true,
"hasPrev": true
}
}
Filtering & Sorting
# Filtering
GET /api/v1/users?status=active&role=admin
GET /api/v1/users?created_at[gte]=2024-01-01
GET /api/v1/users?search=john
# Sorting
GET /api/v1/users?sort=created_at:desc
GET /api/v1/users?sort=-created_at,name # - prefix for desc
# Field selection
GET /api/v1/users?fields=id,name,email
# Embedding related resources
GET /api/v1/users?include=orders,profile
Caching Headers
# Response headers
Cache-Control: public, max-age=3600
ETag: "abc123"
Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
Vary: Accept-Encoding, Authorization
# Conditional requests
If-None-Match: "abc123"
If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
Unit Test Template
import { describe, it, expect } from 'vitest';
import request from 'supertest';
import app from './app';
describe('REST API - Users', () => {
describe('GET /api/v1/users', () => {
it('should return paginated users', async () => {
const res = await request(app)
.get('/api/v1/users?page=1&limit=10')
.expect(200);
expect(res.body).toHaveProperty('data');
expect(res.body).toHaveProperty('pagination');
expect(res.body.pagination.page).toBe(1);
});
it('should filter by status', async () => {
const res = await request(app)
.get('/api/v1/users?status=active')
.expect(200);
res.body.data.forEach(user => {
expect(user.status).toBe('active');
});
});
});
describe('POST /api/v1/users', () => {
it('should create user and return 201', async () => {
const res = await request(app)
.post('/api/v1/users')
.send({ email: '[email protected]', name: 'Test' })
.expect(201);
expect(res.headers.location).toMatch(/\/api\/v1\/users\/\w+/);
expect(res.body.data.id).toBeDefined();
});
it('should return 400 for invalid data', async () => {
const res = await request(app)
.post('/api/v1/users')
.send({ email: 'invalid' })
.expect(400);
expect(res.body.type).toContain('validation');
});
});
describe('GET /api/v1/users/:id', () => {
it('should return 404 for non-existent user', async () => {
await request(app)
.get('/api/v1/users/non-existent-id')
.expect(404);
});
});
});
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| 404 for valid resource | Trailing slash mismatch | Normalize URLs |
| CORS errors | Missing headers | Configure CORS middleware |
| Slow pagination | Large offset | Use cursor pagination |
| Cache not working | Missing Vary header | Add Vary: Authorization |
Quality Checklist
- Resource names are plural nouns
- HTTP methods match actions
- Status codes are correct
- Error responses follow RFC 7807
- Pagination implemented for lists
- Filtering and sorting supported
- Caching headers configured
- Rate limiting in place