# API Contract Sync Manager - Technical Reference This document provides technical details for working with OpenAPI and GraphQL specifications, including structure, breaking change patterns, and validation strategies. ## OpenAPI Specification Structure ### OpenAPI 3.0/3.1 Schema ```yaml openapi: 3.0.0 info: title: API Name version: 1.0.0 description: API description servers: - url: https://api.example.com/v1 paths: /users: get: summary: List users operationId: listUsers parameters: - name: limit in: query schema: type: integer responses: '200': description: Success content: application/json: schema: type: array items: $ref: '#/components/schemas/User' components: schemas: User: type: object required: - id - email properties: id: type: string format: uuid email: type: string format: email name: type: string securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT ``` ### Key OpenAPI Fields **info**: Metadata about the API - `title`: API name - `version`: Semantic version - `description`: Overview of API purpose **servers**: Base URLs for API - `url`: Full base URL - `description`: Environment name (optional) **paths**: API endpoints - Key is the path (e.g., `/users`, `/users/{id}`) - Operations: `get`, `post`, `put`, `patch`, `delete` **components**: Reusable definitions - `schemas`: Data models - `parameters`: Reusable parameters - `responses`: Reusable responses - `securitySchemes`: Auth methods ### OpenAPI Data Types | Type | Format | Description | Example | |------|--------|-------------|---------| | string | - | Text | "hello" | | string | date | ISO 8601 date | "2025-10-16" | | string | date-time | ISO 8601 timestamp | "2025-10-16T10:30:00Z" | | string | email | Email address | "user@example.com" | | string | uuid | UUID v4 | "123e4567-e89b..." | | integer | int32 | 32-bit integer | 42 | | integer | int64 | 64-bit integer | 9007199254740991 | | number | float | Floating point | 3.14 | | number | double | Double precision | 3.141592653589793 | | boolean | - | True/false | true | | array | - | List of items | [1, 2, 3] | | object | - | Key-value pairs | {"key": "value"} | ### OpenAPI References Use `$ref` to avoid duplication: ```yaml # Define once components: schemas: User: type: object properties: id: type: string # Reference multiple times paths: /users/{id}: get: responses: '200': content: application/json: schema: $ref: '#/components/schemas/User' /users: post: requestBody: content: application/json: schema: $ref: '#/components/schemas/User' ``` ## GraphQL Schema Structure ### GraphQL SDL (Schema Definition Language) ```graphql # Scalar types scalar DateTime scalar Email # Enum types enum UserRole { ADMIN MEMBER GUEST } # Object types type User { id: ID! email: Email! name: String role: UserRole! createdAt: DateTime! posts: [Post!]! } type Post { id: ID! title: String! content: String! author: User! published: Boolean! } # Input types (for mutations) input CreateUserInput { email: Email! name: String role: UserRole = MEMBER } # Query operations type Query { user(id: ID!): User users(limit: Int = 10, offset: Int = 0): [User!]! posts(authorId: ID): [Post!]! } # Mutation operations type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: ID!, input: UpdateUserInput!): User! deleteUser(id: ID!): Boolean! } # Subscription operations type Subscription { userCreated: User! postPublished: Post! } ``` ### GraphQL Type Modifiers | Modifier | Meaning | Example | |----------|---------|---------| | `Type` | Nullable | Can be `User` or `null` | | `Type!` | Non-null | Must be `User`, never `null` | | `[Type]` | Nullable list of nullable items | `[User]`, `null`, or `[User, null]` | | `[Type]!` | Non-null list of nullable items | `[User]` or `[User, null]` but never `null` | | `[Type!]` | Nullable list of non-null items | `[User]` or `null`, never `[User, null]` | | `[Type!]!` | Non-null list of non-null items | `[User]`, never `null` or `[User, null]` | ### GraphQL Directives ```graphql type User { id: ID! email: String! oldEmail: String @deprecated(reason: "Use 'email' field instead") internalId: String @internal } type Query { users: [User!]! @auth(requires: ADMIN) } ``` Common directives: - `@deprecated`: Mark field as deprecated - `@auth`, `@requires`: Custom authorization - `@skip`, `@include`: Conditional inclusion (query-side) ## Breaking Change Patterns ### OpenAPI Breaking Changes #### 1. Removed Endpoints ```yaml # Before paths: /users/{id}: delete: # ... # After paths: # /users/{id} delete operation removed ``` **Impact**: Clients calling DELETE /users/{id} will get 404 #### 2. Required Parameters Added ```yaml # Before parameters: - name: email in: query required: false # After parameters: - name: email in: query required: true # Changed to required ``` **Impact**: Existing calls without `email` parameter will fail validation #### 3. Parameter Type Changed ```yaml # Before parameters: - name: limit in: query schema: type: string # After parameters: - name: limit in: query schema: type: integer # Changed from string ``` **Impact**: Clients sending "10" as string may fail validation #### 4. Required Property Added to Request ```yaml # Before CreateUserRequest: type: object required: - email properties: email: type: string # After CreateUserRequest: type: object required: - email - role # New required field properties: email: type: string role: type: string ``` **Impact**: Requests without `role` field will be rejected #### 5. Response Property Removed ```yaml # Before User: properties: id: type: string email: type: string phone: type: string # After User: properties: id: type: string email: type: string # phone removed ``` **Impact**: Clients accessing `user.phone` will get undefined/null #### 6. Property Type Changed ```yaml # Before User: properties: id: type: string # After User: properties: id: type: integer # Changed type ``` **Impact**: Type mismatches in strongly-typed clients #### 7. Enum Values Removed ```yaml # Before UserRole: type: string enum: - admin - member - guest # After UserRole: type: string enum: - admin - member # guest removed ``` **Impact**: Requests with `role: "guest"` will fail validation ### GraphQL Breaking Changes #### 1. Field Removed from Type ```graphql # Before type User { id: ID! email: String! phone: String } # After type User { id: ID! email: String! # phone removed } ``` **Impact**: Queries requesting `phone` field will fail #### 2. Argument Added to Field ```graphql # Before type Query { users: [User!]! } # After type Query { users(role: UserRole!): [User!]! # New required argument } ``` **Impact**: Existing queries without `role` argument will fail #### 3. Non-Null Modifier Added ```graphql # Before type User { email: String } # After type User { email: String! # Now non-null } ``` **Impact**: Clients expecting nullable email may fail #### 4. Argument Type Changed ```graphql # Before type Query { user(id: String!): User } # After type Query { user(id: ID!): User # Changed from String to ID } ``` **Impact**: May cause validation issues depending on implementation #### 5. Field Type Changed ```graphql # Before type User { createdAt: String } # After type User { createdAt: DateTime! # Changed scalar type } ``` **Impact**: Clients expecting string format may break ### Non-Breaking Changes (Safe) #### OpenAPI Non-Breaking - ✓ Add new endpoint - ✓ Add optional parameter - ✓ Add optional request body property - ✓ Add response property - ✓ Make required field optional - ✓ Add new enum value - ✓ Expand validation (e.g., increase maxLength) - ✓ Add default values #### GraphQL Non-Breaking - ✓ Add new field to type - ✓ Add new type - ✓ Add new query/mutation - ✓ Add optional argument to field - ✓ Remove non-null modifier (make nullable) - ✓ Add value to enum - ✓ Deprecate field (with @deprecated) ## Validation Strategies ### OpenAPI Validation #### Structural Validation 1. **Schema adherence**: Validate against OpenAPI 3.0/3.1 spec 2. **Reference integrity**: Ensure all `$ref` point to valid schemas 3. **Required fields**: Check all required fields exist 4. **Type consistency**: Verify types match throughout #### Content Validation 1. **Descriptions**: All operations and schemas should have descriptions 2. **Examples**: Include request/response examples 3. **Error responses**: Document 4xx and 5xx responses 4. **Security**: All protected endpoints have security requirements 5. **Tags**: Operations grouped with consistent tags #### Common Issues to Check ```yaml # ❌ Bad: Missing description /users: get: responses: '200': description: Success # ✓ Good: Descriptive /users: get: summary: List all users description: Returns a paginated list of users with optional filtering responses: '200': description: Successfully retrieved user list ``` ### GraphQL Validation #### Schema Validation 1. **Type definitions**: All types properly defined 2. **Field types**: All fields reference valid types 3. **Arguments**: Argument types are valid scalars, enums, or input types 4. **Resolver coverage**: All fields have resolvers (implementation check) 5. **Circular references**: Detect and handle circular dependencies #### Naming Conventions - **Types**: PascalCase (e.g., `User`, `BlogPost`) - **Fields**: camelCase (e.g., `firstName`, `createdAt`) - **Enums**: UPPER_SNAKE_CASE (e.g., `USER_ROLE`, `POST_STATUS`) - **Arguments**: camelCase (e.g., `userId`, `includeDeleted`) #### Common Issues ```graphql # ❌ Bad: Query returns nullable when it shouldn't type Query { user(id: ID!): User # Could return null } # ✓ Good: Clear nullability type Query { user(id: ID!): User # Can return null if not found requireUser(id: ID!): User! # Always returns user or throws error } ``` ## Type Generation Strategies ### OpenAPI to TypeScript #### Basic Type Mapping ```typescript // OpenAPI schema { "type": "object", "required": ["id", "email"], "properties": { "id": { "type": "string", "format": "uuid" }, "email": { "type": "string", "format": "email" }, "name": { "type": "string" }, "age": { "type": "integer" } } } // Generated TypeScript interface User { id: string; // uuid format → string email: string; // email format → string name?: string; // optional → ? age?: number; // integer → number } ``` #### Union Types from oneOf ```yaml # OpenAPI PaymentMethod: oneOf: - $ref: '#/components/schemas/CreditCard' - $ref: '#/components/schemas/BankAccount' ``` ```typescript // TypeScript type PaymentMethod = CreditCard | BankAccount; ``` #### Enum Mapping ```yaml # OpenAPI UserRole: type: string enum: - admin - member - guest ``` ```typescript // TypeScript enum UserRole { Admin = 'admin', Member = 'member', Guest = 'guest' } // or type UserRole = 'admin' | 'member' | 'guest'; ``` ### GraphQL to TypeScript ```graphql # GraphQL type User { id: ID! email: String! name: String posts: [Post!]! } ``` ```typescript // TypeScript interface User { id: string; // ID! → string email: string; // String! → string name: string | null; // String → string | null posts: Post[]; // [Post!]! → Post[] } ``` ## Validation Tools Integration ### Spectral (OpenAPI) ```bash # Install npm install -g @stoplight/spectral-cli # Validate spectral lint openapi.yaml # Custom ruleset spectral lint openapi.yaml --ruleset .spectral.yaml ``` ### GraphQL Inspector ```bash # Install npm install -g @graphql-inspector/cli # Validate schema graphql-inspector validate schema.graphql # Compare schemas graphql-inspector diff old.graphql new.graphql # Coverage check graphql-inspector coverage schema.graphql documents/*.graphql ``` ### OpenAPI Diff ```bash # Install npm install -g openapi-diff # Compare versions openapi-diff old.yaml new.yaml # Output markdown report openapi-diff old.yaml new.yaml --format markdown > changes.md ``` ## Security Considerations ### OpenAPI Security 1. **Authentication**: Always define security schemes 2. **Authorization**: Document which roles can access endpoints 3. **Sensitive data**: Mark PII fields in schemas 4. **Rate limiting**: Document rate limit headers 5. **HTTPS only**: Use https:// in server URLs ### GraphQL Security 1. **Query depth limiting**: Prevent deeply nested queries 2. **Query cost analysis**: Limit expensive operations 3. **Field-level auth**: Use directives like @auth 4. **Input validation**: Validate all arguments 5. **Disable introspection**: In production environments ## Best Practices Summary ### OpenAPI - Use semantic versioning in `info.version` - Group related operations with tags - Always include request/response examples - Document all error responses (4xx, 5xx) - Use `$ref` to keep specs DRY - Validate specs in CI/CD pipeline ### GraphQL - Use meaningful type and field names - Add descriptions to all types and fields - Use custom scalars for validated types (Email, URL, etc.) - Implement pagination for list fields - Use @deprecated instead of removing fields - Version schema with additive changes only ### Both - Automate validation in CI/CD - Generate client code from specs - Keep specs in version control - Review API changes in pull requests - Maintain changelog of API versions - Test generated client code