FastAPI x GenAI

Types of API Requests

An API request is not just "go fetch me data." The client also has to say what kind of thing it wants to do: read something, create something, change it, delete it. HTTP has a method for each of those, and FastAPI gives you a decorator for each method. Pick the right one and your API reads like plain English.

Reading vs changing

The first split is simple. GET only reads. It should never change anything on the server. Everything else (POST, PUT, PATCH, DELETE) exists to change something. Keep that line clean and your API stays predictable: anyone can GET freely, but a DELETE means business.

Here is the whole set on our running blog example.

from fastapi import FastAPIfrom pydantic import BaseModelapp = FastAPI()class Blog(BaseModel):    title: str    content: strblogs = {1: {"title": "My First Blog", "content": "hello"}}@app.get("/blog/{blog_id}")          # read oneasync def read_blog(blog_id: int):    return blogs[blog_id]@app.post("/blog")                   # create a new oneasync def create_blog(blog: Blog):    blogs[len(blogs) + 1] = blog.model_dump()    return {"message": "created"}@app.put("/blog/{blog_id}")          # replace the whole thingasync def replace_blog(blog_id: int, blog: Blog):    blogs[blog_id] = blog.model_dump()    return {"message": "replaced"}@app.patch("/blog/{blog_id}")        # change part of itasync def update_blog(blog_id: int, blog: Blog):    blogs[blog_id].update(blog.model_dump())    return {"message": "updated"}@app.delete("/blog/{blog_id}")       # remove itasync def delete_blog(blog_id: int):    del blogs[blog_id]    return {"message": "deleted"}

Let's map each one:

  1. GET /blog/1 reads a blog. No body, nothing changes, safe to call a hundred times.

  2. POST /blog creates a new blog from the request body. Call it twice, get two blogs.

  3. PUT /blog/1 replaces blog 1 entirely with what you send.

  4. PATCH /blog/1 changes only the fields you send and leaves the rest alone.

  5. DELETE /blog/1 removes it.

PUT vs PATCH, the part people mix up

Both update, but they mean different things. PUT is "here is the full new version, overwrite it." PATCH is "here is just the bit that changed." If you only want to fix a typo in the title, PATCH with {"title": "..."} is the honest choice. Sending the whole blog through PUT to change one word works, but it says more than you mean.

The new one: QUERY

GET carries its parameters in the URL. Fine, until the query gets big, deeply nested, or a little too sensitive to sit in a plain URL. The usual workaround is POST, but POST is meant for changing things, so its responses are not cacheable and a client cannot safely retry it.

QUERY fills that gap. Standardized in June 2026 in RFC 10008, it sends a body like POST but stays safe and idempotent like GET, so responses can be cached and the request can be safely repeated. Picture a search endpoint that takes a rich JSON filter instead of a mile-long querystring.

It is fresh enough that framework support is still catching up, so you may not spot an @app.query() decorator yet. Worth knowing it exists, because you will start seeing it around. Spec here if you want the details: RFC 10008, The HTTP QUERY Method (https://www.rfc-editor.org/info/rfc10008/).

One habit to build early: match the method to the intent. A GET that quietly deletes something, or a POST used to fetch data, will confuse every tool and teammate that touches your API. The method is a promise. Keep it. 🙂

Promises are made to be broken 😁(Evil laughter....)