pitch2pdf CLI
Convert presentations to PDF from your terminal. Scriptable, pipeable, and designed for AI agents.
Install
npx pitch2pdf-cli https://pitch.com/v/your-deckOr install globally:
npm install -g pitch2pdf-cliUsage
pitch2pdf <url> [options]
Options:
--email <email> Email for protected presentations
--password <password> Password for protected presentations
-o, --output <path> Output file path (use - for stdout)
--json Output NDJSON events to stdout
--no-progress Suppress progress output
--api-url <url> Custom API URL
-V, --version Show version
-h, --help Show helpExamples
Convert a Pitch presentation:
pitch2pdf https://pitch.com/v/my-deckDocSend with email authentication:
pitch2pdf https://docsend.com/view/abc --email you@company.comSave to a specific file:
pitch2pdf https://docs.google.com/presentation/d/1abc/pub -o slides.pdfPipe to another command:
pitch2pdf https://canva.com/design/abc/token/view -o - | wc -cJSON output for scripting:
pitch2pdf https://pitch.com/v/deck --json
# Each line is a JSON object:
# {"status":"processing","stage":"loading","jobId":"abc123"}
# {"status":"processing","stage":"capturing","currentSlide":1,"totalSlides":10}
# {"status":"completed","jobId":"abc123","numSlides":10,...}
# {"event":"saved","path":"deck.pdf","size":2451623}Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error (invalid URL, server error) |
| 2 | Network error |
| 3 | Authentication required or failed |
| 4 | Bot detection blocked the request |
| 5 | Timeout |
| 6 | Connection dropped during conversion |
| 7 | PDF download failed |
| 130 | Interrupted (Ctrl+C) |
Error Code Reference
Every failed conversion carries a code field — in --json output it's {"status":"failed","code":"...","message":"..."}, and it also determines the exit code above. This table covers what each one means, which services most commonly trigger it, and what to do about it.
| Code | Exit | Meaning | Common on | What to do |
|---|---|---|---|---|
UNSUPPORTED_SERVICE | 1 | The URL points to something pitch2pdf doesn't convert. | Prezi Video/Design links, Pitch Data Rooms, Canva templates, DocSend links that forward off-site | Use a supported URL format for that service, or find the actual presentation/document link. |
AUTH_REQUIRED | 3 | The presentation or document needs credentials pitch2pdf doesn't have. | Google Slides/Docs/Sheets/Drive not shared as "Anyone with the link", private Canva designs, gated DocSend/Pitch/Presentations.AI links, private or password-protected Figma Slides decks | Pass --email/--password if the deck supports gated access, or ask the owner to share it publicly. |
AUTH_FAILED | 3 | Credentials were supplied but rejected. | DocSend, Pitch | Double-check the email/password, and confirm you're using the address the owner actually granted access to. |
NAVIGATION_FAILED | 1 | The presentation viewer didn't load as expected. | Any service, occasionally — usually a transient viewer hiccup | Retry. If it persists on the same link, report it. |
DECK_NOT_FOUND | 1 | The link points to a presentation that was deleted, expired, or mistyped. | Pitch, DocSend | Confirm the link opens in a regular browser and ask the sender for a fresh one. |
BOT_BLOCKED | 4 | The service temporarily blocked automated access to this link. | DocSend, Canva, Prezi | pitch2pdf retries once automatically. If it keeps happening, wait a while and try again. |
BLANK_SLIDES | 1 | Every captured page came back blank. | Google Docs/Drive right after a sharing-settings change, occasional DocSend rendering hiccups | Retry — most are transient rendering issues on the source service. |
CAPTURE_FAILED | 1 | Too many pages in a row failed to render within the time available. | Very large decks, especially Canva | Retry. Extremely large presentations may need to be split into smaller ones. |
TIMEOUT | 5 | The conversion exceeded the maximum time limit (15 minutes). | Very large presentations (100+ slides), long Prezi decks | Retry, or split an unusually large deck into smaller ones. |
BROWSER_CRASHED | 1 | Rendering crashed unexpectedly mid-conversion. | Any service, rarely | Retry — this is almost always transient. |
DOWNLOAD_FAILED | 7 | The underlying file couldn't be downloaded. | Direct PDF links, Google Drive/Sheets exports | Confirm the link serves the file directly (not a landing page) and is under the size/page limits. |
DOWNLOAD_DISABLED | 1 | The file owner disabled downloads and the file couldn't be captured another way either. | Google Drive | Ask the owner to enable "Viewers can download", or share it as a Slides/Docs link. |
FILE_NOT_FOUND | 1 | The linked file or document doesn't exist. | Google Drive/Sheets, direct PDF links | Confirm the file still exists and the link is correct and complete. |
NETWORK_ERROR | 2 | The CLI couldn't reach the API at all. | — | Check your internet connection and --api-url (or PITCH2PDF_API_URL). |
HTTP_ERROR | 1 | The server returned an error not covered by a more specific code above. | — | Check the message field for details; retry if it looks transient. |
INVALID_RESPONSE | 1 | The server responded, but not in the expected streaming format. | — | Usually transient — retry. |
NO_BODY | 1 | The server accepted the request but returned no data. | — | Usually transient — retry. |
STREAM_DROPPED | 6 | The connection to the server was lost before a job could be identified. | — | Retry the conversion. |
STREAM_RECOVERY_TIMEOUT | 6 | The connection dropped mid-conversion and automatic recovery timed out. | — | The conversion may still finish server-side for very large decks; retry after a few minutes. |
Environment Variables
| Variable | Description |
|---|---|
PITCH2PDF_API_URL | Override the default API URL |
PITCH2PDF_EMAIL | Email for protected presentations (avoids passing via CLI arg) |
PITCH2PDF_PASSWORD | Password for protected presentations (avoids exposure in process list) |
Free Tier
The CLI uses the free tier: first 10 slides at full resolution, remaining slides as preview thumbnails. For full deck with OCR-powered searchable text, upgrade at pitch2pdf.com.
Pay from an agent
An AI agent can buy the full deck without a person or a checkout page. Take the jobId from the --json output and call POST https://api.pitch2pdf.com/api/jobs/<jobId>/generate-paid; unpaid, the API answers 402 Payment Required with a payment challenge in the headers (x402 for USDC on Base, or Stripe's Machine Payments Protocol for a card via a Link agent wallet or USDC on Tempo). The agent pays the challenge — $3 per deck, the same as the one-time unlock — and retries the same request with the credential to receive the searchable PDF.
curl -N -X POST https://api.pitch2pdf.com/api/jobs/<jobId>/generate-paid \
-H 'Content-Type: application/json' -d '{"size":"medium"}' \
-H 'Authorization: Payment <credential>' # or PAYMENT-SIGNATURE: … for x402--pay is coming to the CLI; until then use the HTTP flow. The full contract, both rails, error codes and refunds are on the agents page.