agentleFS
kensauruskensaurus/skills/skills/design-api/SKILL.md

design-api

Skill9 starsChanged 42 days agoMITView on GitHub

Design REST and GraphQL APIs: naming, versioning, error shapes, auth. Use when "design an API", "create endpoints", "structure my API responses", "plan API architecture", "REST vs GraphQL", or "API contract".

6 other projects use a version of this, 1 of them edited.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

2 rules. 0 are common, 1 is distinctive, and 1 is very specific to this project.

  • 0

    Common

    Most of the 6 edited versions we read keep these.

  • 1

    Distinctive

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Use Supabase MCP to understand existing data structure:

    line 49
  2. Very specific:

    Use Grep to search for similar endpoints already implemented:

    line 67

“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

API Design Skill

Degree of freedom: MIXED. Resource model, error shape, and REST vs GraphQL [HIGH freedom]; pre-design docs/schema/grep [LOW freedom — run exactly].

Design clean, consistent, and developer-friendly APIs.

How to reason

  1. Survey — existing docs, schema, and similar endpoints
  2. Model — resources, relations, REST vs GraphQL
  3. Contract — paths, statuses, error shape, auth, pagination
  4. Check — naming matches this repo; no duplicate endpoint

Worked example

Survey: orders has user_id; no GET /users/:id/orders; clients use useQuery. Model: order is a nested user resource, not a /getUserOrders RPC. Contract: GET /users/:id/orders → { data, meta }; shared { error: { code, message, details } }. Check: plural kebab-case; list paginated; 401/404/422 only from the status table.

Self-critique before reporting

  • Pre-design stated — docs, schema, and similar endpoints were checked out loud
  • One error shape — every failure uses { error: { code, message, details } }
  • Lists paginate — no unbounded GET /resources
  • Right owner — live 4xx/5xx repro → debug-fe-be-integration; product scope still fuzzy → design-prd

Pre-design checks [LOW freedom — run exactly]

Before designing any API:

1. Check Existing API Documentation

  • The running backend's docs route (/api-docs, /docs, /swagger, /openapi.json)
  • The repo's API README or naming-conventions doc (grep naming under docs/ and src/api/)

2. Verify Database Schema

Use Supabase MCP to understand existing data structure:

-- Check table schema
SELECT column_name, data_type, is_nullable
FROM information_schema.columns WHERE table_name = 'your_table';

-- Check enum values
SELECT enum_range(NULL::your_enum_name);

-- Check foreign keys
SELECT tc.constraint_name, kcu.column_name, ccu.table_name AS foreign_table
FROM information_schema.table_constraints tc
JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name
JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name
WHERE tc.table_name = 'your_table' AND tc.constraint_type = 'FOREIGN KEY';

3. Check for Existing Endpoints

Use Grep to search for similar endpoints already implemented:

Grep: "router.get|router.post" to find existing route patterns
Grep: "useQuery|useMutation" to find existing frontend integrations

4. Verification Statement (REQUIRED)

Before designing, state:

"Pre-design check:
- Existing API docs reviewed: [YES/NO]
- Database schema verified: [tables/enums checked]
- Similar endpoints found: [list or none]
- Naming conventions confirmed: [YES/NO]"

REST API Design [HIGH freedom]

URL Structure

GET /resources # List
GET /resources/:id # Get one
POST /resources # Create
PUT /resources/:id # Replace
PATCH /resources/:id # Update
DELETE /resources/:id # Delete

Naming Conventions

DoDon't
/users/getUsers, /user-list
/users/:id/user/:id, /users/get/:id
/users/:id/orders/getUserOrders
Plural nounsVerbs, singular
kebab-casecamelCase, snake_case

Examples

GET /users # List users
GET /users/123 # Get user 123
GET /users/123/orders # User's orders
GET /users/123/orders/456 # Specific order
POST /users/123/orders # Create order for user

Request/Response Format [LOW freedom — run this shape]

