---
title: "Add a chapter (or more script to a chapter not yet started)"
method: POST
path: "/api/v1/audiobooks/{bookId}/chapters"
tags: ["Public API v1"]
---

# Add a chapter (or more script to a chapter not yet started)

`POST /api/v1/audiobooks/{bookId}/chapters`

## Request

- Base URL: `https://api.vieneu.io`
- URL: `https://api.vieneu.io/api/v1/audiobooks/{bookId}/chapters`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Segments are read in order: narration by the narrator, lines by the character named in `speaker` (add new characters in `cast`). The title is read first, then a short beat; a `sceneBreak` segment gets a longer silence. Up to 60,000 characters per chapter, or `chapterCharsMax` when the plan behind this key has a tighter daily or weekly cap. A long chapter is sent in several requests with `appendTo` and `afterSegment`.

## Path parameters

- `bookId` string, required

## Request body

- AddAudiobookChapterDto
  - `title` string: Read by the narrator, then a short beat.
  - `segments` AudiobookSegmentDto[], required: The chapter in reading order.
    - `speaker` string: A character from the cast; empty or "narrator" for the narrator.
    - `text` string, required: What is read. A paragraph of narration, or one character line. Longer passages are cut at sentence ends.
    - `sceneBreak` boolean: This segment starts a new scene (a longer silence before it).
  - `cast` AudiobookCastEntryDto[]: Characters introduced in this chapter.
    - `speaker` string, required: A character name, as used in `segments[].speaker`.
    - `voiceId` string, required: Voice id from GET /v1/voices (engine of the book; not a cloned voice).
  - `appendTo` number: Append these segments to an existing chapter that has not started (by index) instead of adding a new one — for chapters too long for one request.
  - `afterSegment` number: With `appendTo`: how many segments the chapter has before these (the `segments` count of that chapter in the previous answer). A different count answers 409 `segment_mismatch` instead of adding, so a retried request cannot add its text twice and a lost one cannot leave a gap. Without it, a request repeating the chapter's last segments exactly answers 409 `duplicate_segments`.

## Response `201`

The book with the chapter added.

- AudiobookResponseDto
  - `id` string, required
  - `title` string, required
  - `author` string, nullable, required
  - `status` 'draft' | 'queued' | 'rendering' | 'completed' | 'partial' | 'failed' | 'cancelled', required
  - `narratorVoice` string, required
  - `cast` AudiobookCastEntryDto[], required
    - `speaker` string, required: A character name, as used in `segments[].speaker`.
    - `voiceId` string, required: Voice id from GET /v1/voices (engine of the book; not a cloned voice).
  - `waitingReason` string, nullable, required: gpu_busy: books render only while the GPU fleet is idle; quota: the plan hit a limit, retried automatically; queue_full.
  - `error` string, nullable, required
  - `totals` AudiobookTotalsDto, required
    - `chapters` number, required
    - `completedChapters` number, required
    - `characters` number, required
    - `estimatedTokens` number, required: Tokens the chapters not yet rendered will cost.
    - `tokensCharged` number, required
    - `durationSeconds` number, required
  - `otherBooksWaiting` number, nullable, required: While started: how many other books are waiting too. Books take turns, a chapter each.
  - `chapterCharsMax` number, required: The longest chapter (in characters) the plan behind this key can render: a chapter is billed in one go, so it must fit the plan's daily or weekly token cap. 60,000 when the plan has no tighter cap.
  - `chapters` AudiobookChapterResponseDto[], required
    - `index` number, required
    - `title` string, required
    - `status` 'pending' | 'rendering' | 'rendered' | 'mastering' | 'completed' | 'failed' | 'cancelled', required
    - `characters` number, required
    - `segments` number, required
    - `tokenCost` number, nullable, required
    - `progress` AudiobookChapterProgressDto, required
      - `done` number, required
      - `total` number, nullable, required
    - `durationSeconds` number, nullable, required
    - `audioUrl` string, nullable, required: Presigned link (24 h) once completed.
    - `audioFormat` string, nullable, required: mp3 (wav only if mastering failed).
    - `error` string, nullable, required
  - `createdAt` string, date-time, required
  - `completedAt` string, date-time, nullable, required

## Other responses

- `400`: A speaker without a voice, limits exceeded, or a chapter longer than the plan can render (`chapter_over_plan_limit`).
- `401`: API key missing, malformed, or revoked.
- `409`: Not added: the chapter has started, `afterSegment` does not match (`segment_mismatch`), or the request repeats what was just added (`duplicate_segments`, `duplicate_chapter`) — a retried request.

## Changes

- **2026-10-10** `8e42136d02f3`: 3 info
  - added the new optional request property `afterSegment`
  - added the non-success response with the status `409`
  - added the required property `chapterCharsMax` to the response with the `201` status
- **2026-10-01** `17d7990f256f`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/vieneu/apis/vieneu-api/changes/api/v1/audiobooks/:bookId/chapters/post.md)

---

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