Pydantic validates and serializes Python data using type hints. It converts compatible inputs and reports errors when values do not match the declared schema.
An order API, for example, needs to check an order's ID and total before processing it. An annotation such as total_cents: int describes the expected type, but Python does not enforce it. Pydantic checks the value when the application validates the order.
Applications can also use Pydantic to validate configuration, queue messages, and large language model (LLM) responses.
Copy link to headingHow Pydantic works
A model declares the expected fields and their constraints. Define one by subclassing BaseModel:
from pydantic import BaseModel, Field
class Order(BaseModel): order_id: str total_cents: int = Field(gt=0) note: str | None = None
order = Order.model_validate_json( '{"order_id": "a1", "total_cents": "1999"}')
print(order.total_cents)# 1999
print(type(order.total_cents))# <class 'int'>The input contains a string for total_cents. Pydantic's default lax mode converts it to an integer, then checks that it is greater than zero. For a value such as "free", Pydantic raises a ValidationError.
model_validate_json() accepts a JSON string or bytes containing a JSON document. Use model_validate() for Python objects such as dictionaries.
Fields without defaults are required. In this model, note: str | None = None accepts a string or None, and the caller can omit it. Remove the = None default and the caller must supply the field, even if its value is None.
Models can contain other models to validate nested request bodies and lists of records. The validation engine runs in Rust through the separately versioned pydantic-core package.
Pydantic also supports validation without a BaseModel subclass:
Pydantic dataclasses add validation through the
pydantic.dataclasses.dataclassdecorator.TypeAdaptervalidates types such aslist[int]or aTypedDictwithout a model class.@validate_callchecks a function's arguments before each call.
These interfaces use the same pydantic-core validation engine, though their inputs and configurations differ.
Copy link to headingPydantic vs. static type checking
Python's runtime does not enforce function and variable annotations. Tools such as mypy and Pyright use those annotations to detect inconsistencies before execution. Pydantic uses them to validate data during execution.
A codebase can pass static checks and still receive an invalid request body. Validating requests will not catch every internal type error, either. Use a checker during development and validate external data before using it.
Copy link to headingWhere to use runtime validation
Validate data that the application does not control before passing it to code that assumes a particular type or structure.
Copy link to headingAPI request bodies
FastAPI validates incoming JSON against declared request models before passing it to the route handler. By default, request validation failures produce a 422 response with error details.
The handler receives an Order with a positive integer total. It does not need to repeat those checks on the unchanged object.
Copy link to headingEnvironment variables and configuration
The separate pydantic-settings package reads environment variables and configured .env files into a typed settings class. It converts supported values and rejects invalid inputs.
Pydantic settings ignore operating-system environment variables that match no field or alias. A typo can therefore leave a default in use. Unknown entries in a .env file can instead raise a ValidationError under the default configuration. The settings documentation explains how extra and dotenv filtering affect this behavior.
Copy link to headingLLM outputs
Parsing a generated JSON response checks its syntax. A Pydantic model checks whether its fields match the application's schema before other code uses the result.
A response can match the schema and still contain an incorrect fact. Apply any domain checks needed before the output changes the application state. The guide to validating agent outputs covers checks for structured data, generated code, and database queries.
Copy link to headingQueue messages and webhook payloads
A consumer can validate a message when it decodes the payload. It can then report a validation error before a handler tries to read a missing key or use an invalid value.
Explicitly call validation, or use a transport that validates messages. Receiving JSON alone does not check it against a Pydantic model.
Copy link to headingConfigure conversion and validation rules
Copy link to headingChoose lax or strict validation
Lax mode converts compatible values, such as "1" to 1. A datetime field also accepts supported Unix timestamps and ISO 8601-style strings, such as "2032-04-23T10:20:30Z". The supported-type documentation lists the accepted formats and timestamp rules.
These conversions are suitable for inputs that arrive as strings, including URL parameters, HTTP headers, and environment variables.
Strict mode rejects more type mismatches. An integer field rejects "1" instead of converting it. JSON cannot represent every Python type, so strict JSON validation has exceptions. Date and time fields, for example, can still accept strings.
Configure strict validation at the level the application needs:
Pass
strict=Trueto a validation call.Set
Field(strict=True)on a field.Add
Strict()metadata to an annotation, such asAnnotated[int, Strict()].Set
model_config = ConfigDict(strict=True)on a model.
A field-level setting can override the model setting. For example, Field(strict=False) relaxes one field in a model configured as strict.
Accepting a numeric string may suit a query parameter. Between services that have agreed to send a JSON number, rejecting the string can expose a producer's bug.
Copy link to headingAdd constraints and custom validators
Use Field(gt=0) to require a positive total_cents value. Type validation checks whether the input can be an integer. The constraint checks whether that integer is allowed. Use these field constraints for other rules:
Use custom validators for rules that field constraints cannot express:
@field_validatorapplies a rule to a field.@model_validatorsupports checks involving multiple fields, such as requiring a note when an order's total exceeds an application-defined threshold.
The validator mode determines when the rule runs:
If a validator skips built-in checks, its code must enforce the required rules. A model validator in after mode should return the validated instance.
Validators can raise ValueError, AssertionError, or PydanticCustomError to report invalid data. An assert statement can raise AssertionError, but Python skips assertions when run with -O. Use explicit checks for rules that must run in that mode. Import PydanticCustomError from pydantic_core to define a custom error code, message, and context.
In Pydantic v2, a TypeError raised inside a validator propagates rather than being converted to a ValidationError. A handler that catches only ValidationError will not catch it.
Copy link to headingUnderstand the limits of a validated model
Validation checks the input against the configured rules. Later changes can make the object invalid.
By default, Pydantic does not validate ordinary BaseModel field defaults. It also leaves later assignments unchecked unless you enable validate_assignment=True. Custom validators can bypass type checks, too.
Enable validate_default when defaults need checking and validate_assignment when assignments need checking. Validate again after data changes or when another part of the application requires additional rules. The application must also check business rules that depend on its current state.
Copy link to headingHandle validation errors
For the Order model, a total_cents value of zero produces a greater_than error at total_cents. A nonnumeric string produces an integer-parsing error. The caller can distinguish a type mismatch from a failed constraint.
Pydantic can collect multiple failures into one ValidationError. Its error-handling methods provide formats for application code, logs, and responses:
Each error dictionary has a type code, loc location, msg message, and input value. It can also include ctx context and a documentation url. Locations can point into nested models and lists. Model-level errors may have an empty location.
Use the type code to distinguish failures in API responses, logs, or tests. For example, a strict integer field receiving "42" reports int_type. Avoid parsing the human-readable message.
Pydantic may not report every problem in an input. A failed check can prevent later validation from running. Options such as FailFast stop checking a sequence after an invalid item.
Copy link to headingSerialize data and generate JSON Schema
Use model_dump() to produce a Python dictionary or model_dump_json() to produce a JSON string. The same model that validates an order can serialize it for a response or message.
For the example order, order.model_dump() returns a dictionary containing order_id, the integer total_cents, and note. Pass exclude_none=True to omit the None note.
Both dump methods accept these serialization options:
Use model_dump(mode="json") when the result must remain a dictionary but contain JSON-compatible values. It converts supported Python values such as datetime objects and universally unique identifier (UUID) objects to strings. model_dump_json() performs those conversions and returns a JSON string.
For supported field types, model_json_schema() generates a schema compliant with JSON Schema Draft 2020-12 and OpenAPI 3.1. FastAPI uses generated schemas in its OpenAPI document and interactive API documentation.
Use TypeAdapter to validate or serialize a value such as list[Order] without another model class. It can also generate the schema. Its method names differ from those on BaseModel. For example, validate_python() validates a Python object.
For FastAPI responses, define an output model with only the fields the client should receive. To filter out passwords, omit them from that model. FastAPI does not identify sensitive fields for you. Returning a Response object directly bypasses its model-based response validation and filtering.
Copy link to headingOptimize validation work
By default, model_validate() assumes an existing model instance is valid and skips field revalidation. The revalidate_instances setting controls this behavior. See the model documentation.
If a profile shows validation taking too much time, check how the application uses models and adapters:
Reuse a
TypeAdapterrather than constructing one on every call. Each instantiation builds a validator and serializer.When holding a complete JSON document, generally prefer
model_validate_json(raw)overmodel_validate(json.loads(raw)). The performance guide notes exceptions involving somebeforeand wrap validators, so measure the relevant workload.Treat streamed chunks separately from complete messages.
model_validate_json()accepts a JSON document, not an iterator of chunks.Use
model_construct()andSkipValidationonly where the application can safely bypass those checks. UseAnywhen the schema places no type restriction on a value.
Check what the framework already validates. FastAPI validates declared request bodies. SQLModel builds on Pydantic and SQLAlchemy, Django Ninja supports Pydantic validators, and LangChain accepts Pydantic models for structured output. Reuse existing models where they apply, rather than maintaining duplicate schemas for the same data.
Copy link to headingMigrate from Pydantic v1 to v2
Pydantic v2 changed method names, configuration, and validator behavior. Some older APIs remain available with deprecation warnings; others require code changes. The migration guide covers the differences.
BaseSettings moved to pydantic-settings. Color and PaymentCardNumber moved to pydantic-extra-types. The bump-pydantic tool can automate parts of a migration. The pydantic.v1 namespace preserves imports for some older code, but check whether the framework supports it.
Check the Python version alongside package requirements. Vercel's Python runtime defaults to Python 3.12 and also supports 3.13 and 3.14. Pydantic added initial support for Python 3.14 in v2.12.
Copy link to headingUse Pydantic with Vercel's Python SDKs
Vercel's Python SDKs use Pydantic models to validate generated output and messages, and to encode and decode workflow data.
Copy link to headingAI SDK for Python
The AI SDK for Python, currently in public beta, accepts a Pydantic model as a structured-output contract.
To extract orders from text, pass output_type=Order to ai.stream(). Consume the stream, then read stream.output for the validated Order instance. Validation includes the model's positive-total constraint.
Copy link to headingWorkflow streams and hooks
The Workflow Python SDK, currently in beta, uses Pydantic to encode and decode typed stream values. An order-processing workflow could use an OrderProgress model with an order ID and status to report progress.
For external events, define a hook class that inherits from both pydantic.BaseModel and workflow.BaseHook. Its fields describe the payload that resumes the workflow, such as an approval decision and optional notes.
Copy link to headingQueue messages
The Vercel Queues Python SDK, currently in beta, uses TypedJsonTransport[T] to validate JSON payloads on receipt. It supports Pydantic models and other structured type annotations.
Install the typed extra with pip install "vercel-queue[typed]". Define a Topic[Order] so the producer and consumer share the message model. Publish with send() and register a consumer with @subscribe(topic=orders).
Copy link to headingPydantic AI through Vercel AI Gateway
The pydantic-ai package is imported as pydantic_ai. It manages model calls, tools, and agent execution, and uses Pydantic to validate structured outputs. Use VercelProvider to route Pydantic AI requests through AI Gateway.
For the guide's local setup:
Run
pip install pydantic-ai python-dotenv.Import
load_dotenvfromdotenvand callload_dotenv()before creating the provider.Set
VERCEL_AI_GATEWAY_API_KEYin a.envfile and keep that file out of version control.Set
output_type=Orderwhen creating the Pydantic AIAgent. After a successfulrun_sync()call, readresult.outputfor the validatedOrderinstance. The agent uses the same model as the order API, including its positive-total constraint.
Vercel deployments can use the automatically provided VERCEL_OIDC_TOKEN, a short-lived OpenID Connect (OIDC) credential, instead of a long-lived API key.
Copy link to headingFastAPI on Vercel
Vercel discovers a FastAPI instance named app at a supported entrypoint and uses Fluid compute by default. FastAPI handles validation for declared request bodies and ordinary model-based responses.
Follow the FastAPI deployment guide to deploy the app. You can import a repository or choose a starter from Vercel's templates.
Copy link to headingFrequently asked questions
Copy link to headingWhat is Pydantic used for?
Pydantic validates, parses, and serializes data using Python type hints. Common uses include API request and response models, settings parsing with pydantic-settings, structured LLM outputs, and typed queue messages. It can also generate JSON Schema for supported types.
Copy link to headingHow does Pydantic differ from Python type hints?
Type hints describe expected types but are not enforced by Python itself. Pydantic uses those annotations to validate data at runtime. An integer field receiving "123" can become 123 in lax mode or fail validation in strict mode.
Copy link to headingWhat is the current stable Pydantic version?
As of October 22, 2026, Pydantic v2.14 is the current stable release line, with v2.14.1 listed on PyPI. Check PyPI before choosing a version. pydantic-core and Pydantic AI have separate version numbers and release cycles.
Copy link to headingDoes FastAPI use Pydantic?
Yes. FastAPI uses Pydantic for request validation, schema generation, and response serialization. FastAPI v0.159.1 requires pydantic>=2.9.0.
Copy link to headingWhat is the difference between Pydantic and Pydantic AI?
Pydantic validates data at runtime. Pydantic AI is an agent framework from the same team that uses Pydantic to validate structured outputs. Install the library with pip install pydantic and the framework with pip install pydantic-ai.