openapi-contract
OpenAPI contract validation between frontend and backend. Covers type sync, endpoint validation, and contract-first development. USE WHEN: user asks about "OpenAPI validation", "API contract", "swagger sync", "frontend backend types", "API mismatch", "contract testing" DO NOT USE FOR: GraphQL - use `graphql-contract` skill, authentication - use `auth-flow-validation` skill
What this skill does
# OpenAPI Contract Validation - Quick Reference
## When NOT to Use This Skill
- **GraphQL APIs** - Use `graphql-contract` skill
- **Authentication flows** - Use `auth-flow-validation` skill
- **API versioning strategy** - Use `api-versioning` skill
- **Type generation setup** - Use `type-generation` skill
> **Deep Knowledge**: Use `mcp__api-explorer__get_api_endpoint_details` for specific endpoint validation.
## Contract Validation Overview
```
┌─────────────────────────────────────────────────────────────┐
│ CONTRACT VALIDATION │
├─────────────────────────────────────────────────────────────┤
│ │
│ Frontend Code OpenAPI Spec Backend │
│ ┌──────────────┐ ┌────────────┐ ┌──────────────┐ │
│ │ fetch('/api/ │ ←──→ │ paths: │ ←──→│ @Controller │ │
│ │ users') │ │ /users: │ │ @GetMapping │ │
│ │ │ │ get: │ │ │ │
│ │ type User { │ ←──→ │ schemas: │ ←──→│ class UserDto│ │
│ │ id: number │ │ User: │ │ Long id │ │
│ │ } │ │ id:int │ │ │ │
│ └──────────────┘ └────────────┘ └──────────────┘ │
│ │
│ MUST MATCH SOURCE OF MUST MATCH │
│ TRUTH │
└─────────────────────────────────────────────────────────────┘
```
## Common Discrepancy Types
### 1. Path Mismatch
```yaml
# OpenAPI Spec
paths:
/users/{userId}: # Backend path
get: ...
# Frontend Code
fetch('/api/users/${id}') # Frontend uses different path!
```
**Detection:**
```bash
# Find API calls in frontend
grep -r "fetch\|axios\|http\." src/
# Compare with OpenAPI paths
# Use api-explorer to list paths
```
**Fix:** Update frontend to use correct path or configure base URL.
### 2. Type Mismatch
```yaml
# OpenAPI Spec
components:
schemas:
User:
properties:
age:
type: string # Backend uses string
# Frontend Code
interface User {
age: number; # Frontend expects number!
}
```
**Detection:**
```typescript
// Frontend type
interface CreateUserDto {
age: number; // MISMATCH
}
// Should be
interface CreateUserDto {
age: string; // Match OpenAPI spec
}
```
### 3. Required Field Missing
```yaml
# OpenAPI Spec
components:
schemas:
CreateUserRequest:
required:
- email
- name
- role # Required!
properties:
email: { type: string }
name: { type: string }
role: { type: string }
# Frontend Code
const payload = {
email: user.email,
name: user.name,
// role is missing! <-- Will fail validation
};
```
### 4. Response Structure Mismatch
```yaml
# OpenAPI Spec - Paginated response
paths:
/users:
get:
responses:
200:
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/User'
meta:
$ref: '#/components/schemas/PaginationMeta'
# Frontend Code - Expects array directly
const users: User[] = await response.json(); // WRONG!
// Should be
const { data, meta } = await response.json();
const users: User[] = data;
```
## Validation Checklist
### Per-Endpoint Validation
| Check | Frontend | Backend (OpenAPI) | Status |
|-------|----------|-------------------|--------|
| Path | `/api/users` | `/users` | MISMATCH |
| Method | POST | POST | OK |
| Content-Type | application/json | application/json | OK |
| Request Body | matches schema | CreateUserRequest | CHECK |
| Response Type | matches schema | User | CHECK |
| Status Codes | handles 400, 401 | 200, 400, 401, 500 | PARTIAL |
### Request Body Validation
```typescript
// OpenAPI Schema
interface CreateUserRequest {
email: string; // required
name: string; // required
age?: number; // optional
role: UserRole; // required, enum
}
// Validate frontend matches
interface FrontendPayload {
email: string; // OK - required
name: string; // OK - required
age?: number; // OK - optional
role: 'admin' | 'user'; // CHECK - enum values match?
}
```
### Response Handling Validation
```typescript
// OpenAPI Response
interface ApiResponse<T> {
data: T;
meta?: {
page: number;
total: number;
};
error?: {
code: string;
message: string;
};
}
// Frontend should handle all cases
async function fetchUsers(): Promise<User[]> {
const response = await fetch('/api/users');
if (!response.ok) {
const error = await response.json();
throw new ApiError(error.error.code, error.error.message);
}
const result: ApiResponse<User[]> = await response.json();
return result.data;
}
```
## Contract-First Development
### 1. Define OpenAPI Spec First
```yaml
# openapi.yaml
openapi: 3.0.3
info:
title: User API
version: 1.0.0
paths:
/users:
post:
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
description: User created
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
schemas:
CreateUserRequest:
type: object
required: [email, name]
properties:
email:
type: string
format: email
name:
type: string
minLength: 2
maxLength: 100
User:
type: object
properties:
id:
type: string
format: uuid
email:
type: string
name:
type: string
createdAt:
type: string
format: date-time
```
### 2. Generate Types for Both Ends
```bash
# Frontend (TypeScript)
npx openapi-typescript openapi.yaml -o src/api/types.ts
# Backend (Java/Spring)
npx @openapitools/openapi-generator-cli generate \
-i openapi.yaml \
-g spring \
-o generated/
```
### 3. Implement Against Generated Types
```typescript
// Frontend - uses generated types
import type { CreateUserRequest, User } from './api/types';
async function createUser(data: CreateUserRequest): Promise<User> {
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return response.json();
}
```
```java
// Backend - uses generated DTOs
@PostMapping("/users")
public ResponseEntity<User> createUser(
@Valid @RequestBody CreateUserRequest request) {
// Implementation uses generated types
}
```
## MCP api-explorer Usage
### Efficient Validation Queries
```typescript
// 1. Search for endpoint
await mcp__api_explorer__search_api({
query: "users",
searchIn: ["paths"],
limit: 10
});
// 2. Get specific endpoint details
await mcp__api_explorer__get_api_endpoint_details({
path: "/users",
method: "POST"
});
// 3. Get request/response schemas
await mcp__api_explorer__get_api_models({
model: "CreateUserRequest",
compact: true
});
```
### Avoid Token Waste
```typescript
// DON'T - Loads entire spec
await mcp__api_explorer__get_api_schema({ format: "full" });
// DO - Query specific endpoints
await mcp__api_explorer__get_api_endpoint_details({
path: "/users/{id}",
method: "GET"
});
```
## Automated Contract Testing
### Prism (Mock Server)
```bash
# Start mock server from OpenAPI spec
npx @stoplight/prism-cli mock openapi.yaml
# Run frontend tests against mock
npm test -- --api-url=http://localhost:4010
```
### Schemathesis (API Fuzzing)
```bash
# Test backend aRelated in Web Dev
generating-lwc-components
IncludedLightning Web Components with PICKLES methodology and 165-point scoring. Use this skill when the user creates or edits LWC components, builds wire service patterns, or writes Jest tests for LWC. TRIGGER when: user creates/edits LWC components, touches lwc/**/*.js, .html, .css, .js-meta.xml files, or asks about wire service, SLDS, or Jest LWC tests. DO NOT TRIGGER when: Apex classes (use generating-apex), Aura components, or Visualforce.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Set up queries with useQuery, mutations with useMutation, configure QueryClient caching strategies, implement optimistic updates, and handle infinite scroll with useInfiniteQuery. Use when: setting up data fetching in React projects, migrating from v4 to v5, or fixing object syntax required errors, query callbacks removed issues, cacheTime renamed to gcTime, isPending vs isLoading confusion, keepPreviousData removed problems.
document-processor-api
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
nutrient-document-processing
IncludedProcess documents with Nutrient DWS. Use when the user wants to generate PDFs from HTML or URLs, convert Office/images/PDFs, assemble or split packets, OCR scans, extract text/tables/key-value pairs, redact PII, watermark, sign, fill forms, optimize PDFs, or produce compliance outputs like PDF/A or PDF/UA. Triggers include convert to PDF, merge these PDFs, OCR this scan, extract tables, redact PII, sign this PDF, make this PDF/A, or linearize for web delivery.
tanstack-query
IncludedManage server state in React with TanStack Query v5. Covers useMutationState, simplified optimistic updates, throwOnError, network mode (offline/PWA), and infiniteQueryOptions. Use when setting up data fetching, fixing v4→v5 migration errors (object syntax, gcTime, isPending, keepPreviousData), or debugging SSR/hydration issues with streaming server components.
accelint-nextjs-best-practices
IncludedNext.js performance optimization and best practices. Use when writing Next.js code (App Router or Pages Router); implementing Server Components, Server Actions, or API routes; optimizing RSC serialization, data fetching, or server-side rendering; reviewing Next.js code for performance issues; fixing authentication in Server Actions; or implementing Suspense boundaries, parallel data fetching, or request deduplication.