| name | api-design |
| description | Applies REST and GraphQL design principles to produce or review an API contract. |
| version | 1.0.0 |
| tags | ["api","rest","graphql","design","contract"] |
| metadata | {"skill-author":"Marie-Lynne Block"} |
What this skill does
Applies REST and GraphQL design principles to produce or review an API contract. It covers resource modelling, URL conventions, HTTP semantics, request/response schemas, error formats, versioning strategy, and authentication patterns — producing OpenAPI-compatible snippets or GraphQL schema fragments.
When to use it
- User asks to "design an API", "review this API", or "define the endpoints for X".
- User wants to model resources and operations before writing implementation code.
- User needs an OpenAPI snippet or GraphQL schema fragment.
- User is establishing API conventions for a team or project.
Key concepts
REST principles
| Principle | Guidance |
|---|
| Resource naming | Nouns, plural, lowercase, hyphenated: /orders, /line-items. Never verbs in URLs. |
| HTTP methods | GET read, POST create, PUT full replace, PATCH partial update, DELETE remove |
| Idempotency | GET, PUT, DELETE must be idempotent. POST is not. PATCH should be designed to be. |
| Status codes | 200 OK, 201 Created, 204 No Content, 400 Bad Request, 401 Unauthorised, 403 Forbidden, 404 Not Found, 409 Conflict, 422 Unprocessable Entity, 500 Internal Server Error |
| Filtering/sorting | Query parameters: ?status=active&sort=created_at&order=desc&page=2&per_page=25 |
| Versioning | URI prefix (/v1/) for breaking changes; header versioning (Accept: application/vnd.api+json;version=2) for content negotiation |
Error response format
Consistent error bodies across all endpoints:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Human-readable description",
"details": [
{ "field": "email", "issue": "must be a valid email address" }
]
}
}
GraphQL conventions
- Operations:
query for reads, mutation for writes, subscription for real-time.
- Type names: PascalCase (
OrderLine). Field names: camelCase (lineItems).
- Always paginate list fields using Relay-style connections (
edges, node, pageInfo).
- Use input types for mutation arguments:
input CreateOrderInput { ... }.
- Return a result union for mutations:
type CreateOrderResult = Order | ValidationError.
Security checklist
Instructions
-
Identify the API type. REST or GraphQL? If not stated, recommend based on use case (REST for CRUD-heavy APIs, GraphQL for flexible querying across related data).
-
Model the resources or types. Identify the entities involved and their relationships. Name them clearly.
-
Define the operations. For REST: map resources to endpoints and HTTP methods. For GraphQL: define queries, mutations, and types.
-
Design request/response schemas. Specify field names, types, and validation rules. Call out optional vs. required fields.
-
Define the error contract. Consistent error format across all operations.
-
Address versioning and authentication. State the versioning strategy and authentication mechanism.
-
Flag design concerns. Identify any REST anti-patterns, N+1 risks (GraphQL), or security gaps.
-
Produce the output using the format below.
Output format
REST — OpenAPI snippet
openapi: 3.1.0
info:
title: [API name]
version: 1.0.0
paths:
/[resource]:
get:
summary: List [resources]
parameters:
- name: status
in: query
schema:
type: string
responses:
'200':
description: Success
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/[Resource]'
'401':
$ref: '#/components/responses/Unauthorised'
/[resource]/{id}:
get:
summary: Get [resource] by ID
parameters:
- name: id
in: path
required:
[]
[, ]
GraphQL — Schema fragment
type Query {
[resource](id: ID!): [Resource]
[resources](filter: [Resource]FilterInput, first: Int, after: String): [Resource]Connection!
}
type Mutation {
create[Resource](input: Create[Resource]Input!): Create[Resource]Result!
}
type [Resource] {
id: ID!
createdAt DateTime
CreateResource
CreateResourceResult Resource ValidationError
ValidationError
String
FieldError
Design notes
### Design decisions
- [Decision and rationale]
### Concerns / open questions
- [Anti-pattern, risk, or unresolved design question]
Examples
Example 1 — Order management REST API
Input: "Design a REST API for creating and managing orders. An order has line items, a customer, and a status."
Expected output: OpenAPI snippet with /orders (GET, POST) and /orders/{id} (GET, PATCH, DELETE) and /orders/{id}/line-items (GET, POST). Order schema with status enum. Error contract. Design note on whether to embed line items in the order response or use a separate endpoint.
Example 2 — GraphQL API review
Input: User shares a GraphQL schema where a User type has a posts field returning a plain list with no pagination.
Expected output: Concern flagged for missing pagination (N+1 and performance risk at scale). Suggested fix using Relay connection pattern. Note on missing input types for mutations.
Notes
- REST URLs identify resources, not actions. If a URL contains a verb (
/createOrder, /getUser), it is an anti-pattern — model it as a resource operation instead.
- GraphQL is not a replacement for REST in all cases: file uploads, caching, and simple CRUD are often better served by REST.
- OpenAPI snippets in this skill are illustrative, not exhaustive. A full spec requires
info, servers, and security sections.
- Do not design authentication schemes that store credentials in URLs (
?api_key=...) — they appear in server logs and browser history.