# FastAPI + Anthropic Python SDK: non-streaming message endpoint
1. Install the SDK: `pip install anthropic`. Instantiate `AsyncAnthropic()` in async FastAPI endpoints. The SDK ships both a sync and an async client (Anthropic's client-SDK docs list "Sync and async clients" for Python); the sync client blocks the event loop inside an `async def` endpoint, so the async one is the correct choice here.
2. Pass the API key from your server's secret store into the client constructor. Keep it server-side only. Never embed it in frontend code or ship it to the browser.
3. Call `client.messages.create` with a payload dict like this (quoted keys keep it valid in both Python and JSON):
```
{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"system": "You answer concisely.",
"messages": [{"role": "user", "content": "Explain idempotency keys."}]
}
```
4. `system` is a top-level parameter, not a message with a `system` role. The Messages API reference lists `system` alongside `messages` and `tools` as a top-level field. Sending a message with a `system` role inside `messages` is rejected.
5. Read the reply from `message.content` (a list of content blocks) and check `message.stop_reason`. For a plain text answer, the first block is a text block; take its `text` field.
6. Return `{"text": ..., "stop_reason": ...}` to your frontend. Never forward the raw message object unfiltered if it may contain thinking blocks or tool_use blocks you do not want the client to see.
Failure modes this prevents: using the sync client in an async endpoint and stalling every concurrent request; putting the system instructions in `messages` with a made-up role; returning raw SDK objects that leak internal block types.