Request Body

{
 "name": "John Doe",
 "email": "john@example.com",
 "role": "admin"
}

Successful Response

{
 "data": {
 "id": "123",
 "name": "John Doe",
 "email": "john@example.com",
 "createdAt": "2024-01-15T10:30:00Z"
 }
}

List Response (with pagination)

{
 "data": [
 { "id": "1", "name": "John" },
 { "id": "2", "name": "Jane" }
 ],
 "meta": {
 "total": 100,
 "page": 1,
 "perPage": 20,
 "totalPages": 5
 }
}

Error Response

{
 "error": {
 "code": "VALIDATION_ERROR",
 "message": "Invalid input data",
 "details": [
 { "field": "email", "message": "Invalid email format" },
 { "field": "name", "message": "Name is required" }
 ]
 }
}

HTTP Status Codes [LOW freedom — use this table]

Success (2xx)

CodeWhen to Use
200 OKGET, PUT, PATCH success
201 CreatedPOST created new resource
204 No ContentDELETE success, no body

Client Errors (4xx)

CodeWhen to Use
400 Bad RequestInvalid request body
401 UnauthorizedNot authenticated
403 ForbiddenAuthenticated but not allowed
404 Not FoundResource doesn't exist
409 ConflictResource conflict (duplicate)
422 UnprocessableValidation failed
429 Too ManyRate limited

Server Errors (5xx)

CodeWhen to Use
500 Internal ErrorUnexpected server error
502 Bad GatewayUpstream service failed
503 UnavailableService temporarily down

Query Parameters

Filtering

GET /users?role=admin
GET /users?role=admin&status=active
GET /orders?createdAfter=2024-01-01

Sorting

GET /users?sort=name # Ascending
GET /users?sort=-createdAt # Descending (prefix with -)
GET /users?sort=role,-name # Multiple fields

Pagination

GET /users?page=2&perPage=20
GET /users?offset=40&limit=20
GET /users?cursor=abc123 # Cursor-based

Field Selection

GET /users?fields=id,name,email
GET /users?include=orders,profile

Versioning

URL Path (Recommended)

GET /v1/users
GET /v2/users

Header

GET /users
Accept: application/vnd.api+json;version=2

Authentication

Bearer Token

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

API Key

X-API-Key: your-api-key
# or
?apiKey=your-api-key

Common Patterns

Bulk Operations

POST /users/bulk
{
 "create": [{ "name": "John" }, { "name": "Jane" }],
 "update": [{ "id": "1", "name": "Updated" }],
 "delete": ["2", "3"]
}

Search

POST /users/search
{
 "query": "john",
 "filters": { "role": "admin" },
 "sort": { "field": "name", "order": "asc" }
}

Actions (non-CRUD)

POST /orders/123/cancel
POST /users/123/verify-email
POST /payments/123/refund

API Design Checklist [LOW freedom — do not skip]

Consistency

  • Consistent naming conventions
  • Consistent response format
  • Consistent error format
  • Consistent pagination

Usability

  • Intuitive URLs
  • Clear documentation
  • Meaningful error messages
  • Sensible defaults

Security

  • Authentication required
  • Authorization checked
  • Input validation
  • Rate limiting

Performance

  • Pagination for lists
  • Field selection available
  • Efficient queries
  • Caching headers

Documentation Template

## Create User

Create a new user account.

**Endpoint:** `POST /users`

**Authentication:** Required (Bearer token)

**Request Body:**
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| name | string | Yes | User's full name |
| email | string | Yes | Valid email address |
| role | string | No | User role (default: "user") |

**Response:** `201 Created`
\`\`\`json
{
 "data": {
 "id": "123",
 "name": "John Doe",
 "email": "john@example.com",
 "role": "user",
 "createdAt": "2024-01-15T10:30:00Z"
 }
}
\`\`\`

**Errors:**
- `400` - Invalid request body
- `409` - Email already exists
- `422` - Validation failed

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.