# KDPBot AI — Agent Instructions

Extended companion to [https://kdpbot.com/llms.txt](https://kdpbot.com/llms.txt). This document is written for autonomous agents and integration code, not for humans browsing a marketing site.

- **Product:** KDPBot AI — AI book generation for Amazon KDP publishers
- **Site:** https://kdpbot.com
- **API base URL:** `https://kdpbot.com/api/v1` (recommended — same-origin, version-pinned) or `https://bookgen-backend-5zuf.onrender.com/api/v1` (the backend directly)
- **Auth:** JWT bearer — `Authorization: Bearer <access>`
- **Content type:** `application/json` on request and response, except the four export actions which return binary file bodies
- **API surface:** REST over HTTPS. There is no GraphQL endpoint, no gRPC and no WebSocket API. An official MCP server wrapping this same REST API ships in the `kdpbot` npm package — see [https://kdpbot.com/docs/mcp.md](https://kdpbot.com/docs/mcp.md)
- **Machine-readable spec:** [https://kdpbot.com/openapi.json](https://kdpbot.com/openapi.json) / [https://kdpbot.com/openapi.yaml](https://kdpbot.com/openapi.yaml)
- **Resource index:** [https://kdpbot.com/.well-known/api-catalog](https://kdpbot.com/.well-known/api-catalog) (RFC 9727 API catalog)

## Non-negotiable call conventions

1. **Trailing slashes are mandatory on every API path.** `POST /api/books` (no slash) triggers a Django `APPEND_SLASH` redirect that drops the request body. Always write `/api/books/`.
2. **Two origins serve the same API.** `https://kdpbot.com/api/v1` is the recommended base: it is same-origin with the web app, version-pinned, and reverse-proxies to the Django backend with status, body and headers unchanged. `https://bookgen-backend-5zuf.onrender.com/api/v1` reaches that backend directly. Pin one and stay on it; both are listed in the OpenAPI `servers` array.
3. **List endpoints return bare JSON arrays.** Books, chapters, plans, credit packages, add-ons and proofreading reports all come back as plain arrays — no `{count, next, previous, results}` envelope. Exactly one endpoint is paged: `GET /api/proofreading-reports/{id}/suggestions/` (20 per page, `page_size` up to 100). Do not write a pagination loop for anything else.
4. **Three export paths use underscores, not hyphens:** `export_pdf`, `export_docx`, `export_epub`, and `preview_pdf`. Every other multi-word action uses hyphens (`generate-outline`, `generation-status`, `select-cover`, …). Getting this wrong yields a 404.
5. **Generation is asynchronous.** `POST /api/books/{id}/generate/` returns `202` immediately and does the work in a background worker. Poll `GET /api/books/{id}/generation-status/`.
6. **Token-issuing endpoints nest tokens.** `/api/auth/login/`, `/api/auth/register/` and `/api/auth/google/` return `{"tokens": {"access", "refresh"}}`. The refresh endpoint `/api/auth/token/refresh/` returns flat `{"access", "refresh"}`. These are two different shapes; handle both.

## When to use KDPBot AI

| The job | Use KDPBot? | Entry point |
| --- | --- | --- |
| Write a 20k–100k word non-fiction book from a topic | Yes — this is the primary use case | `POST /api/books/` → `generate-outline` → `generate` |
| Write a novel or novella from a premise | Yes | same sequence, `genre` = `fiction`/`sci-fi`/`fantasy`/`mystery`/`romance` |
| Write a children's book with page-level art | Yes | `POST /api/books/` with the children's-book add-on active |
| Turn a human-written outline into a full manuscript | Yes | `generate-outline` → `update-outline` (overwrite) → `generate` |
| Produce a print-ready interior PDF at a KDP trim size | Yes | `POST /api/books/{id}/export_pdf/` |
| Produce DOCX or EPUB for KDP/Kindle upload | Yes (plan-gated) | `export_docx` / `export_epub` |
| Design a book cover / full wrap for a specific trim size | Yes | `POST /api/books/{id}/generate-cover/` |
| Proofread and copy-edit an existing manuscript | Yes | `POST /api/books/{id}/proofreading/` |
| Rewrite one chapter that came out badly | Yes | `POST /api/chapters/{id}/regenerate/` |
| Write a blog post, product description, ad copy, email | **No** — wrong granularity, minimum unit is a chapter | — |
| Answer a question, chat, reason, write code | **No** — KDPBot is a fixed pipeline, not a model endpoint | — |
| Generate a standalone or stock image | **No** — images are only produced in the context of a Book | — |
| Translate or reformat a document the user already has | **No** | — |
| Anything needing a sub-second response | **No** — generation is minutes-scale | — |

## End-to-end call sequence

```
 1. POST /api/auth/register/           or  POST /api/auth/login/     → tokens.access
 2. GET  /api/auth/subscriptions/book-creation-options/              → can_create, max_words
 3. POST /api/books/                                                 → book.id          (201)
 4. POST /api/books/{id}/generate-outline/                           → book with chapters[]
 5. POST /api/books/{id}/update-outline/    (optional, human edits)
 6. POST /api/books/{id}/generate/                                   → 202 + task_id
 7. GET  /api/books/{id}/generation-status/  (poll every 15–30s)     → generation_status
 8. GET  /api/books/{id}/                                            → chapters[].content
 9. POST /api/books/{id}/generate-cover/    (optional)
10. POST /api/books/{id}/export_pdf/                                 → binary PDF
```

Steps 3–7 are the load-bearing part. Steps 2, 5, 9 are optional but recommended: step 2 avoids a 402 mid-flow, step 5 is where a human gets to steer, step 9 produces the asset KDP requires alongside the interior file.

### 1. Get a token

```bash
curl -sS -X POST https://bookgen-backend-5zuf.onrender.com/api/auth/login/ \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","password":"your-password"}'
```

```json
{
  "user": { "id": 1042, "username": "you", "email": "you@example.com",
            "email_verified": true, "is_staff": false,
            "subscription": { "id": 77, "status": "active",
                              "plan": { "id": 2, "name": "Professional", "slug": "professional",
                                        "features": { "books_per_month": 30,
                                                      "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..." }
}
```

Store `tokens.access` and send it as `Authorization: Bearer <access>` on every subsequent call. It is valid for 24 hours. See [https://kdpbot.com/docs/authentication.md](https://kdpbot.com/docs/authentication.md).

### 2. Create the book

```bash
curl -sS -X POST https://bookgen-backend-5zuf.onrender.com/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"
      }'
```

Returns `201` with the full book object. Keep `id`.

`genre` accepts `fiction | non-fiction | mystery | romance | sci-fi | fantasy | biography | self-help | business | other`. `trim_size` accepts the KDP sizes `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`. `content_language` is ISO 639-1 and supports `en, es, de, fr, it, pt, ru, uk, pl, zh, ja, ko, ar, hi, nl, sv, tr, id`.

Quota is checked here but **not consumed** here. It is consumed when generation completes. Creating and deleting draft books costs nothing.

### 3. Generate the outline

```bash
curl -sS -X POST "https://bookgen-backend-5zuf.onrender.com/api/books/$BOOK_ID/generate-outline/" \
  -H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' -d '{}'
```

Synchronous; takes roughly 10–60 seconds. It **deletes all existing chapters** and writes a fresh set, so calling it twice discards edits. The response is the full book object with a populated `chapters` array and `status: "outline"`.

To substitute a human-authored structure, follow this with `POST /api/books/{id}/update-outline/` carrying a `chapters` array of `{chapter_number, title, summary}` objects.

### 4. Start generation

```bash
curl -sS -X POST "https://bookgen-backend-5zuf.onrender.com/api/books/$BOOK_ID/generate/" \
  -H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' -d '{}'
```

```json
{ "message": "Generation started", "book_id": 4821, "task_id": "b0c1…", "mode": "celery" }
```

`202 Accepted`. The book's `status` flips to `generating` immediately.

Pre-flight failures you must handle here: `402` when the monthly book quota is exhausted, `402` when `target_word_count` exceeds the plan's `max_word_count_per_book`, `400` when generation is already running for this book, `400` when the book has no chapters (you skipped step 3).

### 5. Poll to completion

```bash
curl -sS "https://bookgen-backend-5zuf.onrender.com/api/books/$BOOK_ID/generation-status/" \
  -H "Authorization: Bearer $ACCESS"
```

```json
{
  "book": 4821, "total_chapters": 12, "completed_chapters": 5, "current_chapter": 6,
  "percentage": 41, "generation_status": "running",
  "status_message": "Generating chapter 6 of 12",
  "generation_started_at": "2026-09-02T14:02:11Z",
  "generation_completed_at": null,
  "outline": [ { "chapter_number": 1, "title": "Why Remote Fails", "word_count": 3012, "has_content": true } ],
  "progress_percentage": 41, "current_step": "chapter_generation"
}
```

`generation_status` is one of `running | paused | stopped | completed | error`. Poll every **15–30 seconds**; do not poll faster. A 36,000-word book normally finishes in 15–40 minutes. Treat anything past 90 minutes with no change in `completed_chapters` as stalled and surface it to the user rather than restarting blindly.

`404` with `{"message": "No generation in progress"}` means the book has never been generated — it is not a transient error, and retrying will not fix it.

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

### 6. Read the manuscript and export

```bash
# Full book incl. every chapter body
curl -sS "https://bookgen-backend-5zuf.onrender.com/api/books/$BOOK_ID/" \
  -H "Authorization: Bearer $ACCESS"

# Print-ready interior PDF (binary body — write it to a file)
curl -sS -X POST "https://bookgen-backend-5zuf.onrender.com/api/books/$BOOK_ID/export_pdf/" \
  -H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' \
  -d '{"settings":{"pageSize":"6x9"}}' \
  -o remote-work.pdf
```

The three export actions return raw file bytes with `Content-Disposition: attachment`, not JSON. Do not JSON-parse the response. On the Free plan the exported PDF carries a watermark, and DOCX/EPUB return `402` with an `allowed_formats` list.

## Authentication

Full detail: [https://kdpbot.com/docs/authentication.md](https://kdpbot.com/docs/authentication.md).

- Header: `Authorization: Bearer <access token>`
- Access token lifetime: **24 hours**
- Refresh token lifetime: **30 days**, rotated on every refresh (`ROTATE_REFRESH_TOKENS=True`) — always persist the new `refresh` value returned by the refresh call
- Refresh: `POST /api/auth/token/refresh/` with `{"refresh": "..."}` → `{"access": "...", "refresh": "..."}` (flat, not nested)
- Registration may require email verification. When it does, `POST /api/auth/register/` returns `email_verification_required: true` and **no tokens**; the account cannot call authenticated endpoints until the emailed link is followed. An agent cannot complete this step on its own — hand it back to the human.
- There is no server-side logout. Discard tokens client-side.

Agent guidance: refresh proactively when the access token is within ~30 minutes of expiry rather than waiting for a `401`. A long generation poll loop will otherwise expire mid-flight.

## Errors

Full detail and the complete code table: [https://kdpbot.com/docs/errors.md](https://kdpbot.com/docs/errors.md).

Every error response uses this envelope:

```json
{
  "error": {
    "code": "QUOTA_EXCEEDED",
    "message": "You have used all 3 books included in your plan this period.",
    "status": 429,
    "details": { "quota_type": "books", "limit": 3, "used": 3, "remaining": 0 },
    "documentation_url": "https://kdpbot.com/docs/errors.md"
  }
}
```

Branch on `error.code` (a stable SCREAMING_SNAKE identifier). Never branch on `error.message` — it is human-facing prose and will change.

Handling policy for an autonomous agent:

| Class | Codes | Do this |
| --- | --- | --- |
| Fix the request | `VALIDATION_ERROR`, `METHOD_NOT_ALLOWED`, `NOT_FOUND` | Read `details`, correct the call. Do not retry unchanged. |
| Re-authenticate | `TOKEN_EXPIRED`, `TOKEN_INVALID`, `AUTHENTICATION_REQUIRED` | Refresh once, replay the request once. If it fails again, stop and ask the human to re-login. |
| Stop and escalate | `INVALID_CREDENTIALS`, `PERMISSION_DENIED`, `PLAN_UPGRADE_REQUIRED` | These are human decisions (wrong password, wrong account, needs a paid plan). Never retry, never attempt a workaround. |
| Wait, then retry | `RATE_LIMIT_EXCEEDED`, `QUOTA_EXCEEDED` | Honour `Retry-After`. `QUOTA_EXCEEDED` on a monthly quota does not clear within a session — treat it as escalate. |
| Retry with backoff | `UPSTREAM_AI_ERROR`, `SERVER_ERROR` | Exponential backoff, max 3 attempts. Generation endpoints are not idempotent — before retrying `generate/`, poll `generation-status/` to check whether the first call actually started. |
| Reconcile | `CONFLICT` | Something already exists or generation is already running. Poll state instead of retrying the write. |

## Rate limits

Full detail: [https://kdpbot.com/docs/rate-limits.md](https://kdpbot.com/docs/rate-limits.md).

Responses carry `RateLimit-Limit`, `RateLimit-Remaining` and `RateLimit-Reset`. On a `429` the response also carries `Retry-After` in seconds. Read the headers on every response and self-throttle before you are throttled; do not hard-code limit values. Generation, cover and export endpoints are metered far more tightly than reads — treat one book start per user per minute as the ceiling and space polls at 15–30 seconds.

## Idempotency and cost safety

- `POST /api/books/` is **not** idempotent — each call creates a new draft. Store the returned `id` before retrying anything.
- `POST /api/books/{id}/generate-outline/` destroys and recreates all chapters. Never call it as a retry of a failed network read.
- `POST /api/books/{id}/generate/` costs real quota on completion. Before retrying it after a timeout, call `generation-status/` — if `generation_status` is `running`, the first call succeeded.
- Deleting a book does not refund quota.
- Cross-user object ids return `404`, not `403`. A `404` on a book id you believe exists usually means you are holding a token for the wrong account.

## Documentation index

- [https://kdpbot.com/llms.txt](https://kdpbot.com/llms.txt) — short agent guidance file
- [https://kdpbot.com/agents.md](https://kdpbot.com/agents.md) — this document
- [https://kdpbot.com/docs/quickstart.md](https://kdpbot.com/docs/quickstart.md) — copy-pasteable first book
- [https://kdpbot.com/docs/authentication.md](https://kdpbot.com/docs/authentication.md) — JWT flow and token lifetimes
- [https://kdpbot.com/docs/errors.md](https://kdpbot.com/docs/errors.md) — error envelope and code table
- [https://kdpbot.com/docs/rate-limits.md](https://kdpbot.com/docs/rate-limits.md) — headers and backoff
- [https://kdpbot.com/docs/api.md](https://kdpbot.com/docs/api.md) — endpoint reference
- [https://kdpbot.com/docs/versioning.md](https://kdpbot.com/docs/versioning.md) — versioning and deprecation policy
- [https://kdpbot.com/docs/mcp.md](https://kdpbot.com/docs/mcp.md) — the official MCP server (`npx -y kdpbot mcp`): install, client config, all eleven tools and a worked end-to-end example
- [https://kdpbot.com/.well-known/api-catalog](https://kdpbot.com/.well-known/api-catalog) — RFC 9727 API catalog listing every machine-readable resource
- [https://kdpbot.com/openapi.json](https://kdpbot.com/openapi.json) — OpenAPI 3.1 (JSON)
- [https://kdpbot.com/openapi.yaml](https://kdpbot.com/openapi.yaml) — OpenAPI 3.1 (YAML)
- [https://kdpbot.com/developers/](https://kdpbot.com/developers/) — developer portal
- [https://kdpbot.com/pricing](https://kdpbot.com/pricing) — plans, quotas, export-format gating
- [https://kdpbot.com/credits](https://kdpbot.com/credits) — pay-as-you-go credits
- [https://kdpbot.com/terms](https://kdpbot.com/terms) · [https://kdpbot.com/privacy](https://kdpbot.com/privacy) · [https://kdpbot.com/refund](https://kdpbot.com/refund)
- [https://academy.kdpbot.com](https://academy.kdpbot.com) — KDP publishing tutorials

## Contact

- Email: support@kdpbot.com
- Telegram: https://t.me/blabla_ecommerce
- WhatsApp: +380994019521 — https://wa.me/380994019521
- Contact page: https://kdpbot.com/contacts
