11 min read
Master OpenAPI Specification to create machine-readable API contracts that enable parallel development, automatic documentation, and client code generation. Learn from the complete AI Prompt Enhancer API specification with real examples and production-ready patterns.

You've planned your API's design and identified your resources, endpoints, and data structures.
Now you need to transform this design into a formal definition that developers and machines can understand and work with.
This is exactly what the OpenAPI Specification solves.
OpenAPI Specification (OAS) provides a standardized format for describing RESTful APIs. It creates a machine-readable definition that makes your API understandable to humans and computers alike.
Think of OpenAPI as the architectural blueprint for your house.
It doesn't build the house itself, but it communicates the design precisely, ensuring everyone involved in construction shares the same understanding of what needs to be built.
We could have jumped into coding when building our AI Prompt Enhancer API. But that approach often leads to:
By defining our API contract first with OpenAPI, we achieved:
This contract-first approach forms the foundation of successful API companies' "API First" methodology.
Let's examine the main sections using our complete AI Prompt Enhancer API specification as a real-world example.
The top level of your OpenAPI document contains essential information about your API:
openapi: 3.0.3
info:
  title: AI Prompt Enhancer API
  description: |
    An API that transforms basic prompts into optimized, context-rich instructions for AI language models.
    Works with both Mistral and OpenAI to enhance prompts and generate better AI responses.
  version: 1.0.0
  contact:
    name: AI Prompt Enhancer Team
    email: rahul@treblle.com
    url: https://prompt-enhancer.ai
  license:
    name: MIT License
    url: https://opensource.org/licenses/MITThis metadata helps developers understand what your API does and how to get support when needed.
The servers section defines where users can access your API:
servers:
  - url: https://prompt-enhancer.ai/v1
    description: Production server
  - url: https://api.prompt-enhancer.cloudflare.dev/v1
    description: Cloudflare CDN
  - url: https://cdn.prompt-enhancer.ai/v1
    description: CDN-backed production server
  - url: http://localhost:5000/v1
    description: Local development serverMultiple server definitions help developers understand different environments and choose the appropriate endpoint for their use case.
Tags help organize your API endpoints into logical groups:
tags:
  - name: Authentication
    description: Authentication endpoints for token management
  - name: Prompts
    description: Prompt enhancement and management operationsThese tags appear in generated documentation, making it easier for developers to find relevant endpoints.
