OpenAPI Documentation

Automatically generate OpenAPI v3.0 documentation for your APIs with Swagger UI support

OpenAPI v3.0 Documentation Generation

WebApp 2.0.1 includes automatic OpenAPI v3.0 documentation generation, making it easy to document and test your APIs with tools like Swagger UI.

Overview

The OpenAPI documentation generator automatically creates comprehensive API documentation by analyzing your routes, controllers, and data models. This facilitates:

  • Interactive API Testing: Use Swagger UI for testing endpoints
  • Developer Experience: Clear documentation for API consumers
  • API Specification: Standard OpenAPI 3.0 compliant documentation
  • Code Generation: Enable client SDK generation from the spec

Features

Automatic Documentation Generation

  • Scans your routes and controllers automatically
  • Generates OpenAPI 3.0 compliant specifications
  • Includes request/response schemas
  • Documents authentication requirements

Swagger UI Integration

  • Built-in Swagger UI for interactive testing
  • Customizable documentation interface
  • Real-time API testing capabilities

Schema Generation

  • Automatic schema generation from Dart models
  • Support for complex nested objects
  • Validation rule documentation

Getting Started

Basic Setup

import 'package:webapp/wa_server.dart';
import 'package:webapp/wa_openapi.dart';

void main() async {
  var server = WaServer(configs: configs);
  
  // Enable OpenAPI documentation
  server.enableOpenAPI(
    title: 'My WebApp API',
    version: '1.0.0',
    description: 'A comprehensive API for my web application',
    servers: [
      OpenAPIServer(
        url: 'http://localhost:8085',
        description: 'Development server',
      ),
      OpenAPIServer(
        url: 'https://api.example.com',
        description: 'Production server',
      ),
    ],
  );
  
  server.addRouting(getWebRoute);
  await server.start();
}

Accessing Documentation

Once enabled, your OpenAPI documentation will be available at:

  • JSON Spec: http://localhost:8085/openapi.json
  • YAML Spec: http://localhost:8085/openapi.yaml
  • Swagger UI: http://localhost:8085/docs

Documenting Controllers

Use annotations to enhance your API documentation:

Basic Controller Documentation

@OpenAPIController(
  tag: 'Users',
  description: 'User management operations',
)
class UserController extends WaController {
  
  @OpenAPIOperation(
    summary: 'Get all users',
    description: 'Retrieve a list of all users with optional filtering',
    responses: {
      200: OpenAPIResponse(
        description: 'List of users retrieved successfully',
        content: {
          'application/json': OpenAPIMediaType(
            schema: OpenAPISchema(
              type: 'array',
              items: OpenAPISchema.fromModel(User),
            ),
          ),
        },
      ),
      401: OpenAPIResponse(description: 'Unauthorized'),
      500: OpenAPIResponse(description: 'Internal server error'),
    },
  )
  Future<void> getUsers() async {
    // Implementation
  }
  
  @OpenAPIOperation(
    summary: 'Create new user',
    description: 'Create a new user account',
    requestBody: OpenAPIRequestBody(
      required: true,
      content: {
        'application/json': OpenAPIMediaType(
          schema: OpenAPISchema.fromModel(CreateUserRequest),
        ),
      },
    ),
  )
  Future<void> createUser() async {
    // Implementation
  }
}

Route Parameters Documentation

@OpenAPIOperation(
  summary: 'Get user by ID',
  parameters: [
    OpenAPIParameter(
      name: 'id',
      location: ParameterLocation.path,
      required: true,
      description: 'User ID',
      schema: OpenAPISchema(type: 'integer'),
    ),
    OpenAPIParameter(
      name: 'include',
      location: ParameterLocation.query,
      description: 'Additional data to include (profile, posts)',
      schema: OpenAPISchema(type: 'string'),
    ),
  ],
)
Future<void> getUserById() async {
  var userId = rq.params['id'];
  var include = rq.input('include');
  // Implementation
}

Model Documentation

Document your data models for automatic schema generation:

Basic Model

@OpenAPIModel(
  description: 'User account information',
  example: {
    'id': 123,
    'name': 'John Doe',
    'email': 'john@example.com',
    'status': 'active',
  },
)
class User {
  @OpenAPIProperty(
    description: 'Unique user identifier',
    example: 123,
  )
  int id;
  
  @OpenAPIProperty(
    description: 'User full name',
    minLength: 2,
    maxLength: 100,
    example: 'John Doe',
  )
  String name;
  
  @OpenAPIProperty(
    description: 'User email address',
    format: 'email',
    example: 'john@example.com',
  )
  String email;
  
  @OpenAPIProperty(
    description: 'Account status',
    enumValues: ['active', 'inactive', 'pending'],
    example: 'active',
  )
  String status;
  
  @OpenAPIProperty(
    description: 'Account creation date',
    format: 'date-time',
  )
  DateTime createdAt;
}

Nested Models

@OpenAPIModel(description: 'User profile with additional details')
class UserProfile {
  @OpenAPIProperty(description: 'Basic user information')
  User user;
  
  @OpenAPIProperty(
    description: 'User preferences',
    additionalProperties: true,
  )
  Map<String, dynamic> preferences;
  
  @OpenAPIProperty(
    description: 'User posts',
    type: 'array',
  )
  List<Post> posts;
}

Authentication Documentation

Document your authentication schemes:

Bearer Token Authentication

