agentleFS
mehdiozdemirmehdiozdemir/awesome-agent-skills/skills/api-designer/SKILL.md

api-designer

Skill2 starsChanged 10 months agoMITView on GitHub

Designs and reviews REST, GraphQL, and gRPC APIs following industry best practices. Use when creating new API endpoints, reviewing API contracts, generating OpenAPI/Swagger specifications, designing authentication flows, or optimizing API performance and developer experience.

  • Reads credentials

34 other projects use a version of this.

Adopted by

Most recently taken up by

Used with

Projects with it also use shopify-expert, monitoring-expert and 10 more.

Other files people use alongside this one.

Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
  • JeffallanSkill

    shopify-expert

    Builds and debugs Shopify themes (.liquid files, theme.json, sections), develops custom Shopify apps (shopify.app.toml, OAuth, webhooks), and implements Storefront API integrations for headless storefronts. Use when building or customizing Shopify themes, creating Hydrogen or custom React storefronts, developing Shopify apps, implementing checkout UI extensions or Shopify Functions, optimizing performance, or integrating third-party services. Invoke for Liquid templating, Storefront API, app development, checkout customization, Shopify Plus features, App Bridge, Polaris, or Shopify CLI workflows.

    Also in 7 projects that use this

  • JeffallanSkill

    monitoring-expert

    Configures monitoring systems, implements structured logging pipelines, creates Prometheus/Grafana dashboards, defines alerting rules, and instruments distributed tracing. Implements Prometheus/Grafana stacks, conducts load testing, performs application profiling, and plans infrastructure capacity. Use when setting up application monitoring, adding observability to services, debugging production issues with logs/metrics/traces, running load tests with k6 or Artillery, profiling CPU/memory bottlenecks, or forecasting capacity needs.

    Also in 9 projects that use this

  • +10 more from Jeffallan

The file

We split this skill into the rules it gives an agent

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

  • 0

    Common

    Most of the 33 edited versions we read keep these.

  • 2

    Distinctive

    This author's own choices. Worth a look.

  • 0

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When designing an API, provide:

    line 865
  2. Distinctive:

    Document as you design

    line 903

“Common” is measured: kept by at least 6 in 10 of the 33 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 Designer Skill

This skill helps design, review, and implement APIs following industry best practices. Use this whenever you need to create new APIs, review existing API designs, generate specifications, or improve API developer experience.

API Design Principles

1. REST API Fundamentals

PrincipleDescription
Resource-OrientedURLs represent resources, not actions
StatelessEach request contains all needed information
Uniform InterfaceConsistent patterns across endpoints
HATEOASResponses include navigation links
CacheableResponses indicate cacheability

2. HTTP Methods

MethodPurposeIdempotentSafeRequest Body
GETRead resource✅✅❌
POSTCreate resource❌❌✅
PUTReplace resource✅❌✅
PATCHPartial update❌❌✅
DELETERemove resource✅❌❌
HEADGet headers only✅✅❌
OPTIONSGet allowed methods✅✅❌

3. HTTP Status Codes

Success (2xx):

CodeMeaningUse Case
200OKSuccessful GET, PUT, PATCH
201CreatedSuccessful POST
202AcceptedAsync operation started
204No ContentSuccessful DELETE

Client Errors (4xx):

CodeMeaningUse Case
400Bad RequestInvalid input/validation error
401UnauthorizedMissing/invalid authentication
403ForbiddenValid auth but insufficient permissions
404Not FoundResource doesn't exist
405Method Not AllowedWrong HTTP method
409ConflictDuplicate/conflict with current state
422Unprocessable EntitySemantic validation error
429Too Many RequestsRate limit exceeded

Server Errors (5xx):

CodeMeaningUse Case
500Internal Server ErrorUnexpected server error
502Bad GatewayUpstream service error
503Service UnavailableMaintenance/overload
504Gateway TimeoutUpstream timeout

URL Design

Resource Naming Conventions

# ✅ GOOD - Nouns, plural, lowercase, hyphens
GET /api/v1/users
GET /api/v1/users/123
GET /api/v1/users/123/orders
GET /api/v1/order-items

# ❌ BAD - Verbs, singular, camelCase
GET /api/v1/getUser
GET /api/v1/User/123
GET /api/v1/createOrder
GET /api/v1/orderItems

