DEV Community

Fiyinfoluwa Ojo
Fiyinfoluwa Ojo

Posted on

POST /items: Adding New Data to Your API with FastAPI & Pydantic

From Read-Only to Interactive

Until now our API could only read data.
Today we add the ability to CREATE : the C in CRUD.

The Request & Response DTOs

Request : what the client sends

class ItemCreateDTO(BaseModel):
    name: str
    description: Optional[str] = None
    price: float

    @field_validator("price")
    def price_must_be_positive(cls, v):
        if v <= 0:
            raise ValueError("Price must be a positive number")
        return v
Enter fullscreen mode Exit fullscreen mode

Response : what the API returns

class ItemResponseDTO(BaseModel):
    id: int
    name: str
    description: Optional[str]
    price: float
    created_at: datetime
Enter fullscreen mode Exit fullscreen mode

Two separate DTOs : one for input, one for output.
That's clean API design.

The POST Endpoint

@app.post("/items", response_model=ItemResponseDTO, status_code=201)
def create_item(item: ItemCreateDTO):
    db = SessionLocal()
    new_item = Item(
        name=item.name,
        description=item.description,
        price=item.price
    )
    db.add(new_item)
    db.commit()
    db.refresh(new_item)
    db.close()
    return new_item
Enter fullscreen mode Exit fullscreen mode

Notice status_code=201 : that's the correct HTTP status
for a successful creation, not 200.

Testing in Postman

Valid Request

Valid Request

Missing Name — 422 Error

Missing Name

Negative Price — 422 Error

Negative Price

Lessons Learned

POST endpoints need two things done right:
validation on the way in and the correct status
code on the way out. 201 Created is not the same as 200 OK,
and that distinction matters in production systems.

Day 9 done. 21 more to go. 🔥

GDGoCBowen30dayChallenge

Top comments (0)