Request Bodies & Responses¶
Asas integrates with Pydantic on both ends of a call: Pydantic
models go in as the request body, and response_model validates what comes out.
Sending a request body¶
Any parameter that is a Pydantic BaseModel — or a list of them — is serialized to JSON and
sent as the request body:
from pydantic import BaseModel
from asas import AsasClient, post, Response
class CreateUser(BaseModel):
name: str
email: str
class MyClient(AsasClient):
@post("/users")
def create_user(self, response: Response, payload: CreateUser):
return response.json()
client = MyClient(base_url="https://api.example.com")
client.create_user(payload=CreateUser(name="Ada", email="ada@example.com"))
# body: {"name": "Ada", "email": "ada@example.com"}
A list of models becomes a JSON array:
@post("/users/bulk")
def create_users(self, response: Response, payload: list[CreateUser]):
return response.json()
A dict is not a body
Only Pydantic models are routed to the body. A plain dict argument is treated as query
parameters instead. Always wrap body data in a BaseModel.
Validating the response¶
Pass response_model to a decorator and Asas validates the response JSON through a Pydantic
TypeAdapter before handing it
to your method. This supports plain models, List[Model], and other typing constructs:
from pydantic import BaseModel
from asas import AsasClient, get
class User(BaseModel):
id: int
name: str
class MyClient(AsasClient):
@get("/users/{id}", response_model=User)
def get_user(self, user: User, id: int) -> User:
return user
client = MyClient(base_url="https://api.example.com")
user = client.get_user(id=1) # -> User(id=1, name="...")
When response_model is omitted, the raw Response object is
injected instead, and you call response.json() yourself.
Combining body and response models¶
A typical create-and-return endpoint uses both at once:
from pydantic import BaseModel
from asas import AsasClient, post
class CreateUser(BaseModel):
name: str
email: str
class User(BaseModel):
id: int
name: str
email: str
class MyClient(AsasClient):
@post("/users", response_model=User)
def create_user(self, user: User, payload: CreateUser) -> User:
return user
client = MyClient(base_url="https://api.example.com")
created = client.create_user(payload=CreateUser(name="Ada", email="ada@example.com"))
# `payload` is sent as the JSON body; the response is validated into `User`.
Empty bodies are fine
Because Asas returns the parsed result when your method body returns None, the method
body can be left as a single return user (or even just ...) purely for typing. See
the return convention.