ForHosting KIT · Documents & PDF

PDF to EPUB chapter structure from bookmarks

A useful EPUB needs a clear reading order, but a PDF often expresses that order only through its bookmark outline.

● BetaFree · in your browser
Use it from WebAPIEmailTelegramApp soon

This capability takes an extracted PDF bookmark list and converts every top-level bookmark into one EPUB chapter entry. It preserves bookmark order and titles, assigns stable XHTML filenames, and carries over destination pages when they are available. Nested bookmarks remain section-level information and do not accidentally become standalone chapters. If the source has no top-level bookmarks, the request fails clearly instead of inventing a structure that the document never supplied.

Prepare the bookmark outline

Start with the bookmark outline reported by a PDF parser or inspection tool, not with visually prominent headings copied from page content. Supply the records in their original reading order. Each record needs a title and a numeric level, where level 1 means a top-level bookmark; a one-based destination page is optional. A level 2 or deeper record may describe a subsection, appendix entry, figure, or other nested destination. Those records are validated because malformed outline data should not pass silently, but they are not promoted to EPUB chapters. Titles are trimmed at their edges while their spelling, punctuation, capitalization, and internal spacing remain unchanged. Page values must be positive integers when supplied. This explicit representation avoids guessing from indentation or typography and makes the result repeatable across systems. It also lets a workflow separate PDF extraction from publication planning: one component reads the PDF, while this capability performs the narrow, deterministic mapping needed for the EPUB package.

Understand the generated chapter list

The output contains a chapter count and an ordered chapters array. Every chapter receives a one-based index, the normalized title of its corresponding top-level bookmark, and a stable filename such as chapter-001.xhtml. Filenames are based on position rather than title, so punctuation, duplicate titles, non-Latin text, or later slug rules cannot create collisions. When a top-level bookmark includes a destination page, the chapter also includes source_page; when no page was supplied, that optional field is omitted instead of set to null. The capability does not extract page text, split a PDF, write XHTML, or build an EPUB navigation document. Its purpose is to establish a clean intermediate structure that downstream code can use to name files, assign extracted content, create spine entries, and construct navigation links. Because nested bookmarks never become chapters, the chapter count always matches the number of level-1 records in the source outline, preserving the editorial hierarchy already present in the PDF.

Handle missing or imperfect outlines

A PDF can display pages perfectly while containing no usable bookmarks. In that case, there is no reliable top-level chapter signal, so the capability returns an invalid-input error rather than inferring chapters from page numbers, font sizes, or text patterns. That behavior is important in automated conversion: a fabricated chapter list may look plausible but attach content to the wrong title or flatten an intentional hierarchy. If the outline exists but every bookmark is nested below level 1, the same error is returned because no top-level chapter boundary can be established. Correct the upstream extraction or add a deliberate outline before retrying. Other malformed records fail with a location-specific message, including empty titles, invalid levels, and non-positive page numbers. The implementation performs one bounded pass over at most 10,000 bookmark records, uses no network service, and has no time-dependent behavior. Identical outline input therefore produces identical chapter indexes and filenames, whether it runs in a browser or through the API at $0.002 per request.

Plan an EPUB conversion

Turn an extracted PDF outline into the chapter manifest that a conversion pipeline can populate with XHTML content.

Audit document navigation

Compare the number and order of intended EPUB chapters with the PDF's existing top-level bookmarks before publishing.

Create stable chapter filenames

Assign collision-free positional XHTML names even when bookmark titles repeat or contain punctuation and non-Latin characters.

What does it cost?

The API price is $0.002 per request, and the same deterministic transformation can run in the browser.

Does this capability read the PDF file itself?

No. It accepts the bookmark outline already extracted from a PDF and converts that outline into a chapter list.

What counts as a chapter?

Each bookmark whose level is exactly 1 becomes one chapter, in the same order as the input outline.

What happens to nested bookmarks?

They are validated but are not emitted as chapters. They can be handled later as sections within their top-level chapter.

What if the PDF has no top-level bookmarks?

The request returns an invalid-input error because the capability does not invent chapter boundaries.

Are destination pages required?

No. When a page is present it becomes source_page; otherwise that optional output field is omitted.

Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.

POSThttps://api.kit.forhosting.com/pdf/to-epub-structure

Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.

curl -X POST https://api.kit.forhosting.com/pdf/to-epub-structure \
  -H "Authorization: Bearer $KIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"outline":[{"title":"Introduction","level":1,"page":1},{"title":"Background","level":2,"page":3},{"title":"Methods","level":1,"page":12}]}'
{
  "outline": [
    {
      "title": "Introduction",
      "level": 1,
      "page": 1
    },
    {
      "title": "Background",
      "level": 2,
      "page": 3
    },
    {
      "title": "Methods",
      "level": 1,
      "page": 12
    }
  ]
}
{
  "task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
  "type": "pdf.to_epub_structure",
  "status": "queued",
  "_links": {
    "result": "/tasks/tsk_…/result"
  }
}

The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.

Per request$0.002

Published price — no tokens, no invented credits. A failed task is never charged.

max_mb25
max_pages200
HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceYour balance doesn't cover the task price.
404unknown_typeThat task type doesn't exist.
429rate_limitedToo many requests. Use the webhook instead of polling.

Read the full KIT documentation →