openapi-authoring

OpenAPI Authoring Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "openapi-authoring" with this command: npx skills add melodic-software/claude-code-plugins/melodic-software-claude-code-plugins-openapi-authoring

OpenAPI Authoring Skill

When to Use This Skill

Use this skill when:

  • Openapi Authoring tasks - Working on author and validate openapi 3.1 specifications for rest api design, following api-first and contract-first development practices

  • Planning or design - Need guidance on Openapi Authoring approaches

  • Best practices - Want to follow established patterns and standards

Overview

Author OpenAPI 3.1 specifications for REST API design using API-first methodology.

OpenAPI 3.1 Structure

Root Document

openapi: "3.1.0"

info: title: "{Service Name} API" version: "1.0.0" description: | {Service description and purpose} contact: name: "{Team Name}" email: "{team@company.com}" license: name: "MIT" identifier: "MIT"

servers:

tags:

  • name: "{Resource}" description: "Operations for {resource} management"

paths:

Path definitions

components:

Reusable components

security:

  • bearerAuth: []

Path Operations

paths: /resources: get: operationId: "listResources" summary: "List all resources" description: "Retrieves a paginated list of resources" tags: - Resources parameters: - $ref: "#/components/parameters/PageNumber" - $ref: "#/components/parameters/PageSize" - $ref: "#/components/parameters/SortBy" responses: "200": description: "Successful response" content: application/json: schema: $ref: "#/components/schemas/ResourceListResponse" "400": $ref: "#/components/responses/BadRequest" "401": $ref: "#/components/responses/Unauthorized"

post:
  operationId: "createResource"
  summary: "Create a new resource"
  description: "Creates a new resource with the provided data"
  tags:
    - Resources
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/CreateResourceRequest"
  responses:
    "201":
      description: "Resource created"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ResourceResponse"
      headers:
        Location:
          description: "URL of the created resource"
          schema:
            type: string
            format: uri
    "400":
      $ref: "#/components/responses/BadRequest"
    "422":
      $ref: "#/components/responses/UnprocessableEntity"

/resources/{resourceId}: parameters: - $ref: "#/components/parameters/ResourceId"

get:
  operationId: "getResource"
  summary: "Get a resource by ID"
  description: "Retrieves a single resource by its unique identifier"
  tags:
    - Resources
  responses:
    "200":
      description: "Successful response"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ResourceResponse"
    "404":
      $ref: "#/components/responses/NotFound"

put:
  operationId: "updateResource"
  summary: "Update a resource"
  description: "Replaces the entire resource with the provided data"
  tags:
    - Resources
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/UpdateResourceRequest"
  responses:
    "200":
      description: "Resource updated"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ResourceResponse"
    "404":
      $ref: "#/components/responses/NotFound"
    "409":
      $ref: "#/components/responses/Conflict"

patch:
  operationId: "patchResource"
  summary: "Partially update a resource"
  description: "Updates specific fields of the resource"
  tags:
    - Resources
  requestBody:
    required: true
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/PatchResourceRequest"
  responses:
    "200":
      description: "Resource patched"
      content:
        application/json:
          schema:
            $ref: "#/components/schemas/ResourceResponse"
    "404":
      $ref: "#/components/responses/NotFound"

delete:
  operationId: "deleteResource"
  summary: "Delete a resource"
  description: "Permanently removes a resource"
  tags:
    - Resources
  responses:
    "204":
      description: "Resource deleted"
    "404":
      $ref: "#/components/responses/NotFound"
    "409":
      $ref: "#/components/responses/Conflict"

Component Schemas

components: schemas: # Request schemas CreateResourceRequest: type: object required: - name - type properties: name: type: string minLength: 1 maxLength: 100 description: "Resource name" example: "My Resource" type: $ref: "#/components/schemas/ResourceType" description: type: string maxLength: 500 description: "Optional description" metadata: type: object additionalProperties: true description: "Custom metadata key-value pairs"

UpdateResourceRequest:
  allOf:
    - $ref: "#/components/schemas/CreateResourceRequest"

PatchResourceRequest:
  type: object
  properties:
    name:
      type: string
      minLength: 1
      maxLength: 100
    description:
      type: string
      maxLength: 500
  minProperties: 1

# Response schemas
ResourceResponse:
  type: object
  required:
    - id
    - name
    - type
    - createdAt
    - updatedAt
  properties:
    id:
      type: string
      format: uuid
      description: "Unique identifier"
      example: "550e8400-e29b-41d4-a716-446655440000"
    name:
      type: string
      description: "Resource name"
    type:
      $ref: "#/components/schemas/ResourceType"
    description:
      type: string
    metadata:
      type: object
      additionalProperties: true
    createdAt:
      type: string
      format: date-time
      description: "Creation timestamp (ISO 8601)"
    updatedAt:
      type: string
      format: date-time
      description: "Last update timestamp (ISO 8601)"
    _links:
      $ref: "#/components/schemas/ResourceLinks"

