Rust api design
Use when designing REST API endpoints, URL structure, HTTP methods, status codes, request/response formats, pagination, SSE streaming, or OpenAPI docs in Axum.From its SKILL.md
npx -y skills add longzhi/rust-coding-standards --skill rust-api-designAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
3.6 KB, as published. Nobody here has run it
Rust API Design Standards
API Versioning
Use URL path versioning as the default strategy:
/v1/orders
/v1/products/{id}
- Prefix all API routes with
/v1/ - Bump the version only for breaking changes (field removal, type change, behavioral change)
- Non-breaking additions (new optional fields, new endpoints) stay in the current version
- When introducing
/v2/, keep/v1/available for a documented deprecation period
URL Design
GET /v1/orders
POST /v1/orders
GET /v1/orders/{id}
PATCH /v1/orders/{id}
DELETE /v1/orders/{id}
Rules:
- Plural nouns:
ordersnotorder - kebab-case for multi-word paths:
api-keysnotapiKeys - Nesting no more than two levels deep:
/v1/users/{id}/orders
Action Endpoints (Exception)
Use only when the operation cannot be mapped to a standard resource operation:
POST /v1/auth/login
POST /v1/orders/{id}/cancel
POST /v1/payments/{id}/refund
HTTP Methods
| Method | Idempotent | Usage |
|---|---|---|
| GET | Yes | Retrieve a resource |
| POST | No | Create a resource / execute an action |
| PATCH | Depends | Partial update (idempotent if setting absolute values; not idempotent if using relative operations like increment) |
| DELETE | Yes | Delete a resource |
POST idempotency: Use Idempotency-Key header for operations that must not be duplicated (e.g., payment processing).
Request/Response Format
Field names: snake_case
Enum values: snake_case
{
"order_type": "bulk_purchase",
"status": "in_progress"
}
List Response
{
"data": [...],
"pagination": {
"total": 100,
"limit": 20,
"offset": 0,
"has_more": true
}
}
Error Response
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Account balance is too low to complete this purchase"
}
}
HTTP Status Codes
| Code | Usage |
|---|---|
| 200 | GET/PATCH success |
| 201 | POST created successfully |
| 204 | DELETE success (no body) |
| 400 | Malformed request |
| 401 | Unauthenticated |
| 403 | Forbidden (authenticated but not authorized) |
| 404 | Resource not found |
| 422 | Business rule validation failure |
| 429 | Rate limited |
| 500 | Internal server error |
Authentication
Authorization: Bearer <token>
All authenticated endpoints must validate the Bearer token. Return 401 for missing/invalid tokens and 403 for valid tokens with insufficient permissions.
SSE Streaming
GET /v1/orders/{id}/events
Accept: text/event-stream
event: progress
data: {"progress": 50}
event: complete
data: {"status": "completed"}
- Use SSE for server-to-client real-time updates
- Each event must have an
eventtype and JSONdatapayload - Include a heartbeat/keepalive comment (
: ping) at regular intervals to prevent connection timeouts
OpenAPI
Use utoipa crate for annotation-driven API documentation. Expose the generated spec at a well-known endpoint (e.g., GET /docs/openapi.json). Keep annotations co-located with handler functions.
Checklist
- All routes prefixed with version (
/v1/) - URLs use plural nouns + kebab-case
- Correct HTTP methods and status codes
-
snake_casefor both field names and enum values - List endpoints support pagination
- Error responses include
code+message - Bearer token authentication on protected endpoints
- SSE endpoints document their event types