# KDPBot API quickstart

Zero to a finished, exported book in eight `curl` calls.

- **API base URL:** `https://bookgen-backend-5zuf.onrender.com/api`
- **Auth:** `Authorization: Bearer <access token>`
- **Trailing slashes are mandatory on every path.**
- **List endpoints return bare JSON arrays** — there is no pagination envelope, apart from `GET /api/proofreading-reports/{id}/suggestions/`, the one paged endpoint.

Related: [authentication](https://kdpbot.com/docs/authentication.md) · [errors](https://kdpbot.com/docs/errors.md) · [rate limits](https://kdpbot.com/docs/rate-limits.md) · [full API reference](https://kdpbot.com/docs/api.md) · [OpenAPI 3.1 spec](https://kdpbot.com/openapi.json) · [agent instructions](https://kdpbot.com/agents.md)

---

## 0. Set up your shell for the KDPBot API

```bash
export API=https://bookgen-backend-5zuf.onrender.com/api
```

## 1. Create an account (or log in)

### Register

```bash
curl -sS -X POST "$API/auth/register/" \
  -H 'Content-Type: application/json' \
  -d '{
        "username": "jane_publisher",
        "email": "jane@example.com",
        "password": "a-strong-password",
        "first_name": "Jane",
        "last_name": "Doe"
      }'
```

**201 Created**

```json
{
  "user": {
    "id": 1042,
    "username": "jane_publisher",
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "email_verified": false
  },
  "tokens": {
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIi...",
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCI..."
  },
  "message": "Registration successful"
}
```

If email verification is enabled for your account, the response omits `tokens` and returns `"email_verification_required": true` instead. Follow the emailed link, then log in.

### Log in

```bash
curl -sS -X POST "$API/auth/login/" \
  -H 'Content-Type: application/json' \
  -d '{"email":"jane@example.com","password":"a-strong-password"}'
```

**200 OK**

```json
{
  "user": {
    "id": 1042,
    "username": "jane_publisher",
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "email_verified": true,
    "avatar_url": null,
    "is_staff": false,
    "is_superuser": false,
    "subscription": {
      "id": 77,
      "status": "active",
      "plan": {
        "id": 2,
        "name": "Professional",
        "slug": "professional",
        "features": {
          "books_per_month": 30,
          "ai_images_per_month": 200,
          "max_word_count_per_book": 100000,
          "export_formats": ["pdf", "docx", "epub"],
          "watermark": false
        }
      },
      "current_period_end": "2026-10-02T00:00:00Z"
    }
  },
  "tokens": {
    "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  }
}
```

Capture the access token:

```bash
export ACCESS=$(curl -sS -X POST "$API/auth/login/" \
  -H 'Content-Type: application/json' \
  -d '{"email":"jane@example.com","password":"a-strong-password"}' \
  | python3 -c 'import sys,json; print(json.load(sys.stdin)["tokens"]["access"])')
```

The access token is valid for 24 hours. See [authentication](https://kdpbot.com/docs/authentication.md) for the refresh flow.

## 2. Check that your KDPBot account can start a book

Optional but cheap, and it saves you from a `402` three calls later.

```bash
curl -sS "$API/auth/subscriptions/book-creation-options/" \
  -H "Authorization: Bearer $ACCESS"
```

**200 OK**

```json
{
  "can_create": true,
  "subscription_available": true,
  "suggested_source": "subscription",
  "credits_available": false,
  "options": [{"source": "subscription", "label": "Subscription", "max_words": 150000, "available": true}],
  "suggested_source": "subscription",
  "max_words": 100000
}
```

Keep `target_word_count` at or below `max_words`, or step 5 returns `402`.

## 3. Create the book

```bash
curl -sS -X POST "$API/books/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{
        "title": "The Complete Guide to Remote Work",
        "subtitle": "Strategies for Distributed Teams in 2026",
        "genre": "non-fiction",
        "target_audience": "Team leads managing distributed engineering teams",
        "description": "A practical handbook covering hiring, async communication, tooling and culture for fully remote organisations.",
        "chapter_count": 12,
        "target_word_count": 36000,
        "trim_size": "6x9",
        "content_language": "en"
      }'
```

**201 Created** (abridged — the full object also carries `chapters`, `progress`, `images` and editor telemetry)

```json
{
  "id": 4821,
  "user": { "id": 1042, "username": "jane_publisher", "email": "jane@example.com" },
  "title": "The Complete Guide to Remote Work",
  "subtitle": "Strategies for Distributed Teams in 2026",
  "genre": "non-fiction",
  "target_audience": "Team leads managing distributed engineering teams",
  "description": "A practical handbook covering hiring, async communication, tooling and culture for fully remote organisations.",
  "chapter_count": 12,
  "target_word_count": 36000,
  "word_count": 0,
  "trim_size": "6x9",
  "status": "draft",
  "cover_image": null,
  "cover_url": null,
  "content_language": "en",
  "is_autopilot": false,
  "chapters": [],
  "progress": null,
  "created_at": "2026-09-02T13:58:04Z",
  "updated_at": "2026-09-02T13:58:04Z"
}
```

```bash
export BOOK_ID=4821
```

**Field notes.** `genre` ∈ `fiction, non-fiction, mystery, romance, sci-fi, fantasy, biography, self-help, business, other`. `chapter_count` defaults to `10`, `target_word_count` to `40000`, `trim_size` to `6x9`, `content_language` to `en`. `trim_size` ∈ `5x8, 5.25x8, 5.5x8.5, 6x9, 6.14x9.21, 6.69x9.61, 7x10, 7.5x9.25, 8x10, 8.25x6, 8.25x8.25, 8.5x11`. Unknown keys are silently ignored, so a typo in a field name fails quietly — check the response.

Quota is checked here but **not consumed**; it is consumed when generation completes, so drafts are free.

## 4. Generate the outline

```bash
curl -sS -X POST "$API/books/$BOOK_ID/generate-outline/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' -d '{}'
```

Synchronous, typically 10–60 seconds. The request body is ignored.

**200 OK** (abridged)

```json
{
  "id": 4821,
  "title": "The Complete Guide to Remote Work",
  "status": "outline",
  "chapter_count": 12,
  "chapters": [
    {
      "id": 90311,
      "book": 4821,
      "chapter_number": 1,
      "title": "Why Most Remote Transitions Fail",
      "title_options": ["Why Most Remote Transitions Fail", "The Remote Failure Pattern"],
      "summary": "Diagnoses the four structural mistakes companies make in the first ninety days of going remote.",
      "content": "",
      "target_word_count": 3000,
      "actual_word_count": 0,
      "word_count": 0,
      "is_generated": false,
      "created_at": "2026-09-02T13:59:20Z",
      "updated_at": "2026-09-02T13:59:20Z"
    }
  ],
  "progress": {
    "book": 4821,
    "total_chapters": 12,
    "completed_chapters": 0,
    "current_chapter": 0,
    "percentage": 0,
    "generation_status": "running",
    "status_message": "Outline ready"
  }
}
```

> **Warning:** this call deletes every existing chapter and writes a fresh set. Do not call it twice unless you intend to discard edits.

### Optional: replace the AI outline with your own

```bash
curl -sS -X POST "$API/books/$BOOK_ID/update-outline/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{
        "chapters": [
          { "chapter_number": 1, "title": "Why Most Remote Transitions Fail",
            "summary": "The four structural mistakes companies make in the first ninety days." },
          { "chapter_number": 2, "title": "Hiring for Async",
            "summary": "Screening, trial projects and time-zone strategy." }
        ]
      }'
```

## 5. Start generation

```bash
curl -sS -X POST "$API/books/$BOOK_ID/generate/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' -d '{}'
```

**202 Accepted**

```json
{
  "message": "Generation started",
  "book_id": 4821,
  "task_id": "b0c1f2e4-6a19-4d3c-9f77-2e5a1c8d0b44",
  "mode": "celery"
}
```

The path is `/generate/`, not `/generate_content/`. The book's `status` becomes `generating` immediately and the work runs in a background worker.

Failure branches to expect here: `402` when the monthly book quota is exhausted or `target_word_count` exceeds your plan's `max_word_count_per_book`; `400` when generation is already running or the book has no chapters yet.

## 6. Poll until it finishes

```bash
curl -sS "$API/books/$BOOK_ID/generation-status/" \
  -H "Authorization: Bearer $ACCESS"
```

**200 OK — in progress**

```json
{
  "id": 3391,
  "book": 4821,
  "total_chapters": 12,
  "completed_chapters": 5,
  "current_chapter": 6,
  "status_message": "Generating chapter 6 of 12",
  "percentage": 41,
  "generation_status": "running",
  "generation_started_at": "2026-09-02T14:02:11Z",
  "generation_completed_at": null,
  "generation_time_seconds": null,
  "generation_time_formatted": null,
  "outline": [
    { "chapter_number": 1, "title": "Why Most Remote Transitions Fail", "word_count": 3012, "has_content": true },
    { "chapter_number": 6, "title": "Tooling Without Sprawl", "word_count": 0, "has_content": false }
  ],
  "progress_percentage": 41,
  "current_step": "chapter_generation",
  "created_at": "2026-09-02T13:59:20Z",
  "updated_at": "2026-09-02T14:19:47Z"
}
```

**200 OK — done**

```json
{
  "book": 4821,
  "total_chapters": 12,
  "completed_chapters": 12,
  "percentage": 100,
  "generation_status": "completed",
  "status_message": "Generation complete",
  "generation_started_at": "2026-09-02T14:02:11Z",
  "generation_completed_at": "2026-09-02T14:34:52Z",
  "generation_time_seconds": 1961,
  "generation_time_formatted": "32m 41s",
  "progress_percentage": 100,
  "current_step": "completed"
}
```

`generation_status` ∈ `running | paused | stopped | completed | error`. **Poll every 15–30 seconds.** A 36,000-word book normally completes in 15–40 minutes.

A `404` with `{"message": "No generation in progress"}` means this book has never been generated — retrying will not help.

Polling loop:

```bash
until curl -sS "$API/books/$BOOK_ID/generation-status/" -H "Authorization: Bearer $ACCESS" \
      | grep -q '"generation_status": *"completed"'; do
  sleep 30
done
```

Generation can be steered mid-flight with `POST /api/books/{id}/pause-generation/`, `.../resume-generation/` and `.../stop-generation/`.

## 7. Read the manuscript

```bash
curl -sS "$API/books/$BOOK_ID/" -H "Authorization: Bearer $ACCESS"
```

Returns the book with every chapter body in `chapters[].content`, plus `word_count` (the real summed total), `cover_url`, and the `progress` object.

To fix a single chapter without regenerating the book:

```bash
curl -sS -X POST "$API/chapters/90311/regenerate/" \
  -H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' -d '{}'
```

To save hand edits (`actual_word_count` is recomputed server-side, so whatever you send for it is ignored):

```bash
curl -sS -X PATCH "$API/chapters/90311/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{"content":"<p>Revised chapter text…</p>"}'
```

## 8. Generate a cover (optional)

```bash
curl -sS -X POST "$API/books/$BOOK_ID/generate-cover/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{"prompt":"minimalist geometric cover, muted teal and sand, sans-serif title"}'
```

**200 OK**

```json
{
  "variant_1": {"image_url": "https://…/covers/4821-a.png", "prompt": "…"},
  "variant_2": {"image_url": "https://…/covers/4821-b.png", "prompt": "…"}
}
```

Promote one with `POST /api/books/{id}/select-cover/`. The wrap is laid out for the book's `trim_size`.

## 9. Export print-ready files from KDPBot

```bash
# PDF — print-ready interior
curl -sS -X POST "$API/books/$BOOK_ID/export_pdf/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' \
  -d '{"settings":{"pageSize":"6x9"}}' \
  -o remote-work.pdf

# DOCX
curl -sS -X POST "$API/books/$BOOK_ID/export_docx/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' -d '{}' \
  -o remote-work.docx

# EPUB
curl -sS -X POST "$API/books/$BOOK_ID/export_epub/" \
  -H "Authorization: Bearer $ACCESS" \
  -H 'Content-Type: application/json' -d '{}' \
  -o remote-work.epub
```

> **These three paths use underscores** (`export_pdf`, not `export-pdf`). A fourth, `POST /api/books/{id}/preview_pdf/`, returns a preview PDF.

The response body is raw file bytes with `Content-Disposition: attachment` — do not JSON-parse it. Always pass `-o`.

On the Free plan, exported PDFs carry a watermark and DOCX/EPUB return `402`:

```json
{
  "error": {
    "code": "PLAN_UPGRADE_REQUIRED",
    "message": "DOCX export is not available on the Free plan.",
    "status": 402,
    "details": { "allowed_formats": ["pdf"], "requested_format": "docx" },
    "documentation_url": "https://kdpbot.com/docs/errors.md"
  }
}
```

## More KDPBot AI documentation

- [Authentication](https://kdpbot.com/docs/authentication.md) — token lifetimes and the refresh flow
- [Errors](https://kdpbot.com/docs/errors.md) — the error envelope and every error code
- [Rate limits](https://kdpbot.com/docs/rate-limits.md) — `RateLimit-*` headers and backoff
- [API reference](https://kdpbot.com/docs/api.md) — every endpoint group
- [Agent instructions](https://kdpbot.com/agents.md) — when to use KDPBot, decision table, failure policy
- [MCP server](https://kdpbot.com/docs/mcp.md) — `npx -y kdpbot mcp`: the same pipeline as native tools for Claude Desktop, Claude Code and any MCP client
- [Versioning and deprecation policy](https://kdpbot.com/docs/versioning.md) — what is guaranteed to stay stable inside v1
- [KDPBot OpenAPI specification — JSON](https://kdpbot.com/openapi.json) / [YAML](https://kdpbot.com/openapi.yaml) — machine-readable source of truth
- [llms.txt](https://kdpbot.com/llms.txt) — short agent guidance file
- [KDPBot developer portal](https://kdpbot.com/developers/) · [API catalog](https://kdpbot.com/.well-known/api-catalog) — every developer resource from one URL
- [Pricing and plan limits](https://kdpbot.com/pricing) · [Credits](https://kdpbot.com/credits)

Stuck? support@kdpbot.com · [Telegram](https://t.me/blabla_ecommerce) · [WhatsApp](https://wa.me/380994019521) · [https://kdpbot.com/contacts](https://kdpbot.com/contacts)