ResourceListResponse:
  type: object
  required:
    - data
    - pagination
  properties:
    data:
      type: array
      items:
        $ref: "#/components/schemas/ResourceResponse"
    pagination:
      $ref: "#/components/schemas/Pagination"
    _links:
      $ref: "#/components/schemas/PaginationLinks"

# Enums
ResourceType:
  type: string
  enum:
    - standard
    - premium
    - enterprise
  description: "Type of resource"

# Common schemas
Pagination:
  type: object
  required:
    - page
    - pageSize
    - totalItems
    - totalPages
  properties:
    page:
      type: integer
      minimum: 1
      description: "Current page number"
    pageSize:
      type: integer
      minimum: 1
      maximum: 100
      description: "Items per page"
    totalItems:
      type: integer
      minimum: 0
      description: "Total number of items"
    totalPages:
      type: integer
      minimum: 0
      description: "Total number of pages"

ResourceLinks:
  type: object
  properties:
    self:
      type: string
      format: uri
    collection:
      type: string
      format: uri

PaginationLinks:
  type: object
  properties:
    self:
      type: string
      format: uri
    first:
      type: string
      format: uri
    prev:
      type: string
      format: uri
    next:
      type: string
      format: uri
    last:
      type: string
      format: uri

# Error schemas
ErrorResponse:
  type: object
  required:
    - type
    - title
    - status
  properties:
    type:
      type: string
      format: uri
      description: "URI reference identifying the problem type"
    title:
      type: string
      description: "Short, human-readable summary"
    status:
      type: integer
      description: "HTTP status code"
    detail:
      type: string
      description: "Human-readable explanation"
    instance:
      type: string
      format: uri
      description: "URI reference identifying the specific occurrence"
    errors:
      type: array
      items:
        $ref: "#/components/schemas/ValidationError"

ValidationError:
  type: object
  required:
    - field
    - message
  properties:
    field:
      type: string
      description: "Field path (e.g., 'name' or 'address.city')"
    message:
      type: string
      description: "Validation error message"
    code:
      type: string
      description: "Error code for programmatic handling"

Parameters and Responses

components: parameters: ResourceId: name: resourceId in: path required: true description: "Resource unique identifier" schema: type: string format: uuid

PageNumber:
  name: page
  in: query
  description: "Page number (1-indexed)"
  schema:
    type: integer
    minimum: 1
    default: 1

PageSize:
  name: pageSize
  in: query
  description: "Number of items per page"
  schema:
    type: integer
    minimum: 1
    maximum: 100
    default: 20

SortBy:
  name: sortBy
  in: query
  description: "Sort field and direction"
  schema:
    type: string
    pattern: "^[a-zA-Z]+:(asc|desc)$"
    example: "createdAt:desc"

IfMatch:
  name: If-Match
  in: header
  description: "ETag for optimistic concurrency"
  schema:
    type: string

responses: BadRequest: description: "Bad Request - Invalid input" content: application/problem+json: schema: $ref: "#/components/schemas/ErrorResponse" example: type: "https://api.example.com/problems/bad-request" title: "Bad Request" status: 400 detail: "The request body is malformed"

Unauthorized:
  description: "Unauthorized - Authentication required"
  content:
    application/problem+json:
      schema:
        $ref: "#/components/schemas/ErrorResponse"

Forbidden:
  description: "Forbidden - Insufficient permissions"
  content:
    application/problem+json:
      schema:
        $ref: "#/components/schemas/ErrorResponse"

NotFound:
  description: "Not Found - Resource does not exist"
  content:
    application/problem+json:
      schema:
        $ref: "#/components/schemas/ErrorResponse"

Conflict:
  description: "Conflict - Resource state conflict"
  content:
    application/problem+json:
      schema:
        $ref: "#/components/schemas/ErrorResponse"

UnprocessableEntity:
  description: "Unprocessable Entity - Validation failed"
  content:
    application/problem+json:
      schema:
        $ref: "#/components/schemas/ErrorResponse"
      example:
        type: "https://api.example.com/problems/validation-error"
        title: "Validation Error"
        status: 422
        detail: "One or more validation errors occurred"
        errors:
          - field: "name"
            message: "Name is required"
            code: "required"

TooManyRequests:
  description: "Too Many Requests - Rate limit exceeded"
  headers:
    Retry-After:
      description: "Seconds until rate limit resets"
      schema:
        type: integer
    X-RateLimit-Limit:
      description: "Requests per window"
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: "Requests remaining"
      schema:
        type: integer
  content:
    application/problem+json:
      schema:
        $ref: "#/components/schemas/ErrorResponse"

Security Schemes

components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT description: "JWT Bearer token authentication"

apiKey:
  type: apiKey
  in: header
  name: X-API-Key
  description: "API key for service-to-service auth"

oauth2:
  type: oauth2
  description: "OAuth 2.0 authentication"
  flows:
    authorizationCode:
      authorizationUrl: "https://auth.example.com/authorize"
      tokenUrl: "https://auth.example.com/token"
      refreshUrl: "https://auth.example.com/refresh"
      scopes:
        "read:resources": "Read access to resources"
        "write:resources": "Write access to resources"
        "admin:resources": "Administrative access"

C# Models for OpenAPI

using System.Text.Json.Serialization;

namespace SpecDrivenDevelopment.OpenApi;

/// <summary> /// Represents an OpenAPI specification document /// </summary> public record OpenApiSpec { public required string OpenApi { get; init; } = "3.1.0"; public required OpenApiInfo Info { get; init; } public List<OpenApiServer> Servers { get; init; } = []; public Dictionary<string, OpenApiPathItem> Paths { get; init; } = []; public OpenApiComponents? Components { get; init; } public List<OpenApiSecurityRequirement> Security { get; init; } = []; public List<OpenApiTag> Tags { get; init; } = []; }

public record OpenApiInfo { public required string Title { get; init; } public required string Version { get; init; } public string? Description { get; init; } public OpenApiContact? Contact { get; init; } public OpenApiLicense? License { get; init; } }

public record OpenApiContact { public string? Name { get; init; } public string? Email { get; init; } public string? Url { get; init; } }

public record OpenApiLicense { public required string Name { get; init; } public string? Identifier { get; init; } public string? Url { get; init; } }

public record OpenApiServer { public required string Url { get; init; } public string? Description { get; init; } public Dictionary<string, OpenApiServerVariable>? Variables { get; init; } }

public record OpenApiServerVariable { public required string Default { get; init; } public List<string>? Enum { get; init; } public string? Description { get; init; } }

public record OpenApiTag { public required string Name { get; init; } public string? Description { get; init; } }

public record OpenApiPathItem { public string? Summary { get; init; } public string? Description { get; init; } public OpenApiOperation? Get { get; init; } public OpenApiOperation? Post { get; init; } public OpenApiOperation? Put { get; init; } public OpenApiOperation? Patch { get; init; } public OpenApiOperation? Delete { get; init; } public List<OpenApiParameter>? Parameters { get; init; } }

public record OpenApiOperation { public required string OperationId { get; init; } public string? Summary { get; init; } public string? Description { get; init; } public List<string>? Tags { get; init; } public List<OpenApiParameter>? Parameters { get; init; } public OpenApiRequestBody? RequestBody { get; init; } public required Dictionary<string, OpenApiResponse> Responses { get; init; } public List<OpenApiSecurityRequirement>? Security { get; init; } public bool Deprecated { get; init; } }

public record OpenApiParameter { public required string Name { get; init; }

[JsonConverter(typeof(JsonStringEnumConverter))]
public required ParameterLocation In { get; init; }

public string? Description { get; init; }
public bool Required { get; init; }
public OpenApiSchema? Schema { get; init; }

[JsonPropertyName("$ref")]
public string? Ref { get; init; }

}

public enum ParameterLocation { Query, Header, Path, Cookie }

public record OpenApiRequestBody { public string? Description { get; init; } public required Dictionary<string, OpenApiMediaType> Content { get; init; } public bool Required { get; init; } }

public record OpenApiResponse { public required string Description { get; init; } public Dictionary<string, OpenApiMediaType>? Content { get; init; } public Dictionary<string, OpenApiHeader>? Headers { get; init; }

[JsonPropertyName("$ref")]
public string? Ref { get; init; }

}

public record OpenApiMediaType { public OpenApiSchema? Schema { get; init; } public object? Example { get; init; } public Dictionary<string, OpenApiExample>? Examples { get; init; } }

public record OpenApiExample { public string? Summary { get; init; } public string? Description { get; init; } public object? Value { get; init; } }

public record OpenApiHeader { public string? Description { get; init; } public OpenApiSchema? Schema { get; init; } }

public record OpenApiSchema { public string? Type { get; init; } public string? Format { get; init; } public string? Description { get; init; } public List<string>? Enum { get; init; } public object? Default { get; init; } public object? Example { get; init; } public List<string>? Required { get; init; } public Dictionary<string, OpenApiSchema>? Properties { get; init; } public OpenApiSchema? Items { get; init; } public bool? Nullable { get; init; } public int? MinLength { get; init; } public int? MaxLength { get; init; } public int? Minimum { get; init; } public int? Maximum { get; init; } public string? Pattern { get; init; } public List<OpenApiSchema>? AllOf { get; init; } public List<OpenApiSchema>? OneOf { get; init; } public List<OpenApiSchema>? AnyOf { get; init; } public bool? AdditionalProperties { get; init; }

[JsonPropertyName("$ref")]
public string? Ref { get; init; }

}

