Notice that response_model is a parameter of the "decorator" method (get, post, etc). Not of your path operation function, like all the parameters and body.

It receives a standard Pydantic model and will:

Convert the output data to the type declarations of the model

Validate the data

Add a JSON Schema for the response, in the OpenAPI path operation

Will be used by the automatic documentation systems

But most importantly:

Will limit the output data to that of the model. We'll see how that's important below.

Return the same input data

Here we are declaring a UserIn model, it will contain a plaintext password:

fromfastapiimportFastAPIfrompydanticimportBaseModelfrompydantic.typesimportEmailStrapp=FastAPI()classUserIn(BaseModel):username:strpassword:stremail:EmailStrfull_name:str=None# Don't do this in production!@app.post("/user/",response_model=UserIn)asyncdefcreate_user(*,user:UserIn):returnuser

And we are using this model to declare our input and the same model to declare our output:

fromfastapiimportFastAPIfrompydanticimportBaseModelfrompydantic.typesimportEmailStrapp=FastAPI()classUserIn(BaseModel):username:strpassword:stremail:EmailStrfull_name:str=None# Don't do this in production!@app.post("/user/",response_model=UserIn)asyncdefcreate_user(*,user:UserIn):returnuser

Now, whenever a browser is creating a user with a password, the API will return the same password in the response.

In this case, it might not be a problem, becase the user himself is sending the password.

But if we use the same model for another path operation, we could be sending the passwords of our users to every client.

Danger

Never send the plain password of a user in a response.

Add an output model

We can instead create an input model with the plaintext password and an output model without it: