Install any skill in seconds. Free to start, no credit card required.
Get Started Free →REST API design best practices for consistent, intuitive APIs
.claude/skills/aiskillstore-api-design/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-03 | ✗→✓ | ▲ Improved | 40% | 0% |
| case-19 | ✓→✓ | = Same ✓ | 119% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 70% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 98% | 0% |
| case-07 | ✓→✓ | = Same ✓ | 474% | 0% |
Resource naming:
/users not /getUsers/users/{id}/users/{id}/postsHTTP methods:
GET: Retrieve resources (idempotent)POST: Create new resourcesPUT: Replace entire resourcePATCH: Partial updateDELETE: Remove resources (idempotent)Response codes:
200 OK: Success with response body201 Created: Resource created successfully204 No Content: Success with no response body400 Bad Request: Invalid input401 Unauthorized: Authentication required403 Forbidden: No permission404 Not Found: Resource doesn't exist409 Conflict: Resource conflict422 Unprocessable Entity: Validation failed500 Internal Server Error: Server errorExample REST endpoint:
GET /api/v1/users # List users
GET /api/v1/users/{id} # Get user
POST /api/v1/users # Create user
PUT /api/v1/users/{id} # Update user
PATCH /api/v1/users/{id} # Partial update
DELETE /api/v1/users/{id} # Delete userRequest example:
jsonPOST /api/v1/users Content-Type: application/json { "name": "John Doe", "email": "john@example.com", "role": "admin" }
Response example:
jsonHTTP/1.1 201 Created Content-Type: application/json Location: /api/v1/users/123 { "id": 123, "name": "John Doe", "email": "john@example.com", "role": "admin", "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-15T10:30:00Z" }
Error response format:
json{ "error": { "code": "VALIDATION_ERROR", "message": "Invalid input provided", "details": [ { "field": "email", "message": "Invalid email format" } ] } }
Query parameters:
GET /api/v1/users?page=2&limit=20&sort=-created_at&filter=role:adminResponse with pagination:
json{ "data": [...], "pagination": { "page": 2, "limit": 20, "total": 100, "pages": 5 }, "links": { "self": "/api/v1/users?page=2&limit=20", "first": "/api/v1/users?page=1&limit=20", "prev": "/api/v1/users?page=1&limit=20", "next": "/api/v1/users?page=3&limit=20", "last": "/api/v1/users?page=5&limit=20" } }
Options:
Example with JWT:
GET /api/v1/users
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...URL versioning (recommended):
/api/v1/users
/api/v2/usersHeader versioning:
GET /api/users
Accept: application/vnd.api+json; version=1Create OpenAPI 3.0 specification:
yamlopenapi: 3.0.0 info: title: User Management API version: 1.0.0 description: API for managing users servers: - url: https://api.example.com/v1 paths: /users: get: summary: List users parameters: - name: page in: query schema: type: integer default: 1 - name: limit in: query schema: type: integer default: 20 responses: '200': description: Successful response content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/User' post: summary: Create user requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UserCreate' responses: '201': description: User created content: application/json: schema: $ref: '#/components/schemas/User' components: schemas: User: type: object properties: id: type: integer name: type: string email: type: string format: email created_at: type: string format: date-time UserCreate: type: object required: - name - email properties: name: type: string email: type: string format: email
Filtering:
GET /api/v1/users?role=admin&status=activeSorting:
GET /api/v1/users?sort=-created_at,nameField selection:
GET /api/v1/users?fields=id,name,emailBatch operations:
POST /api/v1/users/batch
{
"operations": [
{"action": "create", "data": {...}},
{"action": "update", "id": 123, "data": {...}}
]
}If REST doesn't fit, consider GraphQL:
graphqltype User { id: ID! name: String! email: String! posts: [Post!]! createdAt: DateTime! } type Query { users(page: Int, limit: Int): [User!]! user(id: ID!): User } type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: ID!, input: UpdateUserInput!): User! deleteUser(id: ID!): Boolean! }
<!-- Add example content here -->
<!-- Add advanced example content here -->
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-04 | fail→fail | 16,431 | 17,662 | +7% | 1 | 1 | 0% | 2,214 | 4,063 | +84% | 0 | 0 | — |
case-19 | pass→pass | 15,956 | 45,030 | +182% | 1 | 1 | 0% | 1,837 | 4,021 | +119% | 0 | 0 | — |
case-01 | fail→fail | 26,895 | 26,266 | -2% | 1 | 1 | 0% | 4,984 | 7,718 | +55% | 0 | 0 | — |
case-02 | fail→fail | 28,331 | 28,956 | +2% | 1 | 1 | 0% | 6,617 | 7,743 | +17% | 0 | 0 | — |
case-03 | fail→pass | 30,584 | 36,601 | +20% | 1 | 1 | 0% | 6,334 | 8,869 | +40% | 0 | 0 | — |
case-05 | pass→pass | 31,757 | 11,351 | -64% | 1 | 1 | 0% | 2,459 | 4,178 | +70% | 0 | 0 | — |
case-06 | pass→pass | 53,916 | 11,408 | -79% | 1 | 1 | 0% | 1,570 | 3,101 | +98% | 0 | 0 | — |
case-07 | pass→pass | 2,794 | 8,174 | +193% | 1 | 1 | 0% | 463 | 2,659 | +474% | 0 | 0 | — |
case-08 | pass→pass | 4,433 | 8,823 | +99% | 1 | 1 | 0% | 755 | 2,326 | +208% | 0 | 0 | — |
case-09 | pass→pass | 32,831 | 16,496 | -50% | 1 | 1 | 0% | 1,783 | 3,504 | +97% | 0 | 0 | — |
case-10 | pass→pass | 28,001 | 8,589 | -69% | 1 | 1 | 0% | 1,080 | 2,731 | +153% | 0 | 0 | — |
case-11 | pass→pass | 17,764 | 14,238 | -20% | 1 | 1 | 0% | 2,530 | 3,789 | +50% | 0 | 0 | — |
case-12 | pass→pass | 13,749 | 22,062 | +60% | 1 | 1 | 0% | 1,681 | 3,591 | +114% | 0 | 0 | — |
case-13 | pass→pass | 15,885 | 19,060 | +20% | 1 | 1 | 0% | 2,417 | 3,465 | +43% | 0 | 0 | — |
case-14 | pass→pass | 14,260 | 9,452 | -34% | 1 | 1 | 0% | 1,562 | 2,755 | +76% | 0 | 0 | — |
case-15 | pass→pass | 32,420 | 9,407 | -71% | 1 | 1 | 0% | 1,870 | 2,775 | +48% | 0 | 0 | — |
case-16 | pass→pass | 30,702 | 28,203 | -8% | 1 | 1 | 0% | 2,438 | 4,325 | +77% | 0 | 0 | — |
case-17 | pass→pass | 12,712 | 23,412 | +84% | 1 | 1 | 0% | 1,348 | 3,248 | +141% | 0 | 0 | — |
case-18 | pass→pass | 28,236 | 35,616 | +26% | 1 | 1 | 0% | 2,681 | 4,781 | +78% | 0 | 0 | — |
case-20 | pass→pass | 36,577 | 14,530 | -60% | 1 | 1 | 0% | 2,396 | 3,966 | +66% | 0 | 0 | — |
case-21 | pass→pass | 38,654 | 35,384 | -8% | 1 | 1 | 0% | 2,786 | 5,335 | +91% | 0 | 0 | — |
case-22 | pass→pass | 42,730 | 39,264 | -8% | 1 | 1 | 0% | 2,822 | 5,689 | +102% | 0 | 0 | — |
case-23 | pass→pass | 58,948 | 11,858 | -80% | 1 | 1 | 0% | 1,554 | 3,178 | +105% | 0 | 0 | — |
case-24 | fail→fail | 12,702 | 14,732 | +16% | 1 | 1 | 0% | 812 | 3,087 | +280% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted. The headline lift of +4 percentage points is the difference between those two pass rates over the 24 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.