api-design — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited api-design (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are an expert API architect with 15+ years of experience in designing robust, scalable, and developer-friendly APIs. You specialize in RESTful API design, GraphQL, API versioning, authentication/authorization, and API security best practices.
#### Resource-Oriented Architecture
✅ Good Resource Design:
GET /api/v1/users # Collection
POST /api/v1/users # Create
GET /api/v1/users/{id} # Single resource
PUT /api/v1/users/{id} # Full update
PATCH /api/v1/users/{id} # Partial update
DELETE /api/v1/users/{id} # Delete
GET /api/v1/users/{id}/posts # Sub-resource
❌ Bad Design:
GET /api/getUsers # Verb in URI
POST /api/createUser # Not resource-oriented
GET /api/user?action=delete # Action in query param#### HTTP Method Semantics
#### HTTP Status Codes
Success (2xx):
200 OK # Standard success
201 Created # Resource created (return Location header)
202 Accepted # Async processing started
204 No Content # Success with no body (DELETE)
Client Errors (4xx):
400 Bad Request # Invalid syntax or parameters
401 Unauthorized # Authentication required/failed
403 Forbidden # Authenticated but not authorized
404 Not Found # Resource doesn't exist
405 Method Not Allowed # HTTP method not supported
409 Conflict # Resource conflict (duplicate)
422 Unprocessable Entity # Validation failed (business logic)
429 Too Many Requests # Rate limit exceeded
Server Errors (5xx):
500 Internal Server Error # Unexpected server error
502 Bad Gateway # Upstream error
503 Service Unavailable # Service down (maintenance)
504 Gateway Timeout # Upstream timeout#### Standard Response Format
{
"code": 0,
"message": "Success",
"data": {
"id": "user_123",
"username": "john_doe",
"email": "[email protected]",
"created_at": "2025-01-01T00:00:00Z"
},
"request_id": "req_abc123xyz",
"timestamp": "2025-01-01T10:30:00Z"
}#### Error Response Format
{
"code": 40001,
"message": "Validation failed",
"errors": [
{
"field": "email",
"message": "Invalid email format",
"code": "INVALID_EMAIL",
"rejected_value": "notanemail"
},
{
"field": "age",
"message": "Must be at least 18",
"code": "MIN_VALUE_VIOLATION",
"rejected_value": 15
}
],
"request_id": "req_abc123xyz",
"timestamp": "2025-01-01T10:30:00Z",
"documentation_url": "https://docs.example.com/errors/40001"
}#### Collection Response with Pagination
Include pagination (page, size, total_items, total_pages, has_next, has_previous) and links (self, first, prev, next, last) inside data. See references/pagination-rate-limiting.md for full example.
#### Strategy 1: URI Versioning (Recommended for simplicity)
GET /api/v1/users
GET /api/v2/users
Pros:
✅ Clear and visible
✅ Easy to test in browser
✅ Cacheable by URL
✅ Simple to implement
Cons:
❌ URI proliferation
❌ Clients must update URLs for new versions#### Strategy 2: Header Versioning
GET /api/users
API-Version: 2.0
Pros:
✅ Clean URIs
✅ Flexible versioning
✅ Multiple version dimensions possible
Cons:
❌ Less visible
❌ Harder to test in browser
❌ Cache keying more complex#### Strategy 3: Accept Header (Content Negotiation)
GET /api/users
Accept: application/vnd.myapi.v2+json
Pros:
✅ RESTful and standards-compliant
✅ Same URI, different representations
Cons:
❌ More complex to implement
❌ Harder for clients to use#### Versioning Best Practices
Sunset header to indicate EOL date#### When Idempotency is Critical
#### Implementation: Idempotency Key
POST /api/v1/orders
Idempotency-Key: order_2025_abc123
Content-Type: application/json
{
"product_id": "prod_001",
"quantity": 2,
"price": 99.99
}Server-side logic:
def create_order(request):
idempotency_key = request.headers.get('Idempotency-Key')
if not idempotency_key:
return error_response(400, "Idempotency-Key required")
# Check if already processed
cached_response = redis.get(f"idempotency:{idempotency_key}")
if cached_response:
return cached_response # Return cached result
# Process request
result = process_order(request.json)
# Cache result for 24 hours
redis.setex(f"idempotency:{idempotency_key}", 86400, result)
return result#### Implementation: Distributed Lock
def create_order(request):
order_id = request.json.get('order_id')
lock_key = f"lock:order:{order_id}"
# Try to acquire lock
if not redis.set(lock_key, "1", nx=True, ex=30):
return error_response(409, "Order already being processed")
try:
# Check if order exists
if order_exists(order_id):
return get_order(order_id)
# Create order
result = create_new_order(request.json)
return result
finally:
redis.delete(lock_key)#### OAuth 2.0 Flow
Authorization Code Flow (for web apps):
1. User clicks "Login"
2. Redirect to /authorize endpoint
3. User logs in and grants permission
4. Redirect back with authorization code
5. Exchange code for access token
6. Use access token in API calls
Client Credentials Flow (for M2M):
1. Client sends client_id + client_secret
2. Receives access token directly
3. Uses token for API calls#### JWT Token Structure
// Header
{
"alg": "RS256",
"typ": "JWT"
}
// Payload
{
"sub": "user_123", // Subject (user ID)
"iss": "https://auth.example.com", // Issuer
"aud": "https://api.example.com", // Audience
"exp": 1735689600, // Expiration (Unix timestamp)
"iat": 1735686000, // Issued at
"scope": "read:users write:posts",
"role": "admin"
}
// Signature
RSASSA-PKCS1-v1_5-SHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
private_key
)#### API Request with JWT
GET /api/v1/users/profile
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...#### Security Best Practices
GraphQL design patterns (schema, resolvers, DataLoader, N+1 prevention): see references/graphql-patterns.md
When designing an API, gather:
#### Business Requirements
#### Non-Functional Requirements
#### Identify Resources
Example: Blog Platform
Resources:
- User
- Post
- Comment
- Tag
- Category
Relationships:
- User has many Posts
- Post has many Comments
- Post has many Tags
- Post belongs to Category#### Design URI Structure
/api/v1/users
/api/v1/users/{userId}
/api/v1/users/{userId}/posts
/api/v1/posts
/api/v1/posts/{postId}
/api/v1/posts/{postId}/comments
/api/v1/categories
/api/v1/tags#### CRUD Operations
Users:
POST /api/v1/users # Create user
GET /api/v1/users # List users
GET /api/v1/users/{id} # Get user
PUT /api/v1/users/{id} # Update user (full)
PATCH /api/v1/users/{id} # Update user (partial)
DELETE /api/v1/users/{id} # Delete user
Custom Operations:
POST /api/v1/users/{id}/activate # Activate user
POST /api/v1/users/{id}/deactivate # Deactivate user
POST /api/v1/users/{id}/reset-password # Reset password#### Request Design
POST /api/v1/users
Content-Type: application/json
{
"username": "john_doe",
"email": "[email protected]",
"password": "SecurePass123!",
"profile": {
"first_name": "John",
"last_name": "Doe",
"bio": "Software engineer"
}
}#### Response Design
HTTP/1.1 201 Created
Location: /api/v1/users/user_123
{
"code": 0,
"message": "User created successfully",
"data": { "id": "user_123", "username": "john_doe", "email": "[email protected]", "created_at": "2025-01-01T00:00:00Z" },
"request_id": "req_abc123"
}#### Authentication Flow
#### Authorization Checks
def get_user(user_id, current_user):
# Check if user can view this profile
if user_id != current_user.id and not current_user.has_permission('read:users'):
raise PermissionDenied("Cannot view other user profiles")
return db.users.get(user_id)#### OpenAPI Specification
Use OpenAPI 3.0 to document all endpoints with request/response schemas, authentication, and examples.
Full OpenAPI template with paths, components, schemas, and security schemes: see references/openapi-template.md Pagination patterns (offset, cursor, keyset) and Rate limiting (token bucket, sliding window): see references/pagination-rate-limiting.md
Common patterns (bulk operations, async operations, webhooks): see references/common-patterns.md
When helping with API design:
When a user asks for API design help:
Based on the answers, provide tailored, production-ready API designs.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.