🎯

writing-openapi-specs

🎯Skill

from speakeasy-api/agent-skills

VibeIndex|
What it does

Generates comprehensive OpenAPI specifications with best practices, naming conventions, and advanced REST API pattern support for improved SDK generation.

πŸ“¦

Part of

speakeasy-api/agent-skills(25 items)

writing-openapi-specs

Installation

Quick InstallInstall with npx
npx skills add speakeasy-api/skills
πŸ“– Extracted from docs: speakeasy-api/agent-skills
3Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Reference guide for OpenAPI specification best practices, naming conventions, and expressing complex REST API patterns like polymorphism, enums, file uploads, and server-sent events. Use when writing or improving OpenAPI specs to ensure they follow established conventions and generate quality SDKs.

Overview

# Writing OpenAPI Specs

Reference for OpenAPI best practices and conventions. This skill provides guidance on taste, conventions, and grey areas not covered by the OpenAPI specification itself.

When to Use This Skill

  • Writing a new OpenAPI specification
  • Improving operation naming and organization
  • Expressing complex data types (enums, polymorphism, nullable)
  • Handling file uploads, streaming, or server-sent events
  • Making specs more code-gen friendly
  • Understanding reusability patterns (components vs inline)

Core Principles

Naming Conventions

Operation IDs: Use lowercase with underscores, following resource_action pattern:

```yaml

# Good

operationId: users_list

operationId: users_get

operationId: users_create

# Avoid

operationId: GetApiV1Users # Auto-generated, not semantic

```

Component Names: Use PascalCase for schemas, parameters, and other reusable components:

```yaml

components:

schemas:

UserProfile: # PascalCase

OrderHistory: # PascalCase

parameters:

PageLimit: # PascalCase

```

Tags: Use lowercase with hyphens for machine-friendly tags:

```yaml

tags:

- name: user-management

description: Operations for managing users

- name: order-processing

description: Operations for processing orders

```

For more details, see [reference/operations.md](reference/operations.md) and [reference/components.md](reference/components.md).

Documentation Standards

Use CommonMark: All description fields support CommonMark syntax for rich formatting:

```yaml

description: |

Retrieves a user by ID.

## Authorization

Requires users:read scope.

## Rate Limits

- 100 requests per minute per API key

- 1000 requests per hour per IP

```

Be Specific: Provide actionable information, not generic descriptions:

```yaml

# Good

description: Returns a paginated list of active users, ordered by creation date (newest first)

# Avoid

description: Gets users

```

Use examples over example: The plural examples field provides better SDK generation:

```yaml

# Good

examples:

basic_user:

value:

id: 123

name: "John Doe"

admin_user:

value:

id: 456

name: "Jane Admin"

role: admin

# Avoid single example

example:

id: 123

name: "John Doe"

```

For more details, see [reference/examples.md](reference/examples.md).

Reusability

Create components for:

  • Schemas used in multiple operations
  • Common parameters (pagination, filtering)
  • Common responses (errors, success patterns)
  • Security schemes

Keep inline for:

  • Operation-specific request bodies
  • Unique response shapes
  • One-off parameters

```yaml

# Reusable schema

components:

schemas:

User:

type: object

properties:

id: {type: integer}

name: {type: string}

# Reference it

paths:

/users/{id}:

get:

responses:

'200':

content:

application/json:

schema:

$ref: '#/components/schemas/User'

```

For more details, see [reference/components.md](reference/components.md).

Complex Patterns Quick Reference

These patterns are commonly challenging. Brief examples below with links to detailed guidance.

Enums

Use string enums with clear, semantic values:

```yaml

type: string

enum:

- pending

- approved

- rejected

- cancelled

```

Avoid:

  • Numeric strings ("0", "1", "2")
  • Generic values ("value1", "value2")
  • Unclear abbreviations ("pnd", "appr")

