Skip to main content
POST

Overview

PDF to Video extracts the text of a PDF, turns it into a narration split into scenes, reads it with a voice and puts a visual under each scene. It works like Article to Video, with a PDF instead of a web page. Sending the PDF. Send one of:
  • pdfUrl: a public https:// link to the file, up to 20 MB. Hooked downloads it itself: a private or local address (or a redirect to one), a file over 20 MB or anything that is not a PDF answers 400.
  • pdfBase64: the file itself, base64-encoded, up to 10 MB once decoded (a data:application/pdf;base64, prefix is accepted). Add pdfFileName to name the project after the file.
Not both. The PDF needs a text layer: a scanned or image-only PDF (or one with a password) answers 400 before anything is charged. Run it through OCR first. The narration. summaryType is summarize (default: a short summary, steered by customPrompt), summarize_long (a detailed narration) or key_as_is (the document as close to the original as possible; the video is as long as it needs). With the first two, targetDuration sets the length (default 30 seconds). The narration is written in the document’s own language. The visuals. mediaType as in Script to Video: ai-images (default), ai-videos, media (your own library files) or gameplay. Motion graphics are not available for this format. For gameplay only, see PDF to Brainrot.
The request answers in a few seconds with a projectId and status processing: the PDF is downloaded and its text checked in the request, and splitting it into scenes and making the video happen after that. What can be refused up front (an invalid body, a link that is not a PDF, a PDF without a text layer, missing keys, too few credits) is still answered with a 400 or 402 and nothing is created. If the scenes cannot be written later, the project becomes failed with the reason in message, the credits come back and your webhook gets the failure.

Sending the file itself

For a PDF that is not online (up to 10 MB), send it base64-encoded:

More request bodies



What happens next

  1. Keep the projectId. The project starts as processing while the text is split into scenes; if that fails it becomes failed, with the reason in message and the credits refunded.
  2. Either poll GET /v1/project/{projectId} until video.status is COMPLETED (or the project status is failed), or pass a webhook and wait for the call.
  3. Download the file from video.url (or data.url in the webhook).
The PDF itself is not kept: only its text, turned into scenes, and the pdfUrl it came from. See Webhooks for every payload.

Credits and your own keys

Teams on Hooked’s keys (managed): the project is priced from targetDuration, the media type and the quality or model. The PDF is read first, so a file that cannot be read costs nothing; then the credits are taken. If the balance is short, the request answers 402 INSUFFICIENT_CREDITS with creditsNeeded and creditsAvailable and nothing is created. If the project fails later, the credits are refunded automatically. Teams on their own keys (BYOK): no credits are charged. The team needs these keys in Settings → AI keys:
  • OpenRouter: always (summary, images, video clips, captions).
  • ElevenLabs: for the voiceover. Not needed in speaking mode (ai-videos with a talking preset), where the video model speaks.
  • Gemini: when presetSettings.aiModel is gemini_omni_flash.
No Firecrawl key: Hooked downloads and reads the PDF itself. A missing key answers 402 missing_credentials with the list in missingProviders, before anything is created.

Errors

Send an Idempotency-Key header to retry safely: if a request times out or answers 5xx, sending it again with the same key and body returns the first answer instead of creating (and charging) the project twice.

Next Steps

Get Project

Follow the project until the video is ready

PDF to Video example

More requests for this format

PDF to Brainrot

The same over gameplay

Article to Video

From a web page instead

Authorizations

x-api-key
string
header
required

Headers

Idempotency-Key
string

Makes the request safe to retry. 1-255 printable ASCII characters, one per operation (your job id, or a UUID you store), reused on every retry. Within 24 hours the same key with the same body answers with the first response and the header Idempotent-Replayed: true, without running or charging again. Keys are scoped to your team and the endpoint. 5xx answers and refusals before anything ran (401, 402, 403, 409, 429) are not kept. See Idempotency.

Required string length: 1 - 255
Pattern: ^[\x20-\x7E]+$

Body

application/json
voiceId
string
required

The narrator: a library voice from /v1/voice/list or one of your team's custom voices. An ID that is neither answers 400 (voiceId: Voice "<id>" not found.).