Hierarchical Resources

# Parent-child relationships
GET /api/v1/users/123/orders              # User's orders
GET /api/v1/users/123/orders/456          # Specific order
GET /api/v1/users/123/orders/456/items    # Order items

# Limit nesting depth (max 2-3 levels)
# ❌ Too deep
GET /api/v1/users/123/orders/456/items/789/reviews

# ✅ Flatten with filters
GET /api/v1/reviews?order_item_id=789

Query Parameters

# Filtering
GET /api/v1/products?category=electronics&status=active

# Sorting (use + for asc, - for desc)
GET /api/v1/products?sort=-created_at,+name

# Pagination
GET /api/v1/products?page=2&per_page=20
GET /api/v1/products?offset=20&limit=20
GET /api/v1/products?cursor=eyJpZCI6MTIzfQ

# Field selection (sparse fieldsets)
GET /api/v1/users/123?fields=id,name,email

# Including related resources
GET /api/v1/orders/123?include=customer,items

Request/Response Design

Request Structure

// POST /api/v1/users
{
  "email": "user@example.com",
  "name": "John Doe",
  "password": "SecureP@ss123",
  "preferences": {
    "newsletter": true,
    "language": "en"
  }
}

Response Structure

// Standard response envelope
{
  "data": {
    "id": "usr_123abc",
    "type": "user",
    "attributes": {
      "email": "user@example.com",
      "name": "John Doe",
      "created_at": "2025-01-15T10:30:00Z"
    },
    "relationships": {
      "orders": {
        "links": {
          "related": "/api/v1/users/usr_123abc/orders"
        }
      }
    }
  },
  "meta": {
    "request_id": "req_xyz789"
  },
  "links": {
    "self": "/api/v1/users/usr_123abc"
  }
}

Collection Response with Pagination

{
  "data": [
    { "id": "usr_123", "name": "User 1" },
    { "id": "usr_456", "name": "User 2" }
  ],
  "meta": {
    "total_count": 150,
    "page": 2,
    "per_page": 20,
    "total_pages": 8
  },
  "links": {
    "self": "/api/v1/users?page=2&per_page=20",
    "first": "/api/v1/users?page=1&per_page=20",
    "prev": "/api/v1/users?page=1&per_page=20",
    "next": "/api/v1/users?page=3&per_page=20",
    "last": "/api/v1/users?page=8&per_page=20"
  }
}

Error Response

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "The request could not be validated",
    "details": [
      {
        "field": "email",
        "code": "INVALID_FORMAT",
        "message": "Email must be a valid email address"
      },
      {
        "field": "password",
        "code": "TOO_SHORT",
        "message": "Password must be at least 8 characters"
      }
    ],
    "request_id": "req_xyz789",
    "documentation_url": "https://api.example.com/docs/errors#VALIDATION_ERROR"
  }
}

Authentication & Authorization

Authentication Methods

# API Key (Header)
X-API-Key: sk_live_abc123xyz

# Bearer Token (JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

# Basic Auth (Not recommended for APIs)
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=

# OAuth 2.0 Token
Authorization: Bearer ACCESS_TOKEN

JWT Structure

// Header
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "key-id-123"
}

// Payload
{
  "sub": "usr_123abc",
  "iat": 1704963600,
  "exp": 1704967200,
  "iss": "https://api.example.com",
  "aud": "https://api.example.com",
  "scope": "read:users write:users",
  "roles": ["admin"],
  "email": "user@example.com"
}

OAuth 2.0 Flows

# Authorization Code Flow (Web Apps)
1. Redirect to: /oauth/authorize?client_id=X&redirect_uri=Y&scope=Z&state=random
2. User authenticates and consents
3. Redirect back with: ?code=AUTH_CODE&state=random
4. Exchange code: POST /oauth/token (grant_type=authorization_code)
5. Receive: access_token + refresh_token

# Client Credentials Flow (Machine-to-Machine)
POST /oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=read:data

# Token Refresh
POST /oauth/token
grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
&client_id=YOUR_CLIENT_ID

Versioning Strategies

URL Path Versioning (Recommended)

GET /api/v1/users
GET /api/v2/users

Header Versioning

GET /api/users
Accept: application/vnd.example.v1+json
X-API-Version: 1

Query Parameter Versioning

GET /api/users?version=1

Version Deprecation

