OpenAPI Generation
End-to-end guide for generating and documenting RESTful APIs with OpenAPI 3.0+ specifications using Kestrun’s PowerShell cmdlets and class-based attributes.
Focus areas:
- Class-based Components: Define schemas, request bodies, and responses using PowerShell classes.
- Attributes: Decorate classes and properties with
[OpenApiSchemaComponent],[OpenApiPropertyAttribute], etc. - Document Metadata: Configure title, version, contact, license, and servers.
- Operation Decorators: Annotate route functions with
[OpenApiPath],[OpenApiResponse], and[OpenApiRequestBody]. - Inheritance: Reuse schemas via class inheritance.
Kestrun uses a code-first approach where PowerShell classes define your data models and attributes define your API specification.
1. Concepts
| Concept | Description |
|---|---|
| Schema Component | A PowerShell class decorated with [OpenApiSchemaComponent]. Defines data structure. |
| Request Body | A class decorated with [OpenApiRequestBodyComponent]. Defines payload structure. |
| Response | A class decorated with [OpenApiResponseComponent]. Defines response structure. |
| Parameter | A class decorated with [OpenApiParameterComponent]. Defines reusable parameters. |
| Property Attribute | [OpenApiPropertyAttribute] on class properties defines validation, examples, and descriptions. |
| Route Attribute | [OpenApiPath] on functions defines the HTTP method and route pattern. |
2. Typical Workflow
flowchart LR
A[Define Classes] --> B(Decorate with Attributes)
B --> C(New-KrServer)
C --> D(Add-KrOpenApiInfo)
D --> E(Define Route Functions)
E --> F(Enable-KrConfiguration)
F --> G(Add-KrApiDocumentationRoute)
G --> H(Add-KrOpenApiRoute)
H --> I(Build-KrOpenApiDocument)
I --> J(Start-KrServer)
3. Minimal Example
# 1. Define a Schema
[OpenApiSchemaComponent(Required = ('name'))]
class Pet {
[OpenApiPropertyAttribute(Description = 'Pet ID', Example = 1)]
[long]$id
[OpenApiPropertyAttribute(Description = 'Pet Name', Example = 'Fido')]
[string]$name
}
# 2. Setup Server & Metadata
$srv = New-KrServer -Name 'Pet API'
Add-KrEndpoint -Port 5000
Add-KrOpenApiInfo -Title 'Pet API' -Version '1.0.0'
# 3. Define Route
function getPet {
[OpenApiPath(HttpVerb = 'get', Pattern = '/pets/{id}')]
[OpenApiResponse(StatusCode = '200', Description = 'Found pet', Schema = [Pet])]
param([int]$id)
Write-KrJsonResponse @{ id = $id; name = 'Fido' }
}
# 4. Enable & Build
Enable-KrConfiguration
Add-KrApiDocumentationRoute -DocumentType Swagger
Add-KrOpenApiRoute
Build-KrOpenApiDocument
Start-KrServer -Server $srv
4. Component Schemas
Use [OpenApiSchemaComponent] to define reusable data models.
4.1 Basic Schema
[OpenApiSchemaComponent(Required = ('username', 'email'))]
class User {
[OpenApiPropertyAttribute(Description = 'Unique ID', Format = 'int64', Example = 1)]
[long]$id
[OpenApiPropertyAttribute(Description = 'Username', Example = 'jdoe')]
[string]$username
[OpenApiPropertyAttribute(Description = 'Email address', Format = 'email')]
[string]$email
}
4.2 Enums and Validation
Use PowerShell validation attributes alongside OpenAPI attributes.
[OpenApiSchemaComponent()]
class Product {
[OpenApiPropertyAttribute(Description = 'Product Status', Example = 'available')]
[ValidateSet('available', 'pending', 'sold')]
[string]$status
[OpenApiPropertyAttribute(Minimum = 0, Maximum = 100)]
[int]$stock
}
4.3 Arrays
To define a schema that is a list of other objects, use inheritance and the Array property.
[OpenApiSchemaComponent(Description = 'List of users', Array = $true)]
class UserList : User {}
5. Component Request Bodies
Use [OpenApiRequestBodyComponent] to define reusable request payloads. You can inherit from existing schemas to avoid duplication.
# Define the base schema
[OpenApiSchemaComponent(Required = ('name', 'price'))]
class ProductSchema {
[string]$name
[double]$price
}
# Define the Request Body Component
[OpenApiRequestBodyComponent(
Description = 'Product creation payload',
IsRequired = $true,
ContentType = ('application/json', 'application/xml')
)]
class CreateProductRequest : ProductSchema {}
Usage in Route:
function createProduct {
[OpenApiPath(HttpVerb = 'post', Pattern = '/products')]
[OpenApiRequestBody(Reference = 'CreateProductRequest')]
[OpenApiResponse(StatusCode = '201')]
param()
}
6. Component Responses
Use [OpenApiResponseComponent] to define reusable responses.
[OpenApiResponseComponent(Description = 'Standard error response')]
class ErrorResponse {
[OpenApiPropertyAttribute(Example = 400)]
[int]$code
[OpenApiPropertyAttribute(Example = 'Invalid input')]
[string]$message
}
Usage in Route:
function getProduct {
[OpenApiPath(HttpVerb = 'get', Pattern = '/products/{id}')]
[OpenApiResponse(StatusCode = '200', Schema = [ProductSchema])]
[OpenApiResponse(StatusCode = '404', Description = 'Not Found', Schema = [ErrorResponse])]
param()
}
7. Component Parameters
Use [OpenApiParameterComponent] to group reusable parameters (Query, Header, Cookie).
[OpenApiParameterComponent()]
class PaginationParams {
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Page number')]
[OpenApiPropertyAttribute(Minimum = 1, Default = 1)]
[int]$page
[OpenApiParameter(In = [OaParameterLocation]::Query, Description = 'Items per page')]
[OpenApiPropertyAttribute(Minimum = 1, Maximum = 100, Default = 20)]
[int]$limit
}
Usage in Route:
function listItems {
[OpenApiPath(HttpVerb = 'get', Pattern = '/items')]
[OpenApiParameter(Reference = 'PaginationParams')]
param()
}
8. Document Metadata
Configure the top-level API information.
# Basic Info
Add-KrOpenApiInfo -Title 'My API' -Version '1.0.0' -Description 'API Description'
# Contact & License
Add-KrOpenApiContact -Name 'Support' -Email 'help@example.com'
Add-KrOpenApiLicense -Name 'MIT' -Url 'https://opensource.org/licenses/MIT'
# Servers
Add-KrOpenApiServer -Url 'https://api.example.com' -Description 'Production'
Add-KrOpenApiServer -Url "http://localhost:5000" -Description 'Local'
# Tags (Grouping)
Add-KrOpenApiTag -Name 'Users' -Description 'User management'
Add-KrOpenApiTag -Name 'Products' -Description 'Product catalog'
9. Route Definitions
Routes are PowerShell functions decorated with attributes.
9.1 [OpenApiPath]
Defines the HTTP method, route pattern, and tags.
[OpenApiPath(
HttpVerb = 'post',
Pattern = '/users',
Summary = 'Create a user',
Tags = @('Users')
)]
9.2 [OpenApiResponse]
Defines possible responses. Can reference a class type directly or a component name.
# Reference by Type
[OpenApiResponse(StatusCode = '200', Schema = [User])]
# Reference by Component Name (String)
[OpenApiResponse(StatusCode = '400', SchemaRef = 'ErrorResponse')]
# Inline Description
[OpenApiResponse(StatusCode = '204', Description = 'No Content')]
9.3 [OpenApiRequestBody]
Defines the expected request body.
# Reference a Component
[OpenApiRequestBody(Reference = 'CreateUserRequest')]
# Inline Definition (less common)
[OpenApiRequestBody(Description = 'Raw text', ContentType = 'text/plain')]
9.4 [OpenApiParameter]
Defines individual parameters if not using a component.
[OpenApiParameter(Name = 'id', In = 'path', Required = $true, Type = [long])]
10. Building and Viewing
- Enable Configuration:
Enable-KrConfiguration - Register Viewers:
Add-KrApiDocumentationRoute -DocumentType Swagger(or Redoc, Scalar, etc.) - Register OpenAPI Route:
Add-KrOpenApiRoute - Build:
Build-KrOpenApiDocument - Test:
Test-KrOpenApiDocument - Start:
Start-KrServer ...
Access the UI at /swagger, /redoc, etc., and the raw JSON at /openapi/v1/openapi.json.
Note on CORS: If you plan to host the Swagger UI or other documentation viewers on a different domain or port than your API, you must enable Cross-Origin Resource Sharing (CORS) in your Kestrun server configuration to allow the browser to fetch the
openapi.jsonfile.
11. Component Reference
Attribute Usage Matrix
| Attribute | Target | Key Properties |
|---|---|---|
[OpenApiSchemaComponent] | Class | Key, Examples, Required, Description, Array |
[OpenApiRequestBodyComponent] | Class | Key, ContentType, IsRequired, Description |
[OpenApiResponseComponent] | Class | Description, JoinClassName |
[OpenApiParameterComponent] | Class | Description, JoinClassName |
[OpenApiHeaderComponent] | Class | Description, JoinClassName |
[OpenApiExampleComponent] | Class | Key, Summary, Description, ExternalValue |
[OpenApiPropertyAttribute] | Property | Description, Example, Format, Required, Enum, Minimum, Maximum, Default |
[OpenApiParameter] | Property | In (Query/Header/Path/Cookie), Name, Required, Description, Style, Explode |
[OpenApiPath] | Function | HttpVerb, Pattern, Summary, Description, Tags, OperationId |
[OpenApiResponse] | Function | StatusCode, Description, Schema (Type), SchemaRef (String), ContentType |
[OpenApiRequestBody] | Function | Reference, Description, ContentType, Required, Example |
Common Properties (OpenApiProperties)
These properties are available on [OpenApiSchemaComponent], [OpenApiPropertyAttribute], and others inheriting from the base properties class.
| Property | Type | Description |
|---|---|---|
Description | String | Markdown-enabled description. |
Required | String[] | List of required property names (Class level). |
Format | String | Data format hint (e.g., int64, email, date-time). |
Example | Object | Example value for the schema or property. |
Enum | String[] | Allowed values list. |
Default | Object | Default value. |
Minimum / Maximum | Double | Numeric range constraints. |
MinLength / MaxLength | Int | String length constraints. |
Pattern | String | Regex pattern for string validation. |
MinItems / MaxItems | Int | Array size constraints. |
UniqueItems | Bool | Whether array items must be unique. |
ReadOnly / WriteOnly | Bool | Property access modifiers. |
Deprecated | Bool | Marks the schema/property as deprecated. |
Nullable | Bool | Allows null values. |
Array | Bool | Treats the class as an array of its base type (Class level). |
12. Feature Matrix
| Feature | Status | Notes |
|---|---|---|
| Schemas | ✅ Supported | Use [OpenApiSchemaComponent] classes |
| Request Bodies | ✅ Supported | Use [OpenApiRequestBodyComponent] classes |
| Responses | ✅ Supported | Use [OpenApiResponseComponent] classes |
| Parameters | ✅ Supported | Use [OpenApiParameterComponent] classes |
| Headers | ✅ Supported | Use [OpenApiHeaderComponent] classes |
| Examples | ✅ Supported | Use [OpenApiExampleComponent] classes |
| Inheritance | ✅ Supported | PowerShell class inheritance works for schemas |
| Generics | 🚧 Partial | Use Array = $true for lists |
| Webhooks | ❌ Planned | Not yet implemented |
| Links | ❌ Planned | Not yet implemented |
| Extensions (x-*) | ❌ Planned | Not yet implemented |
13. External References
For deeper understanding of the underlying standards and tools:
-
OpenAPI Specification v3.1.0 The official standard defining the structure of the API description document.
-
Swagger UI Documentation Details on the default visualization tool used by
Add-KrApiDocumentationRoute. -
PowerShell Classes Microsoft documentation on defining classes, properties, and attributes in PowerShell.
-
JSON Schema Validation OpenAPI uses a subset of JSON Schema for data modeling. Understanding keywords like
pattern,minimum, andenumis helpful.