add_chapter
ChatGPTAdd a chapter to a project. If text is given, it is split into lines.
add_line
ChatGPTAdd a single line to a chapter (appended unless position is given).
add_lines
ChatGPTBatch-add many NEW lines to a chapter in a single request (text + optional per-line voice settings / QA status). FREE (no credits). Appended in list order unless an item gives an explicit position. Items apply independently -- the response reports per-item success/failure and the new line ids. Prefer this over calling add_line repeatedly. To split a blob of text into lines automatically instead, use add_chapter(text=...) or create_project(text=...).
check_credits
ChatGPTCheck the caller's balance and whether required credits are affordable.
create_audiobook
ChatGPTOne-call shortcut: create a project, set its voice, estimate the render cost, and -- if affordable and confirm_spend is true -- start generation. Returns the project_id, the estimate, and a generation job_ref to poll with get_job (then get_job_result). For a DOCUMENT import the project is built asynchronously, so this returns the creation job_ref to poll first, after which you call generate_audio(project_id). Composes the low-level tools (create_project, set_project_voice, estimate_project_generation, generate_audio); use those for finer control. BILLABLE when confirm_spend=true.
create_project
ChatGPTCreate a new audiobook project. Three creation modes are supported -- provide exactly ONE source: 1. Document import: provide filename + file_base64. Supported formats: PDF, DOC, DOCX, EPUB, XLSX, TXT. 2. Raw text: provide text. 3. Empty project: provide only name (a first chapter is created to fill in). Provide only one of: text, file_base64 (+ filename), or neither. Document options (web parity; ignored for text/empty): chapter_style "None" | "Heading 1" | "Heading 2" | "Title" include_chapter_title keep the heading text as the chapter title normalization "0" Basic (free) | "2" AI-Enhanced (1 credit/char) enable_translation + source_language/target_language (AI-Enhanced = Arabic-only) line_split_mode "sentences" | "newline" | "custom" (+ line_split_custom) start_page/end_page PDF only: convert just that page range; OCR is billed per page, so a range only pays for the pages selected. BILLABLE for documents: a document runs the async pipeline (OCR for scanned PDFs, normalization, translation, chapter detection) and returns a job_ref -- poll get_job(job_ref). Credits are charged ONLY for OCR / AI-normalization / translation; raw-text and empty projects are free. Use estimate_book_cost to preview a document's cost first.
delete_chapter
ChatGPTSoft-delete a chapter. Requires confirm=true. Mirrors the web: needs delete permission and refuses to remove a project's last active chapter.
delete_line
ChatGPTSoft-delete a single line. Requires confirmation=true. Locked lines cannot be deleted (matching the web). The line is hidden but recoverable in the DB.
delete_project
ChatGPTDelete a project (soft delete). Requires confirm=true.
download_result
ChatGPTDeprecated alias for get_job_result. Returns an artifact URL, not bytes.
estimate_book_cost
ChatGPTCredits for a whole PDF book 'as imported' (OCR + optional normalize/ translate + full TTS). char_count is approximated from pages if omitted.
estimate_edits
ChatGPTCredits to (re)render only the edited/added lines of a project.
estimate_project_generation
ChatGPTCredits to render a project. scope='all' or 'dirty' (changed lines only).
estimate_text_to_speech
ChatGPTCredits to synthesize a piece of text with an optional specific voice.
generate_audio
ChatGPTRender TTS audio for a whole project or one chapter. Provide exactly one of project_id or chapter_id. mode='missing' renders only lines without audio yet (use after edits); mode='all' regenerates everything. BILLABLE: this starts a credit-consuming job. Bills exactly like the web app (resolved voice settings + per-character rate + premium-voice fee) and checks the balance first. Call estimate_project_generation beforehand to preview the cost. Returns a job_ref to poll with get_job; fails clearly if no voice is set.
generate_lines
ChatGPTRender audio for one or more specific lines, by line id. Use this for "generate line X" or a handful of lines; use generate_audio for whole chapters/projects. Runs in the background (TTS is too slow to block on) and returns a job_ref -- poll get_job(job_ref) until is_terminal, then the rendered line ids are in the result. BILLABLE: resolves each line's voice cascade and bills like the web app. A no-voice / insufficient-credits problem surfaces as a failed job with a clear message; estimate_edits previews the cost.
get_balance
ChatGPTReturn the caller's current credit balance.
get_chapter
ChatGPTGet one chapter with its lines (text, QA status, per-line voice, audio state). Bounded to a single chapter (<=200 lines) so the payload is safe. Use after get_project shows you the chapter list, to read line-level content.
get_chapter_audio
ChatGPTGet the merged audio file for a whole chapter (the single stitched MP3). Returns the public Spaces URL of the chapter's current merged version, or has_audio=false if it hasn't been rendered/merged yet. Produce it with generate_audio(chapter_id=...) (poll the job); this just fetches the result.
get_job
ChatGPTPoll a long-running job by its job_ref. is_terminal=true when finished; status is one of pending/processing/completed/failed/cancelled.
get_job_result
ChatGPTGet a finished job's output as a public URL (audio / transcript / file). This does NOT download bytes -- it returns the URL to fetch. Poll get_job until is_terminal, then call this for the artifact.
get_line_audio
ChatGPTGet the rendered audio URL(s) for one or more lines, by line id. Returns each line's current audio version: audio_url, the voice it was rendered with, and the version id. Lines not yet rendered come back with has_audio=false. Use this after generate_lines finishes (its result lists the rendered_lines), or for any already-rendered line.
get_project
ChatGPTProject overview: metadata + a per-chapter summary (line counts and char totals) WITHOUT line text, so it stays small even on multi-million-character books. To read the actual lines of a chapter, call get_chapter(chapter_id).
get_qa_results
ChatGPTRead AI word-level QA results for a chapter (produced by run_ai_qa). Returns the QA run status and, per line that has issues, the suggested corrected text and the list of pending issues; plus totals so you know if review is still needed. status='none' means run_ai_qa hasn't been run yet.
list_projects
ChatGPTList the caller's audiobook projects (most recent first). Page with offset; the result includes total and has_more for large accounts.
list_voices
ChatGPTList voices available to the caller (owned, team, or free public). Page with offset; the result includes total and has_more.
merge_chapters_audio
ChatGPTMerge rendered chapters' audio into ONE MP3 (book order) and return a public URL. FREE -- pure audio concatenation, no TTS. Same feature as the web's Merge button. Chapters without rendered audio are skipped; needs at least 2 with audio. Use for the final audiobook file or combining an intro with its first chapter.
merge_chapters_subtitle
ChatGPTMerge chapters' word-level subtitles into ONE SRT or VTT file with continuous timestamps (book order) and return a public URL. FREE. Same feature as the web's subtitle merge. Requires rendered chapters (word alignment is produced during generation). Pairs with merge_chapters_audio to deliver a single audiobook file + matching subtitles.
play_audio
ChatGPTShow an inline audio PLAYER for Moknah audio (MCP Apps widget). Pass a Moknah audio_url (or a finished job_ref) and this renders the ui://moknah/audio-player widget -- a real play button in hosts that support MCP Apps (e.g., ChatGPT). Hosts without MCP Apps get the audio_url in the result instead. SECURITY: only audio hosted on Moknah (moknah.io / *.moknah.io) is allowed; any other URL is refused, so the player can never be pointed at an external or untrusted source.
play_line
ChatGPTClosure test: return a line's rendered audio as an MCP audio content block (base64) plus the URL as text. Open the raw tools/call result in MCP Inspector to confirm the audio block is delivered; if it is but Claude shows no player, that's Claude's renderer, not the server. (One short line only.)
play_voice_sample
ChatGPTShow an inline audio PLAYER for a voice's sample clip so the user can hear it before choosing. Returns structuredContent (title, subtitle, audio_url) and links the ui://moknah/audio-player widget, so hosts that support MCP Apps (e.g. ChatGPT) render a real play button in chat. The audio_url is the voice's public sample URL. NOTE: Claude Desktop/claude.ai don't render MCP Apps yet (upstream) -- they get the audio_url as text. Errors if the voice has no sample or isn't available to the caller.
rename_chapter
ChatGPTRename a chapter (does not touch its lines or audio).
reorder_chapters
ChatGPTReorder a project's chapters to match the given list of chapter ids.
reorder_lines
ChatGPTReorder a chapter's lines to match the given list of line ids.
run_ai_qa
ChatGPTRun AI word-level quality checking over a chapter (async job). BILLABLE: the AI QA pass consumes credits. Returns a job_ref -- poll with get_job, then read findings with get_qa_results.
set_line_qa_status
ChatGPTSet a line's QA status (1=NotStarted ... 6=Finalized).
set_line_voice_settings
ChatGPTOverride voice settings for one line (voice_id, temperature, similarity, speed, expressiveness, emotions_mode, prerecording). Null = inherit.
set_project_voice
ChatGPTSet the default voice for a whole project.
text_to_speech
ChatGPTGenerate speech from raw text -- no project needed. Available on EVERY plan, including free tier (Audio Studio itself is a Pro feature). BILLABLE when confirm_spend=true (per character + premium-voice fee). The default confirm_spend=false call is FREE and returns only the estimate -- show it to the user and get their OK first. With confirm_spend=true the render runs in the BACKGROUND (TTS is too slow to block on) and returns a job_ref: poll get_job(job_ref) until is_terminal, then get_job_result(job_ref) for the public audio_url.
transcribe_audio
ChatGPTTranscribe an audio file to text (speech-to-text). Provide the audio as base64; filename gives the type (mp3/wav/m4a/aac/ogg). BILLABLE: bills stt_api per minute, estimated from the audio's real duration, and refuses if credits are short. Runs in the background and returns a job_ref -- poll get_job(job_ref) until is_terminal; download_result then returns the transcript file's public URL.
update_line
ChatGPTEdit a line's text. Marks the line unconverted so it re-renders.
update_lines
ChatGPTBatch-edit many lines in a single request: text, voice settings, and/or QA status per line. FREE (no credits). Items are applied independently -- the response reports per-item success/failure, so one bad line does not abort the rest. Prefer this over calling update_line/set_line_voice_settings repeatedly.