
Api Patterns
- 149 installs
- 8.1k repo stars
- Updated August 4, 2026
- vudovn/antigravity-kit
Use api-patterns for development tasks
About
api-patterns: A skill skill for development. This skill provides functionality for development workflows.
- api-patterns
Api Patterns by the numbers
- 149 all-time installs (skills.sh)
- +2 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #2,535 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vudovn/antigravity-kit --skill api-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 149 |
|---|---|
| repo stars | ★ 8.1k |
| Last updated | August 4, 2026 |
| Repository | vudovn/antigravity-kit ↗ |
What it does
Use api-patterns for development tasks
Files
API Patterns
API design principles and decision-making.
Learn to THINK, not copy fixed patterns.
🎯 Selective Reading Rule
Read ONLY files relevant to the request! Check the content map, find what you need.
---
📑 Content Map
| File | Description | When to Read |
|---|---|---|
api-style.md | REST vs GraphQL vs tRPC decision tree | Choosing API type |
rest.md | Resource naming, HTTP methods, status codes | Designing REST API |
response.md | Envelope pattern, error format, pagination | Response structure |
graphql.md | Schema design, when to use, security | Considering GraphQL |
trpc.md | TypeScript monorepo, type safety | TS fullstack projects |
versioning.md | URI/Header/Query versioning | API evolution planning |
auth.md | JWT, OAuth, Passkey, API Keys | Auth pattern selection |
rate-limiting.md | Token bucket, sliding window | API protection |
documentation.md | OpenAPI/Swagger best practices | Documentation |
security-testing.md | OWASP API Top 10, auth/authz testing | Security audits |
---
🔗 Related Skills
| Need | Skill |
|---|---|
| API implementation | @[skills/nodejs-best-practices] |
| Data structure | @[skills/database-design] |
| Security details | @[skills/vulnerability-scanner] |
---
✅ Decision Checklist
Before designing an API:
- [ ] Asked user about API consumers?
- [ ] Chosen API style for THIS context? (REST/GraphQL/tRPC)
- [ ] Defined consistent response format?
- [ ] Planned versioning strategy?
- [ ] Considered authentication needs?
- [ ] Planned rate limiting?
- [ ] Documentation approach defined?
---
❌ Anti-Patterns
DON'T:
- Default to REST for everything
- Use verbs in REST endpoints (/getUsers)
- Return inconsistent response formats
- Expose internal errors to clients
- Skip rate limiting
DO:
- Choose API style based on context
- Ask about client requirements
- Document thoroughly
- Use appropriate status codes
---
Script
| Script | Purpose | Command |
|---|---|---|
scripts/api_validator.py | API endpoint validation | python scripts/api_validator.py <project_path> |
API Style Selection
REST vs GraphQL vs tRPC - which one, when?
Decision Tree
Who are the API consumers?
│
├── Public API / Multiple platforms
│ └── REST + OpenAPI (widest compatibility)
│
├── Complex data needs / Multiple frontends
│ └── GraphQL (flexible queries)
│
├── TypeScript frontend + backend (monorepo)
│ └── tRPC (end-to-end type safety)
│
├── Real-time / Event-driven
│ └── WebSocket + AsyncAPI
│
└── Internal microservices
└── gRPC (performance) or REST (simplicity)Comparison
| Factor | REST | GraphQL | tRPC |
|---|---|---|---|
| Best for | Public APIs | Complex apps | TS monorepos |
| Learning curve | Low | Medium | Low (if TS) |
| Over/under fetching | Common | Solved | Solved |
| Type safety | Manual (OpenAPI) | Schema-based | Automatic |
| Caching | HTTP native | Complex | Client-based |
Selection Questions
1. Who are the API consumers? 2. Is the frontend TypeScript? 3. How complex are the data relationships? 4. Is caching critical? 5. Public or internal API?
Authentication Patterns
Choose auth pattern based on use case.
Selection Guide
| Pattern | Best For |
|---|---|
| JWT | Stateless, microservices |
| Session | Traditional web, simple |
| OAuth 2.0 | Third-party integration |
| API Keys | Server-to-server, public APIs |
| Passkey | Modern passwordless (2025+) |
JWT Principles
Important:
├── Always verify signature
├── Check expiration
├── Include minimal claims
├── Use short expiry + refresh tokens
└── Never store sensitive data in JWTAPI Documentation Principles
Good docs = happy developers = API adoption.
OpenAPI/Swagger Essentials
Include:
├── All endpoints with examples
├── Request/response schemas
├── Authentication requirements
├── Error response formats
└── Rate limiting infoGood Documentation Has
Essentials:
├── Quick start / Getting started
├── Authentication guide
├── Complete API reference
├── Error handling guide
├── Code examples (multiple languages)
└── ChangelogGraphQL Principles
Flexible queries for complex, interconnected data.
When to Use
✅ Good fit:
├── Complex, interconnected data
├── Multiple frontend platforms
├── Clients need flexible queries
├── Evolving data requirements
└── Reducing over-fetching matters
❌ Poor fit:
├── Simple CRUD operations
├── File upload heavy
├── HTTP caching important
└── Team unfamiliar with GraphQLSchema Design Principles
Principles:
├── Think in graphs, not endpoints
├── Design for evolvability (no versions)
├── Use connections for pagination
├── Be specific with types (not generic "data")
└── Handle nullability thoughtfullySecurity Considerations
Protect against:
├── Query depth attacks → Set max depth
├── Query complexity → Calculate cost
├── Batching abuse → Limit batch size
├── Introspection → Disable in productionRate Limiting Principles
Protect your API from abuse and overload.
Why Rate Limit
Protect against:
├── Brute force attacks
├── Resource exhaustion
├── Cost overruns (if pay-per-use)
└── Unfair usageStrategy Selection
| Type | How | When |
|---|---|---|
| Token bucket | Burst allowed, refills over time | Most APIs |
| Sliding window | Smooth distribution | Strict limits |
| Fixed window | Simple counters per window | Basic needs |
Response Headers
Include in headers:
├── X-RateLimit-Limit (max requests)
├── X-RateLimit-Remaining (requests left)
├── X-RateLimit-Reset (when limit resets)
└── Return 429 when exceededResponse Format Principles
Consistency is key - choose a format and stick to it.
Common Patterns
Choose one:
├── Envelope pattern ({ success, data, error })
├── Direct data (just return the resource)
└── HAL/JSON:API (hypermedia)Error Response
Include:
├── Error code (for programmatic handling)
├── User message (for display)
├── Details (for debugging, field-level errors)
├── Request ID (for support)
└── NOT internal details (security!)Pagination Types
| Type | Best For | Trade-offs |
|---|---|---|
| Offset | Simple, jumpable | Performance on large datasets |
| Cursor | Large datasets | Can't jump to page |
| Keyset | Performance critical | Requires sortable key |
Selection Questions
1. How large is the dataset? 2. Do users need to jump to specific pages? 3. Is data frequently changing?
REST Principles
Resource-based API design - nouns not verbs.
Resource Naming Rules
Principles:
├── Use NOUNS, not verbs (resources, not actions)
├── Use PLURAL forms (/users not /user)
├── Use lowercase with hyphens (/user-profiles)
├── Nest for relationships (/users/123/posts)
└── Keep shallow (max 3 levels deep)HTTP Method Selection
| Method | Purpose | Idempotent? | Body? |
|---|---|---|---|
| GET | Read resource(s) | Yes | No |
| POST | Create new resource | No | Yes |
| PUT | Replace entire resource | Yes | Yes |
| PATCH | Partial update | No | Yes |
| DELETE | Remove resource | Yes | No |
Status Code Selection
| Situation | Code | Why |
|---|---|---|
| Success (read) | 200 | Standard success |
| Created | 201 | New resource created |
| No content | 204 | Success, nothing to return |
| Bad request | 400 | Malformed request |
| Unauthorized | 401 | Missing/invalid auth |
| Forbidden | 403 | Valid auth, no permission |
| Not found | 404 | Resource doesn't exist |
| Conflict | 409 | State conflict (duplicate) |
| Validation error | 422 | Valid syntax, invalid data |
| Rate limited | 429 | Too many requests |
| Server error | 500 | Our fault |
#!/usr/bin/env python3
"""
API Validator - Checks API endpoints for best practices.
Validates OpenAPI specs, response formats, and common issues.
"""
import sys
import json
import re
from pathlib import Path
# Fix Windows console encoding for Unicode output
try:
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
sys.stderr.reconfigure(encoding='utf-8', errors='replace')
except AttributeError:
pass # Python < 3.7
def find_api_files(project_path: Path) -> list:
"""Find API-related files."""
patterns = [
"**/*api*.ts", "**/*api*.js", "**/*api*.py",
"**/routes/*.ts", "**/routes/*.js", "**/routes/*.py",
"**/controllers/*.ts", "**/controllers/*.js",
"**/endpoints/*.ts", "**/endpoints/*.py",
"**/*.openapi.json", "**/*.openapi.yaml",
"**/swagger.json", "**/swagger.yaml",
"**/openapi.json", "**/openapi.yaml"
]
files = []
for pattern in patterns:
files.extend(project_path.glob(pattern))
# Exclude node_modules, etc.
return [f for f in files if not any(x in str(f) for x in ['node_modules', '.git', 'dist', 'build', '__pycache__'])]
def check_openapi_spec(file_path: Path) -> dict:
"""Check OpenAPI/Swagger specification."""
issues = []
passed = []
try:
content = file_path.read_text(encoding='utf-8')
if file_path.suffix == '.json':
spec = json.loads(content)
else:
# Basic YAML check
if 'openapi:' in content or 'swagger:' in content:
passed.append("[OK] OpenAPI/Swagger version defined")
else:
issues.append("[X] No OpenAPI version found")
if 'paths:' in content:
passed.append("[OK] Paths section exists")
else:
issues.append("[X] No paths defined")
if 'components:' in content or 'definitions:' in content:
passed.append("[OK] Schema components defined")
return {'file': str(file_path), 'passed': passed, 'issues': issues, 'type': 'openapi'}
# JSON OpenAPI checks
if 'openapi' in spec or 'swagger' in spec:
passed.append("[OK] OpenAPI version defined")
if 'info' in spec:
if 'title' in spec['info']:
passed.append("[OK] API title defined")
if 'version' in spec['info']:
passed.append("[OK] API version defined")
if 'description' not in spec['info']:
issues.append("[!] API description missing")
if 'paths' in spec:
path_count = len(spec['paths'])
passed.append(f"[OK] {path_count} endpoints defined")
# Check each path
for path, methods in spec['paths'].items():
for method, details in methods.items():
if method in ['get', 'post', 'put', 'patch', 'delete']:
if 'responses' not in details:
issues.append(f"[X] {method.upper()} {path}: No responses defined")
if 'summary' not in details and 'description' not in details:
issues.append(f"[!] {method.upper()} {path}: No description")
except Exception as e:
issues.append(f"[X] Parse error: {e}")
return {'file': str(file_path), 'passed': passed, 'issues': issues, 'type': 'openapi'}
def check_api_code(file_path: Path) -> dict:
"""Check API code for common issues."""
issues = []
passed = []
try:
content = file_path.read_text(encoding='utf-8')
# Check for error handling
error_patterns = [
r'try\s*{', r'try:', r'\.catch\(',
r'except\s+', r'catch\s*\('
]
has_error_handling = any(re.search(p, content) for p in error_patterns)
if has_error_handling:
passed.append("[OK] Error handling present")
else:
issues.append("[X] No error handling found")
# Check for status codes
status_patterns = [
r'status\s*\(\s*\d{3}\s*\)', r'statusCode\s*[=:]\s*\d{3}',
r'HttpStatus\.', r'status_code\s*=\s*\d{3}',
r'\.status\(\d{3}\)', r'res\.status\('
]
has_status = any(re.search(p, content) for p in status_patterns)
if has_status:
passed.append("[OK] HTTP status codes used")
else:
issues.append("[!] No explicit HTTP status codes")
# Check for validation
validation_patterns = [
r'validate', r'schema', r'zod', r'joi', r'yup',
r'pydantic', r'@Body\(', r'@Query\('
]
has_validation = any(re.search(p, content, re.I) for p in validation_patterns)
if has_validation:
passed.append("[OK] Input validation present")
else:
issues.append("[!] No input validation detected")
# Check for auth middleware
auth_patterns = [
r'auth', r'jwt', r'bearer', r'token',
r'middleware', r'guard', r'@Authenticated'
]
has_auth = any(re.search(p, content, re.I) for p in auth_patterns)
if has_auth:
passed.append("[OK] Authentication/authorization detected")
# Check for rate limiting
rate_patterns = [r'rateLimit', r'throttle', r'rate.?limit']
has_rate = any(re.search(p, content, re.I) for p in rate_patterns)
if has_rate:
passed.append("[OK] Rate limiting present")
# Check for logging
log_patterns = [r'console\.log', r'logger\.', r'logging\.', r'log\.']
has_logging = any(re.search(p, content) for p in log_patterns)
if has_logging:
passed.append("[OK] Logging present")
except Exception as e:
issues.append(f"[X] Read error: {e}")
return {'file': str(file_path), 'passed': passed, 'issues': issues, 'type': 'code'}
def main():
target = sys.argv[1] if len(sys.argv) > 1 else "."
project_path = Path(target)
print("\n" + "=" * 60)
print(" API VALIDATOR - Endpoint Best Practices Check")
print("=" * 60 + "\n")
api_files = find_api_files(project_path)
if not api_files:
print("[!] No API files found.")
print(" Looking for: routes/, controllers/, api/, openapi.json/yaml")
sys.exit(0)
results = []
for file_path in api_files[:15]: # Limit
if 'openapi' in file_path.name.lower() or 'swagger' in file_path.name.lower():
result = check_openapi_spec(file_path)
else:
result = check_api_code(file_path)
results.append(result)
# Print results
total_issues = 0
total_passed = 0
for result in results:
print(f"\n[FILE] {result['file']} [{result['type']}]")
for item in result['passed']:
print(f" {item}")
total_passed += 1
for item in result['issues']:
print(f" {item}")
if item.startswith("[X]"):
total_issues += 1
print("\n" + "=" * 60)
print(f"[RESULTS] {total_passed} passed, {total_issues} critical issues")
print("=" * 60)
if total_issues == 0:
print("[OK] API validation passed")
sys.exit(0)
else:
print("[X] Fix critical issues before deployment")
sys.exit(1)
if __name__ == "__main__":
main()
API Security Testing
Principles for testing API security. OWASP API Top 10, authentication, authorization testing.
---
OWASP API Security Top 10
| Vulnerability | Test Focus |
|---|---|
| API1: BOLA | Access other users' resources |
| API2: Broken Auth | JWT, session, credentials |
| API3: Property Auth | Mass assignment, data exposure |
| API4: Resource Consumption | Rate limiting, DoS |
| API5: Function Auth | Admin endpoints, role bypass |
| API6: Business Flow | Logic abuse, automation |
| API7: SSRF | Internal network access |
| API8: Misconfiguration | Debug endpoints, CORS |
| API9: Inventory | Shadow APIs, old versions |
| API10: Unsafe Consumption | Third-party API trust |
---
Authentication Testing
JWT Testing
| Check | What to Test |
|---|---|
| Algorithm | None, algorithm confusion |
| Secret | Weak secrets, brute force |
| Claims | Expiration, issuer, audience |
| Signature | Manipulation, key injection |
Session Testing
| Check | What to Test |
|---|---|
| Generation | Predictability |
| Storage | Client-side security |
| Expiration | Timeout enforcement |
| Invalidation | Logout effectiveness |
---
Authorization Testing
| Test Type | Approach |
|---|---|
| Horizontal | Access peer users' data |
| Vertical | Access higher privilege functions |
| Context | Access outside allowed scope |
BOLA/IDOR Testing
1. Identify resource IDs in requests 2. Capture request with user A's session 3. Replay with user B's session 4. Check for unauthorized access
---
Input Validation Testing
| Injection Type | Test Focus |
|---|---|
| SQL | Query manipulation |
| NoSQL | Document queries |
| Command | System commands |
| LDAP | Directory queries |
Approach: Test all parameters, try type coercion, test boundaries, check error messages.
---
Rate Limiting Testing
| Aspect | Check |
|---|---|
| Existence | Is there any limit? |
| Bypass | Headers, IP rotation |
| Scope | Per-user, per-IP, global |
Bypass techniques: X-Forwarded-For, different HTTP methods, case variations, API versioning.
---
GraphQL Security
| Test | Focus |
|---|---|
| Introspection | Schema disclosure |
| Batching | Query DoS |
| Nesting | Depth-based DoS |
| Authorization | Field-level access |
---
Security Testing Checklist
Authentication:
- [ ] Test for bypass
- [ ] Check credential strength
- [ ] Verify token security
Authorization:
- [ ] Test BOLA/IDOR
- [ ] Check privilege escalation
- [ ] Verify function access
Input:
- [ ] Test all parameters
- [ ] Check for injection
Config:
- [ ] Check CORS
- [ ] Verify headers
- [ ] Test error handling
---
Remember: APIs are the backbone of modern apps. Test them like attackers will.
tRPC Principles
End-to-end type safety for TypeScript monorepos.
When to Use
✅ Perfect fit:
├── TypeScript on both ends
├── Monorepo structure
├── Internal tools
├── Rapid development
└── Type safety critical
❌ Poor fit:
├── Non-TypeScript clients
├── Public API
├── Need REST conventions
└── Multiple language backendsKey Benefits
Why tRPC:
├── Zero schema maintenance
├── End-to-end type inference
├── IDE autocomplete across stack
├── Instant API changes reflected
└── No code generation stepIntegration Patterns
Common setups:
├── Next.js + tRPC (most common)
├── Monorepo with shared types
├── Remix + tRPC
└── Any TS frontend + backendVersioning Strategies
Plan for API evolution from day one.
Decision Factors
| Strategy | Implementation | Trade-offs |
|---|---|---|
| URI | /v1/users | Clear, easy caching |
| Header | Accept-Version: 1 | Cleaner URLs, harder discovery |
| Query | ?version=1 | Easy to add, messy |
| None | Evolve carefully | Best for internal, risky for public |
Versioning Philosophy
Consider:
├── Public API? → Version in URI
├── Internal only? → May not need versioning
├── GraphQL? → Typically no versions (evolve schema)
├── tRPC? → Types enforce compatibilityRelated skills
Forks & variants (1)
Api Patterns has 1 known copy in the catalog totaling 20 installs. They canonicalize to this original listing.
- vudovn - 20 installs