This is where you define your actual API endpoints. Here's our main prompt enhancement endpoint:
paths:
  /prompts:
    post:
      summary: Create an enhanced prompt
      description: Takes a basic prompt and returns an optimized, context-rich version
      operationId: createEnhancedPrompt
      tags:
        - Prompts
      security:
        - BearerAuth: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PromptRequest"
            examples:
              basicPrompt:
                value:
                  text: "Write about quantum computing"
                  format: "structured"
      responses:
        "200":
          description: Successfully enhanced prompt
          headers:
            Content-Type:
              schema:
                type: string
              description: Content type of the response
              example: "application/json"
            Content-Encoding:
              schema:
                type: string
              description: Compression method used for the response
              example: "gzip"
            X-RateLimit-Limit:
              $ref: "#/components/headers/X-RateLimit-Limit"
            X-RateLimit-Remaining:
              $ref: "#/components/headers/X-RateLimit-Remaining"
            X-RateLimit-Reset:
              $ref: "#/components/headers/X-RateLimit-Reset"
            X-Frame-Options:
              schema:
                type: string
              description: Prevents clickjacking attacks
              example: "DENY"
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PromptResponse"
              examples:
                successResponse:
                  value:
                    id: "prompt_abc123"
                    originalText: "Write about quantum computing"
                    enhancedText: "You are an expert physicist with deep knowledge in quantum mechanics and quantum computing..."
                    format: "structured"
                    createdAt: "2023-07-15T14:30:00Z"Notice how we use $ref to reference schemas defined elsewhere. This keeps your OpenAPI file DRY (Don't Repeat Yourself) and maintainable.
The components section contains reusable objects referenced throughout your API specification.
Schemas define the structure of your data objects, templates for the JSON data sent to or returned from your API:
components:
  schemas:
    TokenRequest:
      type: object
      description: Request to generate an authentication token
      required:
        - clientSecret
      properties:
        clientId:
          type: string
          description: Client identifier
          example: "frontend-client"
        clientSecret:
          type: string
          description: Client secret (API key)
          example: "your-api-key-here"
 
    TokenResponse:
      type: object
      description: Authentication token response
      properties:
        access_token:
          type: string
          description: JWT access token
          example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
        token_type:
          type: string
          description: Token type
          example: "Bearer"
        expires_in:
          type: integer
          description: Token expiration time in seconds
          example: 86400
        scope:
          type: string
          description: Token scope
          example: "api:access"
 
    PromptRequest:
      type: object
      description: Request body for creating or updating a prompt enhancement
      required:
        - text
      properties:
        text:
          type: string
          description: The original prompt text to be enhanced
          minLength: 1
          maxLength: 8000
          example: "Write about quantum computing"
        format:
          type: string
          description: The desired format for the enhanced prompt
          enum:
            - structured
            - paragraph
            - bullet
            - conversational
          default: structured
          example: "structured"
 
    PromptResponse:
      type: object
      description: Response containing the enhanced prompt information
      properties:
        id:
          type: string
          description: Unique identifier for the enhanced prompt
          example: "prompt_abc123"
        originalText:
          type: string
          description: The original prompt text provided by the user
          example: "Write about quantum computing"
        enhancedText:
          type: string
          description: The enhanced, more detailed prompt text
          example: "As a professional expert in quantum computing, provide a comprehensive overview..."
        format:
          type: string
          description: The format used for enhancing the prompt
          enum:
            - structured
            - paragraph
            - bullet
            - conversational
          example: "structured"
        createdAt:
          type: string
          format: date-time
          description: Timestamp of prompt creation
          example: "2023-07-15T14:30:00Z"
        updatedAt:
          type: string
          format: date-time
          description: Timestamp of the last prompt update (if applicable)
          example: "2023-07-15T15:45:00Z"Each property can include:
A standardized error response format ensures consistency and makes it easier for clients to handle failures:
    Error:
      type: object
      description: Standard error response format
      properties:
        error:
          type: object
          description: Error details
          properties:
            code:
              type: string
              description: Machine-readable error code
              example: "validation_error"
            message:
              type: string
              description: Human-readable error message
              example: "The 'text' field is required"
            details:
              type: object
              description: Additional error details (when available)
              example: { "param": "text", "reason": "missing_required_field" }Define reusable response headers for consistent API behavior:
  headers:
    X-RateLimit-Limit:
      description: Request limit per minute
      schema:
        type: integer
      example: 100
    X-RateLimit-Remaining:
      description: Remaining requests allowed in the current period
      schema:
        type: integer
      example: 95
    X-RateLimit-Reset:
      description: The time at which the current rate limit window resets (Unix timestamp)
      schema:
        type: integer
      example: 1626369250These headers provide crucial information about rate limiting that clients need to implement proper request throttling.
Security defines how your API is protected:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: JWT token obtained from the /auth/tokens endpoint
 
security:
  - BearerAuth: []Our AI Prompt Enhancer API uses JWT-based Bearer tokens, obtained through the authentication endpoint and used in the Authorization header for subsequent requests.
Here's how we defined our complete authentication flow in OpenAPI:
  /auth/tokens:
    post:
      summary: Generate authentication token
      description: Generates a JWT token for API authentication
      operationId: generateToken
      tags:
        - Authentication
      security: [] # No auth required for token generation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/TokenRequest"
            examples:
              basicAuth:
                value:
                  clientId: "frontend-client"
                  clientSecret: "your-api-key-here"
      responses:
        "200":
          description: Successfully generated token
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/TokenResponse"
        "400":
          description: Bad request - Invalid input
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized - Invalid credentials
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"This specification clearly documents how clients should authenticate with your API.
Use $ref pointers to reuse components rather than duplicating them:
responses:
  '400':
    description: Bad request - Invalid input
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/Error"
  '401':
    description: Unauthorized - Authentication failed
    content:
      application/json:
        schema:
          $ref: "#/components/schemas/Error"Include realistic examples for requests and responses to help developers understand your API:
examples:
  basicPrompt:
    value:
      text: "Write about quantum computing"
      format: "structured"
  successResponse:
    value:
      id: "prompt_abc123"
      originalText: "Write about quantum computing"
      enhancedText: "You are an expert physicist with deep knowledge in quantum mechanics..."
      format: "structured"
      createdAt: "2023-07-15T14:30:00Z"Include important response headers like rate limits and security headers:
headers:
  X-RateLimit-Limit:
    $ref: "#/components/headers/X-RateLimit-Limit"
  X-RateLimit-Remaining:
    $ref: "#/components/headers/X-RateLimit-Remaining"
  X-Frame-Options:
    schema:
      type: string
    description: Prevents clickjacking attacks
    example: "DENY"Use specific data types and validation rules to make your API predictable:
text:
  type: string
  description: The original prompt text to be enhanced
  minLength: 1
  maxLength: 8000
  example: "Write about quantum computing"
format:
  type: string
  description: The desired format for the enhanced prompt
  enum:
    - structured
    - paragraph
    - bullet
    - conversational
  default: structuredOnce you have an OpenAPI specification, you can generate interactive documentation. Here's how we implemented this in our AI Prompt Enhancer API:
// Setup Swagger UI in Express
const swaggerUi = require('swagger-ui-express');
const fs = require('fs');
const path = require('path');
 
function loadOpenApiSpec() {
    try {
        const publicOpenApiPath = path.join(__dirname, 'public', 'openapi.json');
        const rootOpenApiPath = path.join(__dirname, 'openapi.json');
        
        if (fs.existsSync(publicOpenApiPath)) {
            return JSON.parse(fs.readFileSync(publicOpenApiPath, 'utf8'));
        } else if (fs.existsSync(rootOpenApiPath)) {
            return JSON.parse(fs.readFileSync(rootOpenApiPath, 'utf8'));
        }
    } catch (error) {
        console.error('Error loading OpenAPI specification:', error.message);
        return {
            openapi: "3.0.3",
            info: {
                title: "AI Prompt Enhancer API",
                version: "1.0.0",
                description: "Error loading API documentation."
            },
            paths: {}
        };
    }
}
 
const openApiSpec = loadOpenApiSpec();
 
const swaggerUiOptions = {
    explorer: true,
    customCss: '.swagger-ui .topbar { display: none }',
    swaggerOptions: {
        docExpansion: 'list',
        filter: true,
        tagsSorter: 'alpha',
        operationsSorter: 'alpha',
    }
};
 
app.use('/docs', swaggerUi.serve, swaggerUi.setup(openApiSpec, swaggerUiOptions));This creates interactive documentation available at /docs that allows developers to test API endpoints directly.
Generate client libraries in various programming languages:
# Generate a TypeScript client
npx openapi-generator-cli generate \
  -i openapi.yaml \
  -g typescript-fetch \
  -o ./typescript-client
 
# Generate a Python client
npx openapi-generator-cli generate \
  -i openapi.yaml \
  -g python \
  -o ./python-client
 
# Generate a JavaScript client
npx openapi-generator-cli generate \
  -i openapi.yaml \
  -g javascript \
  -o ./javascript-clientOne of the biggest advantages of OpenAPI is enabling mock servers for parallel development:
# Create a mock server using Prism
npx @stoplight/prism-cli mock -p 4010 openapi.yaml
 
# Your mock server is now running at http://localhost:4010Frontend developers can build against this mock API while backend developers implement the endpoints.
Before sharing your OpenAPI specification, validate it to catch issues:
# Use Spectral for comprehensive linting
npx @stoplight/spectral-cli lint openapi.yaml
 
# Use Swagger CLI for basic validation
npx swagger-cli validate openapi.yamlHere's how we integrated OpenAPI into our AI Prompt Enhancer development process:
// Generate JSON from YAML during build
const fs = require('fs');
const YAML = require('yaml');
 
const yamlContent = fs.readFileSync('openapi.yaml', 'utf8');
const jsonContent = YAML.parse(yamlContent);
fs.writeFileSync('public/openapi.json', JSON.stringify(jsonContent, null, 2));
 
console.log('OpenAPI JSON generated successfully');This ensures our documentation stays current with each deployment.
For our AI Prompt Enhancer API, we manage the OpenAPI specification as part of our codebase:
openapi.yaml file in the repository root./docs endpointThis approach ensures documentation never becomes outdated.
For the AI Prompt Enhancer API, we followed a documentation-first approach:
This process helped us catch inconsistencies early and provided a clear implementation guide for all team members.
❌ Inconsistent naming: Don't mix camelCase and snake_case in the same API
❌ Missing examples: Examples make your API much easier to understand and test
❌ Vague descriptions: Each field should have a clear, specific description
❌ No validation rules: Use minLength, maxLength, enum, and pattern where appropriate
❌ Incomplete error documentation: Document all possible error responses
❌ Missing security definitions: Clearly document authentication requirements
❌ Outdated specifications: Keep your OpenAPI file synchronized with the implementation
The OpenAPI specification is the single truth source guiding your entire API development process. By defining contracts first, you enable:
Try this contract-first approach on your next API project. Once you experience the benefits of OpenAPI-driven development, you'll wonder how you built APIs without it.