Tutorials·9 min read

How to Use an AI API in Python with FastAPI: Chat Endpoint Tutorial

Build a secure Python backend that proxies an AI API with FastAPI, including streaming responses, environment variables, and production error handling.

By Published

Python remains the default language for data teams, ML engineers, and many backend developers. If you are adding chat or completion features to a Python service, FastAPI is a strong choice: async-friendly, typed, and easy to deploy behind Gunicorn or Uvicorn. This tutorial shows how to call a REST AI API from FastAPI without exposing your key to clients.

If you already use Next.js on the frontend, pair this guide with our Next.js AI API integration so the browser talks only to your own backend.

Prerequisites

  • Python 3.11+
  • A Daymora API key (stored as an environment variable)
  • Basic familiarity with HTTP and JSON

Project setup

Create a virtual environment and install dependencies:

python -m venv .venv
source .venv/bin/activate
pip install fastapi uvicorn httpx python-dotenv

Add .env (never commit it):

DAYMORA_API_KEY=your_key_here

Follow the same key hygiene as in How to manage AI API keys securely.

Non-streaming chat endpoint

Create main.py:

import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import httpx

app = FastAPI()
API_URL = "https://daymora.com/api/v1/chat"

class Message(BaseModel):
    role: str
    content: str

class ChatRequest(BaseModel):
    messages: list[Message]
    model: str = "gpt-5"

@app.post("/api/chat")
async def chat(body: ChatRequest):
    api_key = os.environ.get("DAYMORA_API_KEY")
    if not api_key:
        raise HTTPException(status_code=500, detail="API key not configured")

    async with httpx.AsyncClient(timeout=120.0) as client:
        response = await client.post(
            API_URL,
            headers={
                "API_SECRET": api_key,
                "Content-Type": "application/json",
            },
            json={
                "model": body.model,
                "messages": [m.model_dump() for m in body.messages],
                "stream": False,
            },
        )

    if response.status_code >= 400:
        raise HTTPException(status_code=response.status_code, detail=response.text)

    return response.json()

Run locally:

uvicorn main:app --reload --port 8000

Streaming with Server-Sent Events

Most chat UIs expect tokens as they arrive. Enable streaming on the upstream request and forward the byte stream:

from fastapi.responses import StreamingResponse

@app.post("/api/chat/stream")
async def chat_stream(body: ChatRequest):
    api_key = os.environ["DAYMORA_API_KEY"]

    async def event_generator():
        async with httpx.AsyncClient(timeout=None) as client:
            async with client.stream(
                "POST",
                API_URL,
                headers={"API_SECRET": api_key, "Content-Type": "application/json"},
                json={
                    "model": body.model,
                    "messages": [m.model_dump() for m in body.messages],
                    "stream": True,
                },
            ) as response:
                if response.status_code >= 400:
                    yield f"data: {{\"error\": \"upstream failed\"}}\n\n"
                    return
                async for chunk in response.aiter_bytes():
                    yield chunk

    return StreamingResponse(event_generator(), media_type="text/event-stream")

For a deeper look at why SSE is the common default for LLM APIs, see AI API streaming: SSE vs WebSockets.

Rate limiting and abuse protection

Expose these routes only to authenticated users in your product. Add per-user limits so one account cannot burn through your quota — patterns mirror the Next.js examples in our API key security guide.

Cost predictability

Python services often fan out many internal jobs (summaries, classifiers, embeddings pipelines). Token billing makes each cron run a line item on your invoice. If AI is on the critical path every day, compare your measured monthly usage against flat-rate options in What is a flat-rate AI API?.

Deploying to production

  • Inject DAYMORA_API_KEY via your host's secret store (Railway, Fly.io, AWS, etc.)
  • Set timeout generously for long completions but cap max tokens in the JSON body
  • Log latency and status codes, not full prompts, unless you have a retention policy

Summary

A FastAPI proxy keeps credentials server-side, gives you one place for auth and rate limits, and works with both JSON and streaming clients. Start non-streaming to validate prompts, then add SSE for the chat UX your users expect.

Start building

Start building for $25/month

Flat-rate API access with fair usage included. GPT-5, Claude Sonnet 4, and Gemini 2.5 Pro. Straightforward REST API with code examples and a built-in tester.

Flat-rate AI API pricing. $25/month.

Create your API key →