Install
$ agentstack add skill-sagargupta16-claude-code-recipes-api-design ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
API Design
> REST API conventions: URL structure, HTTP methods, status codes, pagination, filtering, error responses, and versioning.
URL Structure
- Use nouns, not verbs -- the HTTP method provides the verb
- Use plural resource names --
/users,/orders,/products - Use kebab-case for multi-word resources --
/order-items, not/orderItems - Nest resources to show relationships -- max 2 levels deep
- Use query parameters for filtering, not path segments
# Good
GET /api/v1/users
GET /api/v1/users/123
GET /api/v1/users/123/orders
POST /api/v1/users
PATCH /api/v1/users/123
DELETE /api/v1/users/123
# Bad
GET /api/v1/getUsers
GET /api/v1/user/123
POST /api/v1/users/123/orders/456/items/789/notes # too deeply nested
HTTP Methods
| Method | Purpose | Idempotent | Request Body | Success Code | |--------|---------|:----------:|:------------:|:------------:| | GET | Read resource(s) | Yes | No | 200 | | POST | Create resource | No | Yes | 201 | | PUT | Replace resource entirely | Yes | Yes | 200 | | PATCH | Partial update | No* | Yes | 200 | | DELETE | Remove resource | Yes | No | 204 |
*PATCH is not guaranteed idempotent, but should be designed to be when possible.
Rules
- GET requests must be safe -- no side effects, no state changes
- POST for creation -- return the created resource with
Locationheader - Use PATCH over PUT -- partial updates are more practical than full replacement
- DELETE should be idempotent -- deleting a non-existent resource returns 204, not 404
Status Codes
Use the correct status code. When in doubt, refer to this table:
Success (2xx)
| Code | Meaning | When to Use | |------|---------|-------------| | 200 | OK | Successful GET, PUT, PATCH | | 201 | Created | Successful POST that creates a resource | | 204 | No Content | Successful DELETE, or PUT/PATCH with no response body |
Client Errors (4xx)
| Code | Meaning | When to Use | |------|---------|-------------| | 400 | Bad Request | Malformed JSON, invalid field values, validation errors | | 401 | Unauthorized | Missing or invalid authentication | | 403 | Forbidden | Authenticated but lacks permission | | 404 | Not Found | Resource does not exist | | 409 | Conflict | Duplicate resource, state conflict | | 422 | Unprocessable Entity | Valid JSON but fails business rules | | 429 | Too Many Requests | Rate limit exceeded |
Server Errors (5xx)
| Code | Meaning | When to Use | |------|---------|-------------| | 500 | Internal Server Error | Unexpected server failure | | 502 | Bad Gateway | Upstream service failure | | 503 | Service Unavailable | Server overloaded or in maintenance |
Error Responses
Use a consistent error format across all endpoints:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed.",
"details": [
{
"field": "email",
"message": "Must be a valid email address.",
"code": "INVALID_FORMAT"
},
{
"field": "age",
"message": "Must be at least 18.",
"code": "MIN_VALUE"
}
]
}
}
Rules
- Always include a machine-readable error code --
VALIDATION_ERROR,NOT_FOUND,RATE_LIMITED - Include a human-readable message -- suitable for developer debugging
- Never expose internal errors -- no stack traces, SQL queries, or file paths in production
- Field-level errors in
detailsarray -- for validation errors, specify which field failed
Pagination
Use cursor-based pagination for large datasets, offset-based for simple cases.
Offset-based (simple)
GET /api/v1/users?page=2&per_page=25
Response:
{
"data": [ ... ],
"pagination": {
"page": 2,
"per_page": 25,
"total": 150,
"total_pages": 6
}
}
Cursor-based (scalable)
GET /api/v1/users?limit=25&cursor=eyJpZCI6MTAwfQ
Response:
{
"data": [ ... ],
"pagination": {
"limit": 25,
"has_more": true,
"next_cursor": "eyJpZCI6MTI1fQ"
}
}
Rules
- Default page size: 25, max: 100 -- prevent clients from requesting unlimited data
- Always return pagination metadata -- clients need to know if there are more pages
- Use cursor-based for real-time data or large tables -- offset-based breaks with concurrent writes
Filtering and Sorting
# Filter by field values
GET /api/v1/users?status=active&role=admin
# Date ranges
GET /api/v1/orders?created_after=2025-01-01&created_before=2025-12-31
# Search
GET /api/v1/products?q=keyboard
# Sort (prefix with - for descending)
GET /api/v1/users?sort=created_at
GET /api/v1/users?sort=-updated_at
# Combine everything
GET /api/v1/orders?status=shipped&sort=-created_at&page=1&per_page=25
Rules
- Use
snake_casefor query parameter names - Support multiple sort fields --
?sort=-created_at,name - Validate all filter parameters -- return 400 for unknown fields
- Document allowed filter fields per endpoint
Request and Response Conventions
- Use
snake_casefor all JSON keys --created_at,first_name,order_id - Use ISO 8601 for dates --
2025-06-15T14:30:00Z - Use UUIDs or opaque strings for IDs -- avoid exposing auto-increment integers
- Wrap collections in a
datakey --{ "data": [...] }, not a bare array - Include
created_atandupdated_atin all resources - Use
nullfor absent optional fields -- don't omit them entirely
{
"data": {
"id": "usr_a1b2c3d4",
"email": "user@example.com",
"first_name": "Jane",
"last_name": "Doe",
"role": "admin",
"avatar_url": null,
"created_at": "2025-06-15T14:30:00Z",
"updated_at": "2025-06-15T14:30:00Z"
}
}
Versioning
- Use URL path versioning --
/api/v1/,/api/v2/ - Increment the major version only for breaking changes
- Support the previous version for at least 6 months after deprecation
- Return a
Deprecationheader on deprecated endpoints - Document migration guides between versions
Authentication
- Use Bearer tokens in the
Authorizationheader --Authorization: Bearer - Never pass tokens in query parameters -- they end up in server logs
- Return 401 for missing/invalid tokens, 403 for insufficient permissions
- Include rate limit headers --
X-RateLimit-Limit,X-RateLimit-Remaining,X-RateLimit-Reset
Anti-patterns
- Verbs in URLs -- use HTTP methods instead
- Returning 200 with error body -- use proper status codes
- Nested resources deeper than 2 levels -- flatten with query parameters
- Inconsistent naming -- pick
snake_caseorcamelCaseand stick with it - Missing pagination on list endpoints -- always paginate collections
- Exposing internal IDs -- use prefixed opaque IDs like
usr_,ord_,prod_
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Sagargupta16
- Source: Sagargupta16/claude-code-recipes
- License: MIT
- Homepage: https://sagargupta.online
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.