533 lines
12 KiB
Markdown
533 lines
12 KiB
Markdown
---
|
|
name: be-api-design
|
|
description: "Backend Agent uses this skill to design API specs. Based on PRD, produce OpenAPI 3.0 spec including endpoints, request/response structures, error handling. Trigger: After PRD approved (Stage 4)."
|
|
---
|
|
|
|
# /be-api-design — API Design
|
|
|
|
Backend Agent uses this skill to design API specs.
|
|
|
|
## Responsibilities
|
|
|
|
1. Analyze functional requirements from PRD
|
|
2. Use `design-an-interface` to explore multiple API design options
|
|
3. Design RESTful API endpoints
|
|
4. Define request/response schemas
|
|
5. Design error handling mechanism
|
|
6. Produce OpenAPI 3.0 spec
|
|
|
|
## Input
|
|
|
|
- PRD document (`docs/prd/{date}-{feature}.md`)
|
|
- Existing API style (existing API specs in project)
|
|
- Data model context
|
|
|
|
## Output
|
|
|
|
- API spec document: `docs/api/{date}-{feature}.yaml` (OpenAPI 3.0)
|
|
|
|
## Flow
|
|
|
|
```
|
|
Read PRD
|
|
↓
|
|
Identify resources and operations
|
|
↓
|
|
Call design-an-interface to explore 2-3 design options
|
|
↓
|
|
Select best option
|
|
↓
|
|
Define OpenAPI Schema
|
|
↓
|
|
Design error handling
|
|
↓
|
|
Security review
|
|
↓
|
|
Produce OpenAPI document
|
|
```
|
|
|
|
### Step Details
|
|
|
|
**1. Read PRD**
|
|
|
|
Extract all functional requirements from PRD, identify:
|
|
- Resources (nouns): users, orders, products, etc.
|
|
- Operations (verbs): create, read, update, delete, etc.
|
|
- Relationships: relationships between resources (one-to-many, many-to-many)
|
|
- Non-functional requirements: pagination, rate limiting, authentication, etc.
|
|
|
|
**2. Identify Resources and Operations**
|
|
|
|
Map functional requirements to RESTful resources:
|
|
- Each noun → potential resource
|
|
- Each verb → HTTP method
|
|
- Each relationship → nested resource or standalone endpoint
|
|
|
|
**3. Call design-an-interface**
|
|
|
|
Use `design-an-interface` skill to generate 2-3 distinct API design options:
|
|
- Option A: Minimize method count (1-3 endpoints per resource)
|
|
- Option B: Maximize flexibility (support multiple use cases)
|
|
- Option C: Optimize for most common operations
|
|
|
|
Compare pros and cons, select best design.
|
|
|
|
**4. Define OpenAPI Schema**
|
|
|
|
Use template below to produce complete OpenAPI 3.0 spec.
|
|
|
|
**5. Security Review**
|
|
|
|
Ensure all endpoints have appropriate authentication and permission controls.
|
|
|
|
**6. Produce Document**
|
|
|
|
Save to `docs/api/{date}-{feature}.yaml`.
|
|
|
|
## Design Principles
|
|
|
|
### RESTful Design
|
|
|
|
```yaml
|
|
Resource-oriented:
|
|
- URL represents resource, not action
|
|
- HTTP methods represent actions
|
|
|
|
Example:
|
|
GET /api/v1/users # List users
|
|
GET /api/v1/users/{id} # Get specific user
|
|
POST /api/v1/users # Create user
|
|
PUT /api/v1/users/{id} # Full update
|
|
PATCH /api/v1/users/{id} # Partial update
|
|
DELETE /api/v1/users/{id} # Delete user
|
|
|
|
Nested resources:
|
|
GET /api/v1/users/{id}/orders # Get user's orders
|
|
POST /api/v1/users/{id}/orders # Create order for user
|
|
```
|
|
|
|
### HTTP Status Codes
|
|
|
|
```yaml
|
|
Success:
|
|
200: OK # GET, PUT, PATCH, DELETE success
|
|
201: Created # POST successfully created resource
|
|
204: No Content # DELETE success, no response body
|
|
|
|
Client Error:
|
|
400: Bad Request # Request format error
|
|
401: Unauthorized # Not authenticated
|
|
403: Forbidden # No permission
|
|
404: Not Found # Resource not found
|
|
409: Conflict # Resource conflict (e.g., duplicate)
|
|
422: Unprocessable Entity # Validation error
|
|
429: Too Many Requests # Rate limit
|
|
|
|
Server Error:
|
|
500: Internal Server Error # Server internal error
|
|
502: Bad Gateway # Upstream service error
|
|
503: Service Unavailable # Service temporarily unavailable
|
|
```
|
|
|
|
### Response Format
|
|
|
|
```yaml
|
|
Success response:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
meta:
|
|
type: object
|
|
properties:
|
|
page:
|
|
type: integer
|
|
limit:
|
|
type: integer
|
|
total:
|
|
type: integer
|
|
total_pages:
|
|
type: integer
|
|
|
|
Error response:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
message:
|
|
type: string
|
|
details:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
field:
|
|
type: string
|
|
message:
|
|
type: string
|
|
```
|
|
|
|
## OpenAPI 3.0 Template
|
|
|
|
```yaml
|
|
openapi: 3.0.3
|
|
info:
|
|
title: {API Name}
|
|
version: 1.0.0
|
|
description: |
|
|
{Description}
|
|
|
|
Related PRD: {PRD Link}
|
|
|
|
servers:
|
|
- url: https://api.example.com/v1
|
|
description: Production
|
|
- url: https://staging-api.example.com/v1
|
|
description: Staging
|
|
|
|
paths:
|
|
/users:
|
|
get:
|
|
summary: List users
|
|
tags:
|
|
- Users
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
maximum: 100
|
|
- name: search
|
|
in: query
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Success
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UserListResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'500':
|
|
$ref: '#/components/responses/InternalError'
|
|
|
|
post:
|
|
summary: Create user
|
|
tags:
|
|
- Users
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CreateUserRequest'
|
|
responses:
|
|
'201':
|
|
description: Created successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UserResponse'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'422':
|
|
$ref: '#/components/responses/ValidationError'
|
|
|
|
/users/{id}:
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
|
|
get:
|
|
summary: Get user
|
|
tags:
|
|
- Users
|
|
responses:
|
|
'200':
|
|
description: Success
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UserResponse'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
put:
|
|
summary: Full update user
|
|
tags:
|
|
- Users
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateUserRequest'
|
|
responses:
|
|
'200':
|
|
description: Updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UserResponse'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
'422':
|
|
$ref: '#/components/responses/ValidationError'
|
|
|
|
patch:
|
|
summary: Partial update user
|
|
tags:
|
|
- Users
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PatchUserRequest'
|
|
responses:
|
|
'200':
|
|
description: Updated successfully
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UserResponse'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
delete:
|
|
summary: Delete user
|
|
tags:
|
|
- Users
|
|
responses:
|
|
'204':
|
|
description: Deleted successfully
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
components:
|
|
schemas:
|
|
User:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
example: "usr_123456"
|
|
email:
|
|
type: string
|
|
format: email
|
|
example: "user@example.com"
|
|
name:
|
|
type: string
|
|
example: "John Doe"
|
|
status:
|
|
type: string
|
|
enum: [active, inactive, suspended]
|
|
example: "active"
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
required:
|
|
- id
|
|
- email
|
|
- name
|
|
- status
|
|
- created_at
|
|
- updated_at
|
|
|
|
CreateUserRequest:
|
|
type: object
|
|
properties:
|
|
email:
|
|
type: string
|
|
format: email
|
|
password:
|
|
type: string
|
|
minLength: 8
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 100
|
|
required:
|
|
- email
|
|
- password
|
|
- name
|
|
|
|
UpdateUserRequest:
|
|
type: object
|
|
properties:
|
|
email:
|
|
type: string
|
|
format: email
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 100
|
|
status:
|
|
type: string
|
|
enum: [active, inactive]
|
|
|
|
PatchUserRequest:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 100
|
|
status:
|
|
type: string
|
|
enum: [active, inactive]
|
|
|
|
UserResponse:
|
|
type: object
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/User'
|
|
|
|
UserListResponse:
|
|
type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/User'
|
|
meta:
|
|
type: object
|
|
properties:
|
|
page:
|
|
type: integer
|
|
limit:
|
|
type: integer
|
|
total:
|
|
type: integer
|
|
total_pages:
|
|
type: integer
|
|
|
|
Error:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: string
|
|
message:
|
|
type: string
|
|
details:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
field:
|
|
type: string
|
|
message:
|
|
type: string
|
|
|
|
responses:
|
|
BadRequest:
|
|
description: Request format error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
Unauthorized:
|
|
description: Not authenticated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
NotFound:
|
|
description: Resource not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
ValidationError:
|
|
description: Validation error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
InternalError:
|
|
description: Server internal error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
|
|
security:
|
|
- bearerAuth: []
|
|
```
|
|
|
|
## Design Checklist
|
|
|
|
### Security
|
|
- [ ] All endpoints have appropriate authentication
|
|
- [ ] Input validation complete
|
|
- [ ] Rate limiting designed
|
|
- [ ] CORS configured
|
|
|
|
### Performance
|
|
- [ ] Pagination support
|
|
- [ ] Caching strategy
|
|
- [ ] Batch operation support
|
|
|
|
### Reliability
|
|
- [ ] Error response format unified
|
|
- [ ] Retry mechanism recommendations
|
|
- [ ] Idempotency design
|
|
|
|
### Consistency
|
|
- [ ] Naming convention consistent (resources use plural nouns)
|
|
- [ ] Response format consistent (data/meta/error structure)
|
|
- [ ] Filter/sort/pagination parameters consistent
|
|
|
|
## Related Skills
|
|
|
|
- **Prerequisite**: `write-a-prd` (after PRD approved)
|
|
- **辅助**: `design-an-interface` (explore multiple design options)
|
|
- **Follow-up**: `dba-schema` (DB Schema design)
|
|
- **Rollback**: Can rollback to `write-a-prd` to modify requirements
|
|
|
|
## Rollback Mechanism
|
|
|
|
```
|
|
Design Review rejects API design
|
|
↓
|
|
Modify OpenAPI spec
|
|
↓
|
|
Re-submit (or re-call design-an-interface)
|
|
|
|
DBA Agent finds Schema conflict
|
|
↓
|
|
Negotiate domain model or API response format adjustments
|
|
↓
|
|
Update OpenAPI spec
|
|
```
|