See [reference/schemas.md#enums](reference/schemas.md) for more.

Polymorphism (oneOf/allOf/anyOf)

oneOf: Value matches exactly one schema (type discrimination)

```yaml

PaymentMethod:

oneOf:

- $ref: '#/components/schemas/CreditCard'

- $ref: '#/components/schemas/BankAccount'

- $ref: '#/components/schemas/PayPal'

discriminator:

propertyName: type

mapping:

credit_card: '#/components/schemas/CreditCard'

bank_account: '#/components/schemas/BankAccount'

paypal: '#/components/schemas/PayPal'

```

allOf: Value matches all schemas (composition/inheritance)

```yaml

AdminUser:

allOf:

- $ref: '#/components/schemas/User'

- type: object

properties:

permissions:

type: array

items: {type: string}

```

anyOf: Value matches one or more schemas (flexible union)

```yaml

SearchFilter:

anyOf:

- $ref: '#/components/schemas/TextFilter'

- $ref: '#/components/schemas/DateFilter'

- $ref: '#/components/schemas/NumericFilter'

```

See [reference/schemas.md#polymorphism](reference/schemas.md) for detailed guidance.

Discriminators

Use discriminators with oneOf for efficient type identification:

```yaml

Pet:

oneOf:

- $ref: '#/components/schemas/Dog'

- $ref: '#/components/schemas/Cat'

discriminator:

propertyName: petType

mapping:

dog: '#/components/schemas/Dog'

cat: '#/components/schemas/Cat'

Dog:

type: object

required: [petType, bark]

properties:

petType:

type: string

enum: [dog]

bark:

type: string

Cat:

type: object

required: [petType, meow]

properties:

petType:

type: string

enum: [cat]

meow:

type: string

```

See [reference/schemas.md#discriminators](reference/schemas.md) for more.

Nullable Types

Handle null values differently based on OpenAPI version:

OpenAPI 3.1 (JSON Schema 2020-12 compliant):

```yaml

type: [string, "null"]

# or

type: string

nullable: true # Still supported for compatibility

```

OpenAPI 3.0:

```yaml

type: string

nullable: true

```

For optional fields, use required array:

```yaml

type: object

properties:

name: {type: string} # Can be omitted

email: {type: string} # Can be omitted

required: [name] # email is optional

```

See [reference/schemas.md#nullable](reference/schemas.md) for more.

File Uploads

Use multipart/form-data for file uploads:

```yaml

requestBody:

required: true

content:

multipart/form-data:

schema:

type: object

properties:

file:

type: string

format: binary

metadata:

type: object

properties:

description: {type: string}

tags:

type: array

items: {type: string}

required: [file]

```

For base64-encoded files in JSON:

```yaml

requestBody:

content:

application/json:

schema:

type: object

properties:

filename: {type: string}

content:

type: string

format: byte # base64-encoded

```

See [reference/request-bodies.md#file-uploads](reference/request-bodies.md) for more.

Server-Sent Events (SSE)

Express streaming responses with text/event-stream:

```yaml

responses:

'200':

description: Stream of events

content:

text/event-stream:

schema:

type: string

description: |

Server-sent events stream. Each event follows the format:

```

event: message

data: {"type": "update", "content": "..."}

```

examples:

notification_stream:

value: |

event: message

data: {"type": "notification", "message": "New order received"}

event: message

data: {"type": "notification", "message": "Order processing complete"}

```

See [reference/responses.md#streaming](reference/responses.md) for more patterns.

Field Reference

Detailed guidance for each major OpenAPI field:

  • Operations: Operation IDs, methods, tags, deprecation β†’ [reference/operations.md](reference/operations.md)
  • Schemas: Data types, polymorphism, enums, nullable β†’ [reference/schemas.md](reference/schemas.md)
  • Parameters: Path, query, header, cookie parameters β†’ [reference/parameters.md](reference/parameters.md)
  • Request Bodies: Content types, file uploads, encoding β†’ [reference/request-bodies.md](reference/request-bodies.md)
  • Responses: Status codes, streaming, error patterns β†’ [reference/responses.md](reference/responses.md)
  • Components: Reusable definitions, organization β†’ [reference/components.md](reference/components.md)
  • Security: Authentication schemes, scopes, granular control β†’ [reference/security.md](reference/security.md)
  • Examples: Single and multiple examples, placement β†’ [reference/examples.md](reference/examples.md)

SDK Generation Considerations

When writing specs for SDK generation:

  1. Always define operationId: Required for meaningful method names
  2. Provide rich examples: Helps generate better documentation and tests
  3. Be explicit about required fields: Affects SDK method signatures
  4. Use discriminators with oneOf: Generates type-safe unions
  5. Document error responses: Generates better error handling code

Example SDK-friendly operation:

```yaml

paths:

/users:

get:

operationId: users_list

summary: List all users

description: Returns a paginated list of users

parameters:

- name: limit

in: query

schema: {type: integer, default: 20}

- name: offset

in: query

schema: {type: integer, default: 0}

responses:

'200':

description: Success

content:

application/json:

schema:

type: object

required: [data, pagination]

properties:

data:

type: array

items:

$ref: '#/components/schemas/User'

pagination:

$ref: '#/components/schemas/PaginationInfo'

examples:

success:

value:

data: [{id: 1, name: "Alice"}, {id: 2, name: "Bob"}]

pagination: {total: 100, limit: 20, offset: 0}

```

This generates: sdk.users.list({limit: 20, offset: 0})

Common Pitfalls

Don't:

  • Use generic descriptions like "Gets data" or "Returns object"
  • Mix naming conventions (pick one style and stick to it)
  • Forget operationId (causes auto-generated names)
  • Use example when you mean examples (plural is better)
  • Make everything required (be thoughtful about optional fields)
  • Inline everything (use components for reusability)
  • Reference everything (inline simple one-off schemas)
  • Forget to document error responses
  • Use magic numbers without explanation
  • Omit content types (be explicit)

Do:

  • Provide actionable, specific descriptions
  • Use consistent naming patterns throughout
  • Define clear operationId for every operation
  • Use examples (plural) with named examples
  • Carefully consider required vs optional fields
  • Balance reusability with clarity
  • Document all expected responses (success and errors)
  • Explain constraints and validation rules
  • Be explicit about content types and formats