Required string length: 1 - 30
pdfUrl
string<uri>

A public https link to the PDF (up to 20 MB). Hooked downloads it: private or local addresses, redirects to them, files over 20 MB and anything that is not a PDF answer 400. Send this or pdfBase64, not both.

Maximum string length: 2000
pdfBase64
string

The PDF file itself, base64-encoded (up to 10 MB once decoded; a data:application/pdf;base64, prefix is accepted). For bigger files use pdfUrl. Send this or pdfUrl, not both.

pdfFileName
string

The file name, used to name the project. Taken from pdfUrl when omitted.

Maximum string length: 500
summaryType
enum<string>
default:summarize

How the text becomes the narration:

  • summarize: a short summary of the key points, about targetDuration seconds long.
  • summarize_long: a detailed narration with supporting details, about targetDuration seconds long.
  • key_as_is: the text as close to the original as possible, adapted for speech. The video is as long as the text needs; targetDuration is ignored.
Available options:
summarize,
summarize_long,
key_as_is
targetDuration
integer
default:30

Approximate length of the video in seconds (10-600). Not used with key_as_is. It also sets the price of the project.

Required range: 10 <= x <= 600
customPrompt
string

summarize only: extra instructions for the summary, e.g. the angle or the audience (max 2,000 characters). Sent with another summaryType, it answers 400.

Maximum string length: 2000
mediaType
enum<string>
default:ai-images

Where the visuals come from:

  • ai-images (default): one AI image per scene (presetSettings: preset, aiModel, characterIds, useCharacterReferenceImage).
  • ai-videos: one AI video clip per scene (presetSettings: preset, quality, aiModel, isContinuous, characterIds, characterMode, voiceProfile).
  • media: your own images and videos from the media library (media required).
  • gameplay: a gameplay clip in the background (gameplaySettings).

motion-graphics is not available for this format (400).

Available options:
ai-images,
ai-videos,
media,
gameplay
presetSettings
object

Visual settings for ai-images and ai-videos; not used by media and gameplay. Each field says which media types read it.

gameplaySettings
object

mediaType: "gameplay" only: the background clip.

media
string[]

IDs of images or videos in your team's media library (max 50). Required for mediaType: "media"; ignored for the other media types. An ID that is not in your library answers 400 (media: Media "<id>" not found), and so does a media that is not COMPLETED yet.

Maximum array length: 50

Media ID from your library

name
string

Project name (max 100 characters). Generated from the source when omitted.

Maximum string length: 100
musicId
string

Background music: a track from /v1/music/list or your team's own uploaded music. An ID that is neither answers 400 (musicId: Music "<id>" not found.).

Maximum string length: 30
aspectRatio
enum<string>
default:ratio_9_16

Vertical, horizontal or square.

Available options:
ratio_9_16,
ratio_16_9,
ratio_1_1
language
string

Two-letter ISO 639-1 code of the narration. The narration is written in the document's own language, detected when omitted; this does not translate it.

caption
object

Burned-in captions of the narration. Not used with motion-graphics (it typesets its own copy) or a speaking cast.

audio
object

Narrator voice settings (ElevenLabs). Any field you leave out keeps its default. Not used by a speaking cast.

addStickers
boolean
default:false

Add emoji/GIF stickers anchored to the captions. Not used with motion-graphics or a speaking cast.

content
object

Branding.

webhook
string<uri>

HTTPS URL on a public host, called when the video is ready or the project fails (max 500 characters). Requests are signed: verify the Hooked-Signature header (HMAC-SHA256 of ".") with the signing secret from Settings → Webhooks; Hooked-Event and Hooked-Delivery headers name the event and the delivery. No redirects are followed; 10 s timeout; 3 immediate attempts. See the Webhooks guide for the payload.

Maximum string length: 500
metadata
object

Any JSON object of your own (max 5 KB). Stored on the project and sent back in the webhook payload. The key automationId is reserved for dashboard automations and is removed.

Response

Project created. Follow it with GET /v1/project/{projectId} or wait for the webhook.

success
enum<boolean>
required
Available options:
true
data
object
required
message
string
required