---
title: "Talk to the librarian"
method: POST
path: "/api/chat"
tags: ["chat"]
---

# Talk to the librarian

`POST /api/chat`

## Request

- Base URL: `https://leafle.org` (the document declares no server; this is the origin it was published from)
- URL: `https://leafle.org/api/chat`
- Auth: HTTP bearer

**Access: write token.**

Post a new message, or `message: null` to continue after discovery. Returns an SSE stream; see **Stream a conversation** above and the response frame schemas below. Only one turn per reader can run at a time (409). A disconnect may leave the turn running; recover through `/api/me` before retrying.

## Request body

- ChatRequest
  - `resume_handoff` boolean
  - `message` string, nullable
  - `lead_in` string, nullable
  - `reader_id` integer, nullable

## Response `200`

Server-sent events: each data value is one JSON frame matching a schema below, followed by a blank line. Lines starting with ':' are keepalives. The stream ends with a done or error frame (enrichment uses done: true).

## Other responses

- `400`: Invalid input; see detail for the reason.
- `401`: Missing or unusable credential.
- `403`: Insufficient token scope or the reader is outside your account.
- `409`: Conflicting state: a turn is running, the book is already read, or the library offer has been settled.
- `422`: Validation Error
- `429`: Request or usage limit reached. Wait before retrying.
- `503`: Capacity is unavailable or the service is restarting. Honour Retry-After when present.

---

[API](https://skmtc.dev/leafle/apis/leafle-api.md) · [All operations](https://skmtc.dev/leafle/apis/leafle-api/llms.txt) · [OpenAPI document](https://skmtc.dev/leafle/apis/leafle-api/revisions/f2e56cb74495?raw)