public record OpenApiComponents { public Dictionary<string, OpenApiSchema>? Schemas { get; init; } public Dictionary<string, OpenApiParameter>? Parameters { get; init; } public Dictionary<string, OpenApiResponse>? Responses { get; init; } public Dictionary<string, OpenApiSecurityScheme>? SecuritySchemes { get; init; } }

public record OpenApiSecurityScheme { public required string Type { get; init; } public string? Scheme { get; init; } public string? BearerFormat { get; init; } public string? Description { get; init; } public string? Name { get; init; } public string? In { get; init; } public OpenApiOAuthFlows? Flows { get; init; } }

public record OpenApiOAuthFlows { public OpenApiOAuthFlow? AuthorizationCode { get; init; } public OpenApiOAuthFlow? ClientCredentials { get; init; } }

public record OpenApiOAuthFlow { public required string AuthorizationUrl { get; init; } public required string TokenUrl { get; init; } public string? RefreshUrl { get; init; } public required Dictionary<string, string> Scopes { get; init; } }

public record OpenApiSecurityRequirement : Dictionary<string, List<string>>;

OpenAPI Design Patterns

Versioning Strategy

versioning_strategies: url_path: description: "Version in URL path" example: "/v1/resources" pros: - "Explicit and visible" - "Easy to route" - "Cache-friendly" cons: - "URL changes on major version"

header: description: "Version in custom header" example: "X-API-Version: 2023-01-15" pros: - "Clean URLs" - "Fine-grained control" cons: - "Less discoverable" - "Harder to test in browser"

query_parameter: description: "Version as query parameter" example: "/resources?version=2" pros: - "Easy to specify" - "Fallback to default" cons: - "Cache complications" - "Less clean"

recommended: "url_path" rationale: "Most explicit, widely adopted, cache-friendly"

Pagination Patterns

pagination_patterns: offset_based: description: "Traditional page/pageSize pagination" parameters: - "page (1-indexed)" - "pageSize (default 20, max 100)" response: pagination: page: 2 pageSize: 20 totalItems: 150 totalPages: 8 pros: - "Simple to implement" - "Random access to pages" cons: - "Inconsistent with concurrent writes" - "Performance degrades at high offsets"

cursor_based: description: "Cursor/continuation token pagination" parameters: - "cursor (opaque token)" - "limit (default 20, max 100)" response: pagination: nextCursor: "eyJpZCI6MTIzfQ==" hasMore: true pros: - "Consistent with concurrent writes" - "Better performance at scale" cons: - "No random access" - "Harder to implement"

recommended: "cursor_based for large datasets, offset_based for small"

Error Handling (RFC 7807)

error_handling: standard: "RFC 7807 Problem Details" content_type: "application/problem+json"

structure: type: "URI reference identifying problem type" title: "Short human-readable summary" status: "HTTP status code" detail: "Human-readable explanation specific to this occurrence" instance: "URI reference to specific occurrence"

extensions: errors: "Array of field-level validation errors" traceId: "Correlation ID for debugging"

example: type: "https://api.example.com/problems/validation-error" title: "Validation Error" status: 422 detail: "The request contains invalid data" instance: "/resources/123" traceId: "abc-123-xyz" errors: - field: "email" message: "Invalid email format" code: "invalid_format"

Validation Checklist

openapi_validation_checklist: structure: - "Valid OpenAPI 3.1.0 syntax" - "All required fields present (openapi, info, paths)" - "No undefined $ref references" - "Consistent naming conventions"

operations: - "Every operation has unique operationId" - "All operations have summary and description" - "All operations tagged appropriately" - "All path parameters defined" - "Response codes cover success and error cases"

schemas: - "All schemas have descriptions" - "Required fields explicitly listed" - "Examples provided for complex types" - "Enums documented with descriptions" - "String formats specified (uuid, date-time, email, uri)"

security: - "Security schemes defined" - "Operations specify security requirements" - "OAuth scopes documented"

documentation: - "API description explains purpose" - "Contact information provided" - "Server URLs for all environments" - "Tags organized logically"

best_practices: - "Use RFC 7807 for errors" - "Consistent pagination approach" - "HATEOAS links where appropriate" - "Idempotency keys for POST operations" - "ETag/If-Match for optimistic concurrency"

References

  • references/openapi-patterns.md

  • Common OpenAPI design patterns

  • references/api-guidelines.md

  • API design guidelines and standards

Last Updated: 2025-12-26

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

design-thinking

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

plantuml-syntax

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

system-prompt-engineering

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

swot-pestle-analysis

No summary provided by upstream source.

Repository SourceNeeds Review