OpenAPI Spec Patterns — API Spec Analysis Patterns Guide
Methodology for effectively analyzing OpenAPI/GraphQL/gRPC specs and extracting the metadata needed for SDK generation.
OpenAPI 3.x Analysis Procedure
1. Endpoint Grouping
# Tag-based grouping -> SDK class mapping
paths:
/users:
get:
tags: [Users] # -> UsersClient.list()
post:
tags: [Users] # -> UsersClient.create()
/users/{id}:
get:
tags: [Users] # -> UsersClient.get(id)
put:
tags: [Users] # -> UsersClient.update(id, data)
delete:
tags: [Users] # -> UsersClient.delete(id)
/users/{id}/orders:
get:
tags: [Users, Orders] # -> UsersClient.listOrders(id)
Mapping Rules
| HTTP Method |
Pattern |
SDK Method Name |
| GET /resources |
List |
list() |
| GET /resources/{id} |
Detail |
get(id) |
| POST /resources |
Create |
create(data) |
| PUT /resources/{id} |
Full update |
update(id, data) |
| PATCH /resources/{id} |
Partial update |
patch(id, data) |
| DELETE /resources/{id} |
Delete |
delete(id) |
| POST /resources/{id}/action |
Action |
actionName(id, data) |
2. Authentication Method Mapping
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
OAuth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.example.com/authorize
tokenUrl: https://auth.example.com/token
scopes:
read: Read access
write: Write access
| Auth Type |
SDK Implementation |
Code Pattern |
| Bearer |
Header interceptor |
Authorization: Bearer {token} |
| API Key |
Header/query interceptor |
X-API-Key: {key} |
| OAuth2 |
Token manager + refresh |
Auto refresh_token handling |
| Basic |
Header |
Authorization: Basic {base64} |
3. Pagination Pattern Detection
# Pattern 1: Offset-based
parameters:
- name: offset
in: query
schema: { type: integer }
- name: limit
in: query
schema: { type: integer, default: 20 }
# Pattern 2: Cursor-based
parameters:
- name: cursor
in: query
schema: { type: string }
- name: limit
in: query
schema: { type: integer }
# Pattern 3: Page-based
parameters:
- name: page
in: query
schema: { type: integer }
- name: per_page
in: query
schema: { type: integer }
| Detection Pattern |
SDK Implementation |
| offset/limit |
listAll() auto page traversal |
| cursor/after |
iterate() iterator |
| page/per_page |
listPage(page) |
| Link header |
HTTP Link header parsing |
4. Error Response Patterns
# Standard error structure extraction
responses:
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Error:
type: object
properties:
code: { type: string }
message: { type: string }
details: { type: array, items: { $ref: '#/components/schemas/ErrorDetail' } }
SDK Error Class Mapping
| HTTP Status |
SDK Exception |
Retry |
| 400 |
BadRequestError |
No |
| 401 |
AuthenticationError |
No (once after token refresh) |
| 403 |
PermissionError |
No |
| 404 |
NotFoundError |
No |
| 409 |
ConflictError |
No |
| 422 |
ValidationError |
No |
| 429 |
RateLimitError |
Yes (Retry-After) |
| 500 |
InternalError |
Yes (exponential backoff) |
| 502/503/504 |
ServiceUnavailableError |
Yes |
Schema Normalization
Circular Reference Handling
# Circular: User -> Order -> User
User:
properties:
orders:
type: array
items: { $ref: '#/components/schemas/Order' }
Order:
properties:
user: { $ref: '#/components/schemas/User' } # Circular!
# Resolution: Lazy Reference
# TypeScript: type User = { orders: () => Order[] }
# Python: User = ForwardRef('User')
allOf/oneOf/anyOf Interpretation
# allOf -> Intersection (inheritance/extension)
UpdateUser:
allOf:
- $ref: '#/components/schemas/BaseUser'
- type: object
properties:
password: { type: string }
# -> class UpdateUser extends BaseUser { password?: string }
# oneOf -> Union (exclusive choice)
Pet:
oneOf:
- $ref: '#/components/schemas/Cat'
- $ref: '#/components/schemas/Dog'
discriminator:
propertyName: petType
# -> type Pet = Cat | Dog (discriminated union)
# anyOf -> Flexible union
Filter:
anyOf:
- type: string
- type: integer
- type: array
items: { type: string }
# -> type Filter = string | number | string[]
GraphQL Schema Analysis
# Query -> SDK read methods
type Query {
user(id: ID!): User # -> client.users.get(id)
users(first: Int, after: String): UserConnection # -> client.users.list()
}
# Mutation -> SDK write methods
type Mutation {
createUser(input: CreateUserInput!): User # -> client.users.create(input)
updateUser(id: ID!, input: UpdateUserInput!): User
}
# Connection pattern -> Auto-pagination
type UserConnection {
edges: [UserEdge!]!
pageInfo: PageInfo!
}
gRPC Proto Analysis
service UserService {
rpc GetUser (GetUserRequest) returns (User); // -> client.getUser(id)
rpc ListUsers (ListUsersRequest) returns (ListUsersResponse);
rpc CreateUser (CreateUserRequest) returns (User);
rpc StreamUsers (StreamRequest) returns (stream User); // -> Streaming API
}
| gRPC Pattern |
SDK Implementation |
| Unary |
Standard async method |
| Server Stream |
AsyncIterator |
| Client Stream |
Stream send method |
| Bidirectional |
Bidirectional stream |