// Response headers for deprecated version
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 31 Dec 2025 23:59:59 GMT
Link: <https://api.example.com/v2/users>; rel="successor-version"

// Response body warning
{
  "data": { ... },
  "warnings": [
    {
      "code": "DEPRECATED_VERSION",
      "message": "API v1 is deprecated. Please migrate to v2 by Dec 31, 2025.",
      "documentation_url": "https://docs.example.com/migration/v1-to-v2"
    }
  ]
}

OpenAPI Specification

Basic Structure

openapi: 3.1.0
info:
  title: User Management API
  description: API for managing users and their resources
  version: 1.0.0
  contact:
    name: API Support
    email: api-support@example.com
    url: https://example.com/support
  license:
    name: MIT
    url: https://opensource.org/licenses/MIT

servers:
  - url: https://api.example.com/v1
    description: Production
  - url: https://staging-api.example.com/v1
    description: Staging
  - url: http://localhost:3000/v1
    description: Local development

tags:
  - name: Users
    description: User management operations
  - name: Orders
    description: Order processing

security:
  - BearerAuth: []
  - ApiKeyAuth: []

Path Definition

paths:
  /users:
    get:
      summary: List all users
      description: Returns a paginated list of users
      operationId: listUsers
      tags:
        - Users
      parameters:
        - name: page
          in: query
          description: Page number
          schema:
            type: integer
            default: 1
            minimum: 1
        - name: per_page
          in: query
          description: Items per page
          schema:
            type: integer
            default: 20
            maximum: 100
        - name: status
          in: query
          description: Filter by status
          schema:
            type: string
            enum: [active, inactive, pending]
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UserList'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

    post:
      summary: Create a user
      description: Creates a new user account
      operationId: createUser
      tags:
        - Users
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
            examples:
              basic:
                summary: Basic user
                value:
                  email: user@example.com
                  name: John Doe
                  password: SecureP@ss123
      responses:
        '201':
          description: User created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          $ref: '#/components/responses/ValidationError'
        '409':
          description: Email already exists
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /users/{userId}:
    parameters:
      - name: userId
        in: path
        required: true
        description: User ID
        schema:
          type: string
          pattern: '^usr_[a-zA-Z0-9]+$'

    get:
      summary: Get user by ID
      operationId: getUser
      tags:
        - Users
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          $ref: '#/components/responses/NotFound'

    patch:
      summary: Update user
      operationId: updateUser
      tags:
        - Users
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdateUserRequest'
      responses:
        '200':
          description: User updated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'

    delete:
      summary: Delete user
      operationId: deleteUser
      tags:
        - Users
      responses:
        '204':
          description: User deleted
        '404':
          $ref: '#/components/responses/NotFound'

Schema Definitions

components:
  schemas:
    User:
      type: object
      required:
        - id
        - email
        - name
        - created_at
      properties:
        id:
          type: string
          pattern: '^usr_[a-zA-Z0-9]+$'
          example: usr_123abc
          readOnly: true
        email:
          type: string
          format: email
          example: user@example.com
        name:
          type: string
          minLength: 1
          maxLength: 100
          example: John Doe
        status:
          type: string
          enum: [active, inactive, pending]
          default: pending
        created_at:
          type: string
          format: date-time
          readOnly: true
        updated_at:
          type: string
          format: date-time
          readOnly: true

    CreateUserRequest:
      type: object
      required:
        - email
        - name
        - password
      properties:
        email:
          type: string
          format: email
        name:
          type: string
          minLength: 1
          maxLength: 100
        password:
          type: string
          minLength: 8
          maxLength: 128
          format: password
          writeOnly: true

    UpdateUserRequest:
      type: object
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 100
        status:
          type: string
          enum: [active, inactive]

    UserList:
      type: object
      properties:
        data:
          type: array
          items:
            $ref: '#/components/schemas/User'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
        links:
          $ref: '#/components/schemas/PaginationLinks'

    PaginationMeta:
      type: object
      properties:
        total_count:
          type: integer
        page:
          type: integer
        per_page:
          type: integer
        total_pages:
          type: integer

    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
            message:
              type: string
            details:
              type: array
              items:
                type: object
                properties:
                  field:
                    type: string
                  code:
                    type: string
                  message:
                    type: string
            request_id:
              type: string

  responses:
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: NOT_FOUND
              message: The requested resource was not found

    Unauthorized:
      description: Authentication required
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    ValidationError:
      description: Validation failed
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

    RateLimited:
      description: Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
        X-RateLimit-Remaining:
          schema:
            type: integer
        X-RateLimit-Reset:
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT

    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key

