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.
Comprehensive API design skill combining REST, GraphQL, gRPC, and Python library architecture expertise with patterns, templates, and tools for production-grade APIs.
What are you building?
+-- CRUD resources with clear entity model? --> REST
| Best for: resource-oriented operations, caching, wide tooling support
+-- Complex queries with varying client needs? --> GraphQL
| Best for: over-fetching prevention, nested data, multiple client types
+-- High-throughput service-to-service? --> gRPC
| Best for: low latency, strong typing, streaming, polyglot microservices
+-- Reusable Python package? --> Python Library API
Best for: SDKs, internal tooling, developer experienceURL Patterns:
/api/v1/users (plural nouns, lowercase with hyphens)/api/v1/organizations/{org_id}/teams (hierarchical, max 2 levels)/getUsers or underscores: /user_profilesHTTP Methods:
GET - Retrieve (safe, idempotent, cacheable)POST - Create (returns 201 with Location header)PUT - Replace entire resource (idempotent)PATCH - Partial update (only changed fields)DELETE - Remove (idempotent, returns 204)| Category | Code | When |
|---|---|---|
| Success | 200 | GET, PUT, PATCH success |
| Success | 201 | POST success (include Location header) |
| Success | 204 | DELETE success |
| Client Error | 400 | Malformed request |
| Client Error | 401 | Missing/invalid authentication |
| Client Error | 403 | Insufficient permissions |
| Client Error | 404 | Resource doesn't exist |
| Client Error | 409 | Duplicate resource |
| Client Error | 422 | Validation errors |
| Client Error | 429 | Rate limit exceeded |
| Server Error | 500 | Unhandled exception |
| Server Error | 503 | Database/service down |
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"details": [
{ "field": "email", "message": "Invalid email format" }
],
"requestId": "req_abc123",
"timestamp": "2025-10-25T10:30:00Z"
}
}type User {
id: ID!
email: String!
profile: Profile
posts(first: Int, after: String): PostConnection!
createdAt: DateTime!
}
type PostConnection {
edges: [PostEdge!]!
pageInfo: PageInfo!
totalCount: Int!
}
type Query {
user(id: ID!): User
users(first: Int, after: String): UserConnection!
me: User
}
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
}from fastapi import APIRouter, Depends, HTTPException, status
router = APIRouter(prefix="/api/v1/users", tags=["users"])
@router.post("", response_model=UserRead, status_code=status.HTTP_201_CREATED)
async def create_user(
user_data: UserCreate,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_user),
) -> UserRead:
"""Create a new user in the current tenant."""
repository = UserRepository(db, tenant_id=current_user.tenant_id)
user = await repository.create(user_data)
return userfrom pydantic import BaseModel, EmailStr, Field, ConfigDict
class UserCreate(BaseModel):
email: EmailStr
full_name: str = Field(..., min_length=1, max_length=255)
password: str = Field(..., min_length=8)
class UserRead(BaseModel):
id: str
tenant_id: str
email: EmailStr
full_name: str
created_at: datetime
model_config = ConfigDict(from_attributes=True)Cursor-Based (recommended for large datasets):
GET /posts?limit=20&cursor=***
{ "data": [...], "pagination": { "nextCursor": "***", "hasMore": true } }Offset-Based (simpler, for small datasets):
GET /posts?limit=20&offset=40
{ "data": [...], "pagination": { "total": 500, "limit": 20, "offset": 40 } }| Flow | Use Case |
|---|---|
| JWT Bearer tokens | API authentication, stateless sessions |
| API Key (X-API-Key) | Service-to-service, developer access |
| OAuth 2.0 Authorization Code | Web apps with backend |
| OAuth 2.0 Client Credentials | Service-to-service |
| OAuth 2.0 PKCE | Mobile/SPA apps |
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 75
X-RateLimit-Reset: 1698340800
Retry-After: 60| File | Description |
|---|---|
references/rest-best-practices.md | Comprehensive REST API patterns and status codes |
references/authentication.md | OAuth 2.0, JWT, API keys, MFA patterns |
references/versioning-strategies.md | API versioning and deprecation |
references/common-patterns.md | Health checks, webhooks, batch operations |
references/schema-patterns.md | GraphQL schema design patterns |
references/federation-guide.md | Apollo Federation architecture |
references/performance-optimization.md | GraphQL performance, DataLoader, caching |
references/architectural-principles.md | Python library SOLID principles |
references/pep-standards.md | Python PEP quick reference |
references/fastapi-setup.md | FastAPI main app configuration |
references/openapi.md | OpenAPI customization |
references/error-handlers.md | FastAPI exception handlers |
references/cors-rate-limiting.md | CORS and rate limiting setup |
references/openapi-spec.yaml | Complete OpenAPI 3.1 example |
references/graphql-schema.graphql | GraphQL with Relay connections |
references/grpc-service.proto | Protocol Buffer definitions |
references/rate-limiting.yaml | Tier-based rate limit config |
references/api-security.yaml | Auth, CORS, security headers |
| File | Description |
|---|---|
templates/fastapi-crud-endpoint.py | Complete CRUD router template |
templates/pydantic-schemas.py | Request/response schema template |
templates/repository-pattern.py | Repository with tenant isolation |
templates/rate-limiter.py | Upstash Redis rate limiter |
templates/error-handler.py | FastAPI exception handlers |
templates/tanstack-server-function.ts | TanStack Start server functions |
| File | Description |
|---|---|
examples/fastapi-crud.md | CRUD endpoints with repository |
examples/pydantic-schemas.md | Validation schema examples |
examples/pagination.md | Pagination implementation |
examples/testing.md | API testing patterns |
examples/tanstack-start.md | TanStack Start examples |
examples/openapi-spec.yaml | Blog API OpenAPI specification |
examples/graphql-schema.graphql | Full GraphQL schema with subscriptions |
| File | Description |
|---|---|
scripts/schema_analyzer.py | Analyze GraphQL schemas for quality |
scripts/resolver_generator.py | Generate TypeScript resolvers |
scripts/federation_scaffolder.py | Scaffold Apollo Federation subgraphs |
scripts/api_helper.py | OpenAPI validation and docs generation |
scripts/validate-api-spec.sh | Validate API specifications |
| File | Description |
|---|---|
assets/pyproject.toml.template | Production-ready pyproject.toml |
assets/README.md.template | Library README template |
assets/CONTRIBUTING.md.template | Contribution guide |
assets/project-structure.txt | Recommended package layout |
assets/test-structure.txt | Test organization |
assets/example-exceptions.py | Exception hierarchy pattern |
assets/example-config.py | Configuration pattern |
| File | Description |
|---|---|
checklists/api-design-checklist.md | API design review checklist |
checklists/security-review.md | Security review checklist |
# Validate OpenAPI spec
python scripts/api_helper.py validate --spec openapi.yaml
# Analyze GraphQL schema
python scripts/schema_analyzer.py schema.graphql --validate
# Generate documentation
python scripts/api_helper.py docs --spec openapi.yaml --output docs/| Anti-Pattern | Problem | Solution |
|---|---|---|
| Verb-based URLs | /getUsers violates REST conventions | Use /users with GET method |
| Inconsistent response envelopes | Clients can't parse predictably | Always use consistent structure |
| Breaking changes without versioning | Clients break on updates | Use semantic versioning; deprecation headers |
| N+1 queries in GraphQL | Each resolver fires separate DB query | Use DataLoader for batching |
| Over-fetching REST endpoints | Clients get more data than needed | Support sparse fieldsets, filtering |
| Missing pagination | List endpoints return unbounded results | Always paginate list endpoints |
| No idempotency keys | Duplicate mutations from retries | Accept Idempotency-Key header |
| Leaky internal errors | Stack traces exposed to clients | Generic messages in production |
| Missing CORS configuration | Browser requests blocked | Configure allowed origins explicitly |
| No rate limiting | API abuse and DoS | Implement per-user/per-endpoint limits |
| PUT for partial updates | Overwrites unchanged fields | Use PATCH for partial updates |
| Monolithic GraphQL schema | Schema becomes unmaintainable | Use Federation for schema separation |
[ ] All endpoints use nouns, not verbs
[ ] Consistent response envelope structure
[ ] Error responses include codes and actionable messages
[ ] Pagination on all list endpoints
[ ] Authentication/authorization documented
[ ] Rate limit headers defined
[ ] Versioning strategy documented
[ ] CORS configured for known origins
[ ] Idempotency keys for mutating operations
[ ] OpenAPI spec validates without errors
[ ] Examples for all request/response typesVersion: 1.1.0 Last Updated: 2026-04-18
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.