⚡️ Using Clientele with FastAPI
This guide shows you how to scaffold a Python client for a FastAPI application using Clientele.
💡 Working Example: See a real FastAPI application with code examples from this guide in
server_examples/fastapi/
Prerequisites
- A FastAPI application with API endpoints
- FastAPI's automatic OpenAPI schema generation enabled (enabled by default)
Step 1: Get Your OpenAPI Schema
FastAPI automatically generates an OpenAPI schema for your API. You can access it at:
http://your-api-domain/openapi.json
For example, if your FastAPI app is running locally on port 8000:
http://localhost:8000/openapi.json
Downloading the Schema
You can either:
Option A: Use the URL directly (if the API is accessible):
clientele start-api -u http://localhost:8000/openapi.json -o my_client/
Option B: Download the schema file first:
curl http://localhost:8000/openapi.json > openapi.json
clientele start-api -f openapi.json -o my_client/
Step 2: Scaffold the Client
clientele start-api -u http://localhost:8000/openapi.json -o my_client/
Async Client
If your FastAPI app uses async endpoints and you want an async client:
clientele start-api -u http://localhost:8000/openapi.json -o my_client/ --asyncio
Step 3: Use the scaffolded Client
Usage Example
from my_client import client, schemas
# Call a simple GET endpoint
response = client.get_users_users_get()
# Call a POST endpoint with data
user_data = schemas.CreateUserRequest(
name="Alice",
email="[email protected]"
)
response = client.create_user_users_post(data=user_data)
# Handle different response types
match response:
case schemas.UserResponse():
print(f"User created: {response.name}")
case schemas.HTTPValidationError():
print(f"Validation error: {response.detail}")
Async usage Example
from my_async_client import client, schemas
async def create_user():
user_data = schemas.CreateUserRequest(
name="Alice",
email="[email protected]"
)
response = await client.create_user_users_post(data=user_data)
return response
Working with operationId
FastAPI generates operationId values for each endpoint, which Clientele uses to create function names.
Default operationId Generation
By default, FastAPI creates operation IDs like: {function_name}_{path}_{method}
For example:
- Function
get_users()at path/userswith GET →get_users_users_get - Function
create_user()at path/userswith POST →create_user_users_post
Custom operationId
You can customize the operation ID in FastAPI to get cleaner function names:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users", operation_id="list_users")
def get_users():
return []
@app.post("/users", operation_id="create_user")
def create_user(user: UserCreate):
return user
This generates:
client.list_users()instead ofclient.get_users_users_get()client.create_user()instead ofclient.create_user_users_post()
Authentication
See api authentication.
Path and Query Parameters
FastAPI's path and query parameters are automatically converted to function arguments:
FastAPI Endpoint
@app.get("/users/{user_id}")
def get_user(user_id: int, include_posts: bool = False):
return {"user_id": user_id, "include_posts": include_posts}
Client Usage
# Required path parameter, optional query parameter
response = client.get_user_users_user_id_get(
user_id=123,
include_posts=True
)
Response Models
FastAPI's response models become Pydantic schemas in the client:
FastAPI Endpoint
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str
email: str
@app.get("/users/{user_id}", response_model=User)
def get_user(user_id: int):
return User(id=user_id, name="Alice", email="[email protected]")
Generated Client Usage
response = client.get_user_users_user_id_get(user_id=123)
# response is typed as schemas.User
print(response.name)
Best Practices
- Use custom operationId values for cleaner function names
- Keep schemas in sync by regenerating after API changes
- Version your generated client in git to track changes
- Test thoroughly after regenerating
- Use the same Python version for both API and client when possible