GraphQL API Design

Schema Definition

type Query {
  # Get single user
  user(id: ID!): User
  
  # List users with filtering and pagination
  users(
    filter: UserFilter
    pagination: PaginationInput
    orderBy: UserOrderBy
  ): UserConnection!
  
  # Current authenticated user
  me: User
}

type Mutation {
  createUser(input: CreateUserInput!): CreateUserPayload!
  updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
  deleteUser(id: ID!): DeleteUserPayload!
}

type User {
  id: ID!
  email: String!
  name: String!
  status: UserStatus!
  createdAt: DateTime!
  updatedAt: DateTime
  
  # Relationships
  orders(first: Int, after: String): OrderConnection!
  profile: UserProfile
}

enum UserStatus {
  ACTIVE
  INACTIVE
  PENDING
}

input UserFilter {
  status: UserStatus
  searchTerm: String
  createdAfter: DateTime
  createdBefore: DateTime
}

input PaginationInput {
  first: Int
  after: String
  last: Int
  before: String
}

input UserOrderBy {
  field: UserOrderField!
  direction: OrderDirection!
}

enum UserOrderField {
  CREATED_AT
  NAME
  EMAIL
}

enum OrderDirection {
  ASC
  DESC
}

# Relay-style connection
type UserConnection {
  edges: [UserEdge!]!
  pageInfo: PageInfo!
  totalCount: Int!
}

type UserEdge {
  node: User!
  cursor: String!
}

type PageInfo {
  hasNextPage: Boolean!
  hasPreviousPage: Boolean!
  startCursor: String
  endCursor: String
}

# Mutation payloads
input CreateUserInput {
  email: String!
  name: String!
  password: String!
}

type CreateUserPayload {
  user: User
  errors: [UserError!]
}

type UserError {
  field: String
  message: String!
  code: String!
}

Rate Limiting

Headers

X-RateLimit-Limit: 1000          # Max requests per window
X-RateLimit-Remaining: 999       # Remaining requests
X-RateLimit-Reset: 1704963600    # Unix timestamp when limit resets
Retry-After: 60                  # Seconds until retry (on 429)

Rate Limit Tiers

rate_limits:
  anonymous:
    requests_per_minute: 60
    requests_per_hour: 1000
  
  authenticated:
    requests_per_minute: 600
    requests_per_hour: 10000
  
  premium:
    requests_per_minute: 6000
    requests_per_hour: 100000

# Per-endpoint limits
endpoints:
  /auth/login:
    requests_per_minute: 5
    burst: 3
  
  /search:
    requests_per_minute: 30
  
  /export:
    requests_per_day: 10

API Design Checklist

Resource Design

  • Resources named with nouns (plural)
  • URL hierarchy reflects relationships
  • Consistent naming conventions
  • Max 2-3 nesting levels
  • ID format documented

Request/Response

  • Consistent response envelope
  • Proper status codes used
  • Error responses include details
  • Pagination implemented
  • Sorting/filtering supported

Security

  • Authentication required
  • Authorization enforced
  • Input validation
  • Rate limiting configured
  • HTTPS enforced

Documentation

  • OpenAPI spec complete
  • Examples provided
  • Error codes documented
  • Changelog maintained

Developer Experience

  • Consistent patterns
  • Helpful error messages
  • SDK/client examples
  • Sandbox environment

Output Format

When designing an API, provide:

## API Design Proposal

### Resource: [Resource Name]

#### Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | /resource | List all |
| POST | /resource | Create |
| GET | /resource/{id} | Get one |
| PATCH | /resource/{id} | Update |
| DELETE | /resource/{id} | Delete |

#### Request/Response Examples

[Include examples for each endpoint]

#### OpenAPI Specification

```yaml
[OpenAPI spec for the resource]

Implementation Notes

  • [Important consideration 1]
  • [Important consideration 2]

## Notes

- Design APIs for consumers, not implementation
- Consistency is more important than perfection
- Version from the start
- Document as you design
- Consider backwards compatibility
- Plan for deprecation

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.