# FastAPI: turn a client's model into an API with a clear contract in a single session

> On a client site, the most persuasive thing is rarely a slide. It is a /docs link the client can click and try straight away, and FastAPI builds that link from the code you write.

Original: https://fdetimes.net/en/tools/fastapi-wrap-client-model-api/

It is Tuesday afternoon on a client site. Their data scientist hands you a notebook containing a model that predicts late deliveries and asks: "Can the app team call this?" The best answer before you leave for the day is a link the client can try for themselves, with a clear schema and tests to back it.

FastAPI was made for exactly that moment. The official documentation defines it as a Python web framework for building APIs based on standard Python type hints. It is open source under the MIT licence, and the official repository lives at github.com/fastapi/fastapi.

For an FDE, the value is that one piece of code produces three things at once: a data contract, interactive documentation and an API that can be tested immediately. Those are the three things a client needs to see before believing your demo can go on to production.

## Why does writing the code give you the docs too?

FastAPI is built on two open standards, OpenAPI (formerly known as Swagger) and JSON Schema. You declare data types with type hints and Pydantic models, and the framework translates them into a schema. There is no separate "write the documentation" step to forget to update.

The concrete result: start the app and you get an interactive documentation page, served by Swagger UI, at /docs with no further configuration. Alongside it, the full API description sits at /openapi.json. The client's app team can use that file to generate an SDK or check the contract without reading your code.

The tool's origins also fit the job of wrapping models. Sebastián Ramírez (@tiangolo), who created FastAPI as well as Typer and SQLModel, says he spent years building APIs with complex requirements, including machine learning, distributed systems and asynchronous jobs. FastAPI is built on top of Pydantic and Starlette.

## An endpoint that wraps a model, line by line

Take the late-delivery model above. The client's internal data table also holds the recipient's phone number, which must never reach an outside app. The minimal endpoint looks like this, where `score_late` is a hypothetical function that calls the client's model:

```python
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class ShipmentIn(BaseModel):
    shipment_id: str
    distance_km: float
    warehouse_id: str

class Prediction(BaseModel):
    shipment_id: str
    late_probability: float

@app.post("/predict", response_model=Prediction)
def predict(shipment: ShipmentIn):
    row = load_shipment(shipment.shipment_id)  # includes customer_phone
    return {
        "shipment_id": shipment.shipment_id,
        "late_probability": score_late(shipment),
        "customer_phone": row["customer_phone"],
    }
```

The function returns a dict with three fields, but `Prediction` declares only two. According to the documentation, FastAPI uses Pydantic to filter out any data not in the output model, so `customer_phone` never leaves the server. This is precisely the mechanism you need when wrapping a client's real data: a careless slip in the handler does not become a leak.

In the other direction, FastAPI is strict too. If the handler returns something that does not match `Prediction`, such as a response missing `late_probability`, FastAPI returns a server error instead of sending wrong data. The response model also attaches the output's JSON Schema to the OpenAPI description, so the /docs page describes exactly what the app team will receive.

**Key point:** A good API for a client would rather fail loudly than quietly return wrong data.

## Tests in the same session, no server required

A demo is only credible with tests, and this is where FastAPI keeps the cost low. You only need to install httpx and use pytest. `TestClient` is built on HTTPX, so tests run in-process, with no server to start and no port to open.

```python
from fastapi.testclient import TestClient
from app import app

client = TestClient(app)

def test_phone_never_leaks():
    r = client.post("/predict", json={
        "shipment_id": "S-001",
        "distance_km": 12.5,
        "warehouse_id": "HCM-1",
    })
    assert r.status_code == 200
    assert "customer_phone" not in r.json()
```

The test function is a plain `def`, not `async def`, even when the endpoint is async. That lets you write tests during the working session, even sitting alongside the client's engineers. This test should be the first one you write: it turns the promise "no personal data leaks" into a single assert anyone can read.

## Two easy mistakes when wrapping real data

The first is leaving out the output model. The filtering above depends on it; without that model, FastAPI has no list of fields to check against. The consequence is easy to see: whatever the handler returns, the client risks receiving, `customer_phone` included.

The second is returning an ORM object, or an entire row from the client's table, directly. Today the table has five harmless columns; next month the data team adds a column of personal information, and without a filtering layer the new column goes out with everything else and nobody notices.

The safe habit is always to go through a dedicated output model, even when it nearly duplicates the table. Then keep a test like `test_phone_never_leaks` in the suite, so that if someone accidentally deletes `response_model`, the test fails before the client sees any data slip out.

## Limits to state plainly to the client

FastAPI has not yet reached 1.0. The official release notes list version 0.157.0 on 2026-10-21, showing the project still ships new releases but remains in its 0.x phase. The practical advice is to pin the exact version in the dependency file of every demo you hand over, so that when the client reinstalls it months later it still runs exactly the same.

The second limit is scope. FastAPI handles the contract layer and HTTP communication; it does not make the client's model faster or more accurate. If the model takes several seconds per prediction, however polished the endpoint, it will be just as slow, and you still have to solve operations in the client's environment yourself.

## What to learn first, and what to put on your CV

The sensible order is type hints and Pydantic models first, because everything else is generated from them. Next comes `response_model`, then `TestClient`. These three pieces are enough to get you from a notebook to a documented, tested API in an afternoon.

If an FDE job description mentions building prototypes or integrating with client systems, this is a skill worth talking about. On your CV, do not just list "FastAPI" among your skills.

A line such as "wrapped a client's prediction model as an API with an OpenAPI schema and automated tests blocking personal-data leaks, delivered in one day" tells both the technical story and how you work with clients.

Next time someone asks "can the app team call this?", your answer should be a /docs link and a green test.

**Try this week:**

- Take a Python function you already have (a model, an SQL query), wrap it in a FastAPI endpoint and open /docs to try calling it.
- Add a dummy field such as customer_phone to the returned data, declare a response_model without that field, then write a test asserting it never gets out.
- Send that endpoint's /openapi.json to a colleague and ask them to call the API without asking you a single question.

## Sources

- [FastAPI (official documentation)](https://fastapi.tiangolo.com/)

- [First Steps - FastAPI](https://fastapi.tiangolo.com/tutorial/first-steps/)

- [Response Model - Return Type - FastAPI](https://fastapi.tiangolo.com/tutorial/response-model/)

- [Testing - FastAPI](https://fastapi.tiangolo.com/tutorial/testing/)

- [Sebastián Ramírez (tiangolo.com)](https://tiangolo.com)

- [History, Design and Future - FastAPI](https://fastapi.tiangolo.com/history-design-future/)

- [GitHub - fastapi/fastapi](https://github.com/fastapi/fastapi)

- [Release Notes - FastAPI](https://fastapi.tiangolo.com/release-notes/)
