Endpoints¶
An endpoint is a typed annotation on your client class:
Method— one of the endpoint types below; it fixes the HTTP method and how the request is serialized.RequestModel— a Pydantic model (orNonefor parameterless endpoints).ResponseModel— a Pydantic model, a response wrapper, orNone.Literal["/path"]— the path template, optionally with{placeholders}.
Endpoint types¶
| Sync | Async | HTTP Method | Request style | Typical use |
|---|---|---|---|---|
Get |
AsyncGet |
GET | Query params | Read operations |
Post |
AsyncPost |
POST | JSON body | Create operations |
Put |
AsyncPut |
PUT | JSON body | Full update |
Patch |
AsyncPatch |
PATCH | JSON body | Partial update |
Delete |
AsyncDelete |
DELETE | Query params | Delete operations |
The sync and async variants are interchangeable in shape — use the Async*
types on an AsyncAPIClient, the plain types on an APIClient.
How the request model maps to the request¶
When you call an endpoint, the request model is dumped (with exclude_none=True)
and split into three destinations:
- Path parameters. Any
{name}placeholder in the path is filled from the field of the same name on the request model. - Query string (GET / DELETE). All remaining fields are URL-encoded onto the query string.
- JSON body (POST / PUT / PATCH). All remaining fields are serialized into a JSON request body.
class UpdateUserRequest(BaseModel):
user_id: str # -> path: /users/{user_id}
name: str # -> JSON body
email: str # -> JSON body
class UserAPI(APIClient):
update_user: Put[UpdateUserRequest, User, Literal["/users/{user_id}"]]
client.update_user(UpdateUserRequest(user_id="7", name="Al", email="al@x.com"))
# PUT https://api.example.com/users/7 body: {"name": "Al", "email": "al@x.com"}
For a GET, the same leftover fields become query parameters instead:
class SearchRequest(BaseModel):
query: str
limit: int | None = None
class UserAPI(APIClient):
search_users: Get[SearchRequest, UserList, Literal["/users/search"]]
client.search_users(SearchRequest(query="ada", limit=10))
# GET https://api.example.com/users/search?query=ada&limit=10
Missing path parameters raise
If a {placeholder} in the path has no matching field in the request model
(after exclude_none), preparation raises ValueError.
Query value serialization¶
Query parameters are stringified with a small set of rules:
bool→"true"/"false"list→ comma-joined ([1, 2, 3]→"1,2,3")- everything else →
str(value)
What an endpoint returns¶
The return type is driven by the response model — see
Requests & Responses. In short: a Pydantic model is
parsed and returned as that model; TextResponse / BytesResponse wrap raw
content; None means no body is expected and the call returns None.