skills/export-openapi/SKILL.md
Generate OpenAPI 3.0 specification from blueprint API documentation. Creates interactive API docs that can be imported into Postman, Swagger UI, and other API testing tools.
npx skillsauth add navraj007in/architecture-cowork-plugin export-openapiInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Convert your architecture blueprint's API specification into an OpenAPI 3.0 document for interactive API documentation and testing.
Perfect for: API documentation, frontend/mobile dev handoff, API testing, client SDK generation
Use this skill when you need to:
Input: Architecture blueprint (Section 6: API Specification)
Output: openapi.yaml (OpenAPI 3.0 spec)
openapi.yaml:
openapi: 3.0.3
info:
title: Acme Ticketing API
description: Customer support ticketing platform API
version: 1.0.0
contact:
name: API Support
email: [email protected]
license:
name: MIT
servers:
- url: https://api.acme.com/v1
description: Production
- url: https://staging-api.acme.com/v1
description: Staging
- url: http://localhost:3000/v1
description: Local Development
tags:
- name: Authentication
description: User authentication and authorization
- name: Tickets
description: Ticket management operations
- name: Users
description: User management operations
- name: Workspaces
description: Workspace/tenant management
paths:
/auth/signup:
post:
summary: Create new user account
description: Register a new user and create their workspace
operationId: createUser
tags:
- Authentication
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SignupRequest'
examples:
basic:
value:
email: [email protected]
password: SecurePass123!
workspaceName: Acme Corp
responses:
'201':
description: User created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/AuthResponse'
examples:
success:
value:
user:
id: usr_abc123
email: [email protected]
workspaceId: ws_xyz789
accessToken: eyJhbGc...
refreshToken: eyJhbGc...
'400':
$ref: '#/components/responses/BadRequest'
'409':
description: Email already exists
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
duplicate:
value:
error: email_exists
message: Email already registered
'429':
$ref: '#/components/responses/RateLimitExceeded'
/tickets:
get:
summary: List tickets
description: Retrieve tickets for current workspace with filtering and pagination
operationId: listTickets
tags:
- Tickets
security:
- bearerAuth: []
parameters:
- name: status
in: query
schema:
type: string
enum: [OPEN, IN_PROGRESS, RESOLVED, CLOSED]
description: Filter by ticket status
- name: assigneeId
in: query
schema:
type: string
description: Filter by assigned user ID
- name: page
in: query
schema:
type: integer
minimum: 1
default: 1
description: Page number
- name: limit
in: query
schema:
type: integer
minimum: 1
maximum: 100
default: 20
description: Items per page
- name: sort
in: query
schema:
type: string
enum: [createdAt, updatedAt, priority]
default: createdAt
description: Sort field
- name: order
in: query
schema:
type: string
enum: [asc, desc]
default: desc
description: Sort order
responses:
'200':
description: Tickets retrieved successfully
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/Ticket'
pagination:
$ref: '#/components/schemas/Pagination'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
post:
summary: Create ticket
description: Create a new support ticket
operationId: createTicket
tags:
- Tickets
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTicketRequest'
responses:
'201':
description: Ticket created successfully
content:
application/json:
schema:
$ref: '#/components/schemas/Ticket'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: JWT token from /auth/login or /auth/signup
schemas:
SignupRequest:
type: object
required:
- email
- password
- workspaceName
properties:
email:
type: string
format: email
example: [email protected]
password:
type: string
format: password
minLength: 8
example: SecurePass123!
workspaceName:
type: string
minLength: 1
maxLength: 100
example: Acme Corp
AuthResponse:
type: object
properties:
user:
$ref: '#/components/schemas/User'
accessToken:
type: string
description: JWT access token (expires in 15 minutes)
refreshToken:
type: string
description: Refresh token (expires in 30 days)
User:
type: object
properties:
id:
type: string
example: usr_abc123
email:
type: string
format: email
name:
type: string
nullable: true
role:
type: string
enum: [ADMIN, AGENT, VIEWER]
workspaceId:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
Ticket:
type: object
properties:
id:
type: string
example: tkt_xyz789
workspaceId:
type: string
title:
type: string
description:
type: string
status:
type: string
enum: [OPEN, IN_PROGRESS, RESOLVED, CLOSED]
priority:
type: string
enum: [LOW, MEDIUM, HIGH, URGENT]
assigneeId:
type: string
nullable: true
createdBy:
type: string
createdAt:
type: string
format: date-time
updatedAt:
type: string
format: date-time
CreateTicketRequest:
type: object
required:
- title
- description
properties:
title:
type: string
minLength: 1
maxLength: 200
description:
type: string
minLength: 1
priority:
type: string
enum: [LOW, MEDIUM, HIGH, URGENT]
default: MEDIUM
assigneeId:
type: string
nullable: true
Pagination:
type: object
properties:
page:
type: integer
limit:
type: integer
total:
type: integer
totalPages:
type: integer
Error:
type: object
properties:
error:
type: string
description: Error code
message:
type: string
description: Human-readable error message
details:
type: object
nullable: true
description: Additional error details
responses:
BadRequest:
description: Invalid request parameters
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
validation:
value:
error: validation_error
message: Invalid request parameters
details:
email: Invalid email format
Unauthorized:
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
missing_token:
value:
error: unauthorized
message: Authentication token required
Forbidden:
description: Insufficient permissions
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
access_denied:
value:
error: forbidden
message: Insufficient permissions to access this resource
RateLimitExceeded:
description: Rate limit exceeded
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
examples:
rate_limit:
value:
error: rate_limit_exceeded
message: Too many requests, please try again later
headers:
X-RateLimit-Limit:
schema:
type: integer
description: Request limit per window
X-RateLimit-Remaining:
schema:
type: integer
description: Requests remaining in current window
X-RateLimit-Reset:
schema:
type: integer
description: Unix timestamp when rate limit resets
Extract from Section 6: API Specification:
## API Specification
### Endpoints
#### POST /auth/signup
**Description**: Create new user account and workspace
**Authentication**: None (public endpoint)
**Request**:
```json
{
"email": "[email protected]",
"password": "SecurePass123!",
"workspaceName": "Acme Corp"
}
Response (201 Created):
{
"user": {
"id": "usr_abc123",
"email": "[email protected]",
"workspaceId": "ws_xyz789"
},
"accessToken": "eyJhbGc...",
"refreshToken": "eyJhbGc..."
}
Errors:
Description: List tickets for current workspace
Authentication: Required (Bearer token)
Query Parameters:
status (optional): Filter by status (OPEN, IN_PROGRESS, RESOLVED, CLOSED)assigneeId (optional): Filter by assigned userpage (optional, default: 1): Page numberlimit (optional, default: 20, max: 100): Items per pagesort (optional, default: createdAt): Sort fieldorder (optional, default: desc): Sort order (asc, desc)Response (200 OK):
{
"data": [
{
"id": "tkt_xyz789",
"title": "Cannot login to app",
"description": "Users report login button is broken",
"status": "OPEN",
"priority": "HIGH",
"assigneeId": "usr_abc123",
"createdBy": "usr_def456",
"createdAt": "2026-02-07T10:00:00Z",
"updatedAt": "2026-02-07T10:00:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 47,
"totalPages": 3
}
}
Errors:
### Step 2: Extract API Metadata
From blueprint sections:
**Info**:
- **Title**: From Section 1 (Executive Summary)
- **Description**: From product description
- **Version**: 1.0.0 (default)
- **Contact**: Placeholder or from user input
**Servers**:
- **Production**: From deployment section (Section 9)
- **Staging**: Inferred from production URL
- **Local**: http://localhost:3000 (default for dev)
**Security**:
- **Bearer JWT**: If Clerk/Auth0 detected
- **API Key**: If API key auth mentioned
- **OAuth2**: If OAuth flows described
### Step 3: Convert Endpoints to OpenAPI Paths
For each endpoint:
1. **Parse HTTP method and path**: `POST /auth/signup`
2. **Extract request schema**: From request JSON example
3. **Extract response schemas**: From response examples
4. **Extract parameters**: Query, path, header params
5. **Extract error responses**: 400, 401, 403, 404, 500, etc.
6. **Add tags**: Group by feature area (Auth, Tickets, Users)
**Type inference from examples**:
```json
{
"email": "[email protected]", // → type: string, format: email
"age": 25, // → type: integer
"price": 19.99, // → type: number, format: double
"isActive": true, // → type: boolean
"createdAt": "2026-02-07T10:00:00Z" // → type: string, format: date-time
}
Create schemas for common types:
Request/Response objects:
Domain models:
Common responses:
Reuse via $ref:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/SignupRequest'
Based on authentication method detected:
JWT (Clerk, Auth0):
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
API Key (custom):
components:
securitySchemes:
apiKey:
type: apiKey
in: header
name: X-API-Key
OAuth2 (third-party integrations):
components:
securitySchemes:
oauth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: https://auth.acme.com/oauth/authorize
tokenUrl: https://auth.acme.com/oauth/token
scopes:
read:tickets: Read tickets
write:tickets: Create and update tickets
For each endpoint:
Example:
parameters:
- name: limit
in: query
description: Maximum number of items to return (1-100)
schema:
type: integer
minimum: 1
maximum: 100
default: 20
examples:
small_page:
value: 10
summary: Small page size
large_page:
value: 100
summary: Maximum page size
When invoked, generate:
📄 Generating OpenAPI specification from blueprint...
✅ Parsed API specification (Section 6)
✅ Detected 23 endpoints across 4 resource types
- Authentication: 4 endpoints
- Tickets: 7 endpoints
- Users: 5 endpoints
- Workspaces: 3 endpoints
- Comments: 4 endpoints
✅ Inferred 18 request/response schemas
✅ Detected authentication: Bearer JWT (Clerk)
✅ Detected rate limiting: 60 requests/minute
✅ Added 3 server environments (prod, staging, local)
📄 Created openapi.yaml (847 lines)
📄 Created openapi.json (JSON format)
🚀 View interactive docs:
- Swagger UI: https://editor.swagger.io/ (paste openapi.yaml)
- Redoc: https://redocly.github.io/redoc/ (paste openapi.yaml)
📦 Import into tools:
- Postman: Import → OpenAPI 3.0 → openapi.yaml
- Insomnia: Import → openapi.yaml
- Stoplight: Import OpenAPI
- Paw: Import OpenAPI
🛠️ Generate client SDKs:
- TypeScript: npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g typescript-fetch
- Python: openapi-generator-cli generate -i openapi.yaml -g python
- Go: openapi-generator-cli generate -i openapi.yaml -g go
- Swift: openapi-generator-cli generate -i openapi.yaml -g swift5
Next steps:
1. Review openapi.yaml for accuracy
2. Import into Postman for API testing
3. Generate client SDK for frontend
4. Host Swagger UI for team documentation
Swagger UI:
Redoc:
Use OpenAPI spec to generate mock servers:
Prism (recommended):
npm install -g @stoplight/prism-cli
# Start mock server
prism mock openapi.yaml
# Mock server running at http://127.0.0.1:4010
# Returns example responses from spec
Benefits:
TypeScript:
npx @openapitools/openapi-generator-cli generate \
-i openapi.yaml \
-g typescript-fetch \
-o ./generated/api-client
# Generated: Type-safe API client
import { TicketsApi } from './generated/api-client';
const api = new TicketsApi({ basePath: 'https://api.acme.com' });
const tickets = await api.listTickets({ status: 'OPEN' });
Python:
openapi-generator-cli generate \
-i openapi.yaml \
-g python \
-o ./api-client
# Generated: Python client
from api_client import TicketsApi
api = TicketsApi()
tickets = api.list_tickets(status='OPEN')
Express.js middleware:
import { validateRequest } from 'express-openapi-validator';
app.use(validateRequest({
apiSpec: './openapi.yaml',
validateRequests: true,
validateResponses: true,
}));
// Automatically validates all requests/responses against spec
// Returns 400 if request doesn't match schema
Automatically create Postman collection:
# Convert OpenAPI to Postman Collection
npx openapi-to-postmanv2 \
-s openapi.yaml \
-o postman-collection.json
# Import postman-collection.json into Postman
Optional parameters:
Examples:
# JSON format
/architect:publish-api-docs --format=json
# Custom servers
/architect:publish-api-docs --prod-url=https://api.prod.acme.com
# Add contact info
/architect:publish-api-docs [email protected] --contact-name="API Support"
# Custom license
/architect:publish-api-docs --license=Apache-2.0
If webhooks mentioned in blueprint:
webhooks:
ticketCreated:
post:
summary: Ticket Created
description: Triggered when a new ticket is created
requestBody:
content:
application/json:
schema:
type: object
properties:
event:
type: string
enum: [ticket.created]
data:
$ref: '#/components/schemas/Ticket'
responses:
'200':
description: Webhook received successfully
Add pagination metadata:
Pagination:
type: object
properties:
page:
type: integer
limit:
type: integer
total:
type: integer
totalPages:
type: integer
links:
type: object
properties:
self:
type: string
example: /tickets?page=2
first:
type: string
example: /tickets?page=1
prev:
type: string
nullable: true
example: /tickets?page=1
next:
type: string
nullable: true
example: /tickets?page=3
last:
type: string
example: /tickets?page=10
Document rate limit headers:
headers:
X-RateLimit-Limit:
schema:
type: integer
description: Total requests allowed per window
example: 60
X-RateLimit-Remaining:
schema:
type: integer
description: Requests remaining in current window
example: 42
X-RateLimit-Reset:
schema:
type: integer
description: Unix timestamp when limit resets
example: 1612742400
/architect:blueprint first."# Install Swagger UI
npm install swagger-ui-express
# Serve OpenAPI spec
node -e "
const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const express = require('express');
const app = express();
const spec = YAML.load('./openapi.yaml');
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(spec));
app.listen(3001, () => console.log('Docs at http://localhost:3001/api-docs'));
"
Visual OpenAPI editor:
# Install Stoplight Studio
brew install stoplight/tap/studio
# Open spec
studio openapi.yaml
# Edit visually with GUI
A successful OpenAPI export should:
/architect:publish-api-docs
# Output:
# ✅ Created openapi.yaml (847 lines)
# ✅ 23 endpoints documented
/architect:publish-api-docs --format=json
# Output:
# ✅ Created openapi.json
/architect:publish-api-docs \
--prod-url=https://api.acme.com/v1 \
--staging-url=https://staging-api.acme.com/v1
# Output:
# ✅ Added 3 server environments
/architect:publish-api-docs
npx swagger-ui-express openapi.yaml --port 3001
# Docs available at: http://localhost:3001
development
# Trade-Off Analysis Skill Quantifies exact trade-offs when switching between architecture options. Shows users precisely what they gain and lose when choosing Option A over Option B. ## When to Use Use this skill to help users decide between options by showing: 1. **Cost difference** — how much more/less per month? 2. **Performance difference** — how much faster/slower? 3. **Complexity difference** — how much harder to build/maintain? 4. **Scalability difference** — when does this option hit
testing
# Stage Detection Skill Detects the current project stage (concept → mvp → growth → enterprise) based on `_state.json` field presence and completeness. Used by `/architect:next-steps`, `/architect:check-state`, and roadmap commands. ## When to Use Invoke this skill when you need to determine what stage a project is at based on its state file. Stage detection drives: - Command recommendations (what to run next) - Required fields validation (what should exist at this stage) - Risk assessment (w
development
# Stack Swap Simulator Skill Estimates cost and effort to switch from one tech stack to another. Helps answer: "Can we migrate later if needed?" ## When to Use Use this skill to understand: 1. **Cost of switching stacks** — engineer weeks + downtime risk 2. **Timeline to switch** — how long is the project? 3. **Risk of switching** — what can go wrong? 4. **ROI of switching** — does it save money long-term? 5. **Backwards compatibility** — can we do a gradual migration? ## Input Provide sour
tools
# Stack Compatibility Skill Verifies that chosen technologies integrate well together. Prevents "I picked these tools and they don't work well together" regrets. ## When to Use Use this skill to verify: 1. **Chosen tools work together** — React + Node + MongoDB = good? 2. **No hidden incompatibilities** — will I hit issues in production? 3. **Team can support it** — do we have expertise for this combo? 4. **Licenses compatible** — can we use these together commercially? 5. **Performance assum