server.enableOpenAPI(
  // ... other config
  securitySchemes: {
    'bearerAuth': OpenAPISecurityScheme(
      type: 'http',
      scheme: 'bearer',
      bearerFormat: 'JWT',
      description: 'JWT token authentication',
    ),
  },
  security: [
    {'bearerAuth': []},
  ],
);

API Key Authentication

server.enableOpenAPI(
  // ... other config
  securitySchemes: {
    'apiKey': OpenAPISecurityScheme(
      type: 'apiKey',
      name: 'X-API-Key',
      location: 'header',
      description: 'API key for authentication',
    ),
  },
);

Controller-Level Security

@OpenAPIController(
  tag: 'Admin',
  security: [
    {'bearerAuth': ['admin']},
  ],
)
class AdminController extends WaController {
  // All operations require bearer token with admin scope
}

Advanced Configuration

Custom Swagger UI

server.enableOpenAPI(
  // ... other config
  swaggerUIConfig: SwaggerUIConfig(
    title: 'My API Documentation',
    favicon: '/favicon.ico',
    customCSS: '''
      .swagger-ui .topbar { background-color: #2c3e50; }
    ''',
    customJS: '''
      console.log('Custom Swagger UI loaded');
    ''',
  ),
);

Response Examples

@OpenAPIOperation(
  responses: {
    200: OpenAPIResponse(
      description: 'Success response',
      content: {
        'application/json': OpenAPIMediaType(
          schema: OpenAPISchema.fromModel(User),
          examples: {
            'example1': OpenAPIExample(
              summary: 'Active user',
              value: {
                'id': 1,
                'name': 'John Doe',
                'email': 'john@example.com',
                'status': 'active',
              },
            ),
            'example2': OpenAPIExample(
              summary: 'Inactive user',
              value: {
                'id': 2,
                'name': 'Jane Smith',
                'email': 'jane@example.com',
                'status': 'inactive',
              },
            ),
          },
        ),
      },
    ),
  },
)
Future<void> getUser() async {
  // Implementation
}

Error Response Documentation

// Define reusable error responses
var commonErrorResponses = {
  400: OpenAPIResponse(
    description: 'Bad Request',
    content: {
      'application/json': OpenAPIMediaType(
        schema: OpenAPISchema.fromModel(ErrorResponse),
      ),
    },
  ),
  401: OpenAPIResponse(description: 'Unauthorized'),
  403: OpenAPIResponse(description: 'Forbidden'),
  404: OpenAPIResponse(description: 'Not Found'),
  500: OpenAPIResponse(description: 'Internal Server Error'),
};

Validation Integration

Integrate with form validators for automatic validation documentation:

@OpenAPIOperation(
  requestBody: OpenAPIRequestBody(
    content: {
      'application/json': OpenAPIMediaType(
        schema: OpenAPISchema(
          type: 'object',
          properties: {
            'email': OpenAPISchema(
              type: 'string',
              format: 'email',
              description: 'Valid email address',
            ),
            'password': OpenAPISchema(
              type: 'string',
              minLength: 8,
              description: 'Password (minimum 8 characters)',
            ),
          },
          required: ['email', 'password'],
        ),
      ),
    },
  ),
)
Future<void> login() async {
  var validator = WaFormValidator(rq);
  validator.validateEmail('email');
  validator.validateRequired('password');
  validator.validateMinLength('password', 8);
  
  if (!validator.isValid) {
    return rq.renderJson({'errors': validator.errors});
  }
  
  // Login logic
}

Generating Client SDKs

Use the generated OpenAPI specification to create client SDKs:

Using OpenAPI Generator

# Install OpenAPI Generator
npm install -g @openapitools/openapi-generator-cli

# Generate JavaScript/TypeScript client
openapi-generator generate \
  -i http://localhost:8085/openapi.json \
  -g typescript-axios \
  -o ./generated-client

# Generate Python client
openapi-generator generate \
  -i http://localhost:8085/openapi.json \
  -g python \
  -o ./python-client

Best Practices

Documentation Guidelines

  1. Comprehensive Descriptions: Provide clear, detailed descriptions for all operations
  2. Realistic Examples: Use realistic data in examples
  3. Error Documentation: Document all possible error responses
  4. Consistent Naming: Use consistent naming conventions
  5. Version Management: Keep API versions documented

Schema Design

  1. Reusable Components: Create reusable schema components
  2. Validation Rules: Include validation constraints in schemas
  3. Nested Objects: Properly structure nested object relationships
  4. Enum Documentation: Document all possible enum values

Security Documentation

  1. Authentication Methods: Clearly document all authentication methods
  2. Authorization Scopes: Define and document permission scopes
  3. Rate Limiting: Document rate limiting policies
  4. CORS Configuration: Document CORS settings

Troubleshooting

Common Issues

Missing Documentation

// Ensure controllers are properly annotated
@OpenAPIController(tag: 'MyController')
class MyController extends WaController {
  // Operations must be annotated too
  @OpenAPIOperation(summary: 'My operation')
  Future<void> myOperation() async {}
}

Schema Generation Errors

// Ensure models have proper annotations
@OpenAPIModel()
class MyModel {
  @OpenAPIProperty()
  String property;
}

Authentication Issues

// Verify security schemes are properly configured
server.enableOpenAPI(
  securitySchemes: {
    'bearerAuth': OpenAPISecurityScheme(/* config */),
  },
);

Next Steps