Skip to content

📘 Generate from OpenAPI

Generate Pydantic models from OpenAPI 3 schema definitions.

🚀 Quick Start

datamodel-codegen --input api.yaml --input-file-type openapi --output model.py

📝 Example

api.yaml
openapi: "3.0.0"
info:
  version: 1.0.0
  title: Swagger Petstore
  license:
    name: MIT
servers:
  - url: http://petstore.swagger.io/v1
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          description: How many items to return at one time (max 100)
          required: false
          schema:
            type: integer
            format: int32
      responses:
        '200':
          description: A paged array of pets
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      summary: Create a pet
      operationId: createPets
      tags:
        - pets
      responses:
        '201':
          description: Null response
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      tags:
        - pets
      parameters:
        - name: petId
          in: path
          required: true
          description: The id of the pet to retrieve
          schema:
            type: string
      responses:
        '200':
          description: Expected response to a valid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Pets"
        default:
          description: unexpected error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
components:
  schemas:
    Pet:
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
    Pets:
      type: array
      items:
        $ref: "#/components/schemas/Pet"
    Error:
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string

✨ Generated model.py:

# generated by datamodel-codegen:
#   filename:  api.yaml

from __future__ import annotations

from pydantic import BaseModel, RootModel


class Pet(BaseModel):
    id: int
    name: str
    tag: str | None = None


class Pets(RootModel[list[Pet]]):
    root: list[Pet]


class Error(BaseModel):
    code: int
    message: str

📖 readOnly / writeOnly Properties

OpenAPI 3.x supports readOnly and writeOnly property annotations:

  • 📤 readOnly: Property is only returned in responses (e.g., id, created_at)
  • 📥 writeOnly: Property is only sent in requests (e.g., password)

⚙️ Option: --read-only-write-only-model-type

This option generates separate Request/Response models based on these annotations.

Value Description
(not set) Default. No special handling (backward compatible)
request-response Generate only Request/Response models (no base model)
all Generate base model + Request + Response models

📋 Example Schema

openapi: "3.0.0"
info:
  title: User API
  version: "1.0"
paths: {}
components:
  schemas:
    User:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          readOnly: true      # Server-generated, not in requests
        name:
          type: string
        password:
          type: string
          writeOnly: true     # Client-only, not in responses
        created_at:
          type: string
          format: date-time
          readOnly: true

✨ Generated Output

datamodel-codegen --input user.yaml --input-file-type openapi \
    --output-model-type pydantic_v2.BaseModel \
    --read-only-write-only-model-type all
from pydantic import BaseModel
from typing import Optional
from datetime import datetime

# 📥 Request model: excludes readOnly fields (id, created_at)
class UserRequest(BaseModel):
    name: str
    password: Optional[str] = None

# 📤 Response model: excludes writeOnly fields (password)
class UserResponse(BaseModel):
    id: int
    name: str
    created_at: Optional[datetime] = None

# 📦 Base model: contains all fields
class User(BaseModel):
    id: int
    name: str
    password: Optional[str] = None
    created_at: Optional[datetime] = None

🎯 Usage Patterns

Use Case Recommended Option Generated Models
API client validation request-response UserRequest, UserResponse
Database ORM mapping (not set) User
Both client & ORM all User, UserRequest, UserResponse

🔗 Behavior with allOf Inheritance

When using allOf with $ref, fields from all referenced schemas are flattened into Request/Response models:

components:
  schemas:
    Timestamps:
      type: object
      properties:
        created_at:
          type: string
          format: date-time
          readOnly: true

    User:
      allOf:
        - $ref: "#/components/schemas/Timestamps"
        - type: object
          properties:
            name:
              type: string

Generated UserRequest will exclude created_at (readOnly from Timestamps).

⚠️ Collision Handling

If a schema named UserRequest or UserResponse already exists, the generated model will be named UserRequestModel or UserResponseModel to avoid conflicts.

📤 Supported Output Formats

This option works with all output formats:

  • pydantic.BaseModel / pydantic_v2.BaseModel
  • dataclasses.dataclass
  • typing.TypedDict
  • msgspec.Struct

🔗 Supported $ref Types

readOnly/writeOnly resolution works with local and file reference types:

Reference Type Example Support
Local #/components/schemas/User ✅ Supported
File ./common.yaml#/User ✅ Supported

📖 See Also