{"openapi":"3.1.0","info":{"title":"pitch2pdf API","version":"1.0.0","description":"Convert a public presentation link (Pitch, DocSend, Google Slides, Google Drive, Google Docs, Google Sheets, Canva, Prezi, Presentations.AI, Figma Slides, or a direct PDF URL) to PDF. The first 10 slides are free; the full deck with an OCR text layer costs $3.00 and can be bought over HTTP 402 with a Stripe Shared Payment Token, USDC on Base (x402) or USDC on Tempo. See https://www.pitch2pdf.com/agents."},"servers":[{"url":"https://api.pitch2pdf.com"}],"x-service-info":{"name":"pitch2pdf","categories":["documents","pdf","presentations"],"docs":{"homepage":"https://www.pitch2pdf.com/agents","llms":"https://www.pitch2pdf.com/llms.txt","apiReference":"https://api.pitch2pdf.com/openapi.json"}},"paths":{"/api/convert":{"post":{"operationId":"convert","summary":"Start a conversion and stream its progress","description":"Captures the deck and streams Server-Sent Events: `progress` events during capture, then one `complete` event with `{ jobId, numSlides, serviceName, downloadUrl, warnings?, isDuplicate? }` (the free preview PDF, first 10 slides) or one `error` event with `{ error, code }`. Rate-limited per IP; at most 5 concurrent conversions per IP.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Public link to the presentation."},"email":{"type":"string","format":"email","description":"Email for a deck whose viewer asks for one (DocSend, Pitch)."},"password":{"type":"string","description":"Password for a password-protected deck."},"notify":{"type":"boolean","description":"Send one completion or failure email to `notifyEmail` (or `email`)."},"notifyEmail":{"type":"string","format":"email","description":"Notification address; never sent to the deck."},"force":{"type":"boolean","description":"Skip the 7-day cache and capture the deck fresh."}},"required":["url"]}}}},"responses":{"200":{"description":"SSE stream of `progress` events ending in `complete` or `error`.","content":{"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Missing or invalid `url`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit or concurrency cap reached; retry after `Retry-After`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}}}}},"/api/jobs/{jobId}/results":{"get":{"operationId":"getJobResults","summary":"Read a job: free PDF, slide count, entitlement, and which purchase paths are open","parameters":[{"name":"jobId","in":"path","required":true,"description":"The `jobId` from the `complete` event of POST /api/convert.","schema":{"type":"string","pattern":"^job_\\d+_[a-z0-9]+$","example":"job_1757500000000_a1b2c3d4e5"}}],"responses":{"200":{"description":"Job state.","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"},"url":{"type":"string"},"status":{"type":"string","enum":["pending","processing","completed","failed"]},"serviceName":{"type":"string"},"totalSlides":{"type":"integer"},"freeSlideCount":{"type":"integer"},"freeUrl":{"type":"string","format":"uri","description":"Signed URL of the free preview PDF."},"planType":{"type":"string","enum":["free","one_time","subscription"]},"paidAvailable":{"type":"boolean","description":"True once the job is paid for."},"paidUrls":{"$ref":"#/components/schemas/PaidUrls"},"warnings":{"type":"array","items":{"type":"string"}},"regionalPricingAvailable":{"type":"boolean"},"agentPaymentsAvailable":{"type":"boolean","description":"True when POST generate-paid answers 402 with a payable challenge; false means it answers 403 and only the hosted checkout can unlock the deck."}}}}}},"404":{"description":"Unknown or expired job.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}}}}},"/api/jobs/{jobId}/paid-urls":{"get":{"operationId":"getPaidUrls","summary":"Signed download URLs of paid PDFs already built for this job","parameters":[{"name":"jobId","in":"path","required":true,"description":"The `jobId` from the `complete` event of POST /api/convert.","schema":{"type":"string","pattern":"^job_\\d+_[a-z0-9]+$","example":"job_1757500000000_a1b2c3d4e5"}}],"responses":{"200":{"description":"Paid PDF URLs by size (an empty object until one has been generated).","content":{"application/json":{"schema":{"type":"object","properties":{"jobId":{"type":"string"},"paidUrls":{"$ref":"#/components/schemas/PaidUrls"},"planType":{"type":"string","enum":["free","one_time","subscription"]}}}}}},"403":{"description":"The job is not paid for.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Unknown or expired job.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}}}}},"/api/jobs/{jobId}/generate-paid":{"post":{"operationId":"generatePaidPdf","summary":"Buy and build the full deck PDF with an OCR text layer","description":"Unpaid job: answers 402 with an MPP challenge (`WWW-Authenticate: Payment …`) and, when the x402 rail is configured, a `PAYMENT-REQUIRED` header. Retry the same request with the credential (`Authorization: Payment …` for MPP, `PAYMENT-SIGNATURE` for x402); the payment is verified and settled before the PDF is built, and the response carries `Payment-Receipt` (plus `PAYMENT-RESPONSE` on the x402 wire). Paid job: streams SSE progress (`starting`, `ocr`, `building`, `uploading`) ending in a `complete` event with `{ downloadUrl, size, actualSize }`, or answers plain JSON `{ downloadUrl, size, cached: true }` when that size was already built. The purchase covers every size and a free re-capture of the same deck for 7 days.","parameters":[{"name":"jobId","in":"path","required":true,"description":"The `jobId` from the `complete` event of POST /api/convert.","schema":{"type":"string","pattern":"^job_\\d+_[a-z0-9]+$","example":"job_1757500000000_a1b2c3d4e5"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"size":{"type":"string","enum":["small","medium","large"],"default":"medium"}},"required":["size"]},"example":{"size":"medium"}}}},"x-payment-info":{"offers":[{"method":"stripe","intent":"charge","amount":"300","currency":"usd","description":"Full deck PDF with OCR text layer"},{"method":"evm","intent":"charge","amount":"3000000","currency":"USDC","network":"eip155:8453","description":"Full deck PDF with OCR text layer"},{"method":"tempo","intent":"charge","amount":"3000000","currency":"USDC","description":"Full deck PDF with OCR text layer"}]},"responses":{"200":{"description":"Paid: SSE progress ending in `complete`, or the cached download as JSON.","content":{"text/event-stream":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"object","properties":{"downloadUrl":{"type":"string","format":"uri"},"size":{"type":"string","enum":["small","medium","large"]},"cached":{"type":"boolean","const":true}},"required":["downloadUrl","size","cached"]}}}},"402":{"description":"Payment required. Pay $3.00 with one of the offered rails and retry with the credential. `code` is `PAYMENT_INVALID` when a credential was sent but refused (wrong job, amount, or settlement failed).","headers":{"WWW-Authenticate":{"description":"MPP challenge (one per rail): `Payment id=…, realm=…, method=stripe|tempo, intent=charge, request=<base64 JSON>, opaque=<jobId>`.","schema":{"type":"string"}},"PAYMENT-REQUIRED":{"description":"x402 v2 PaymentRequired, base64 JSON: USDC on Base (eip155:8453) to the deposit address. Present only when the x402 rail is configured.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string","const":"PAYMENT_REQUIRED"},"error":{"type":"string"},"jobId":{"type":"string"},"amountUsd":{"type":"number","const":3},"rails":{"type":"array","items":{"type":"string","enum":["spt","x402","tempo"]}},"docs":{"type":"string","format":"uri","const":"https://www.pitch2pdf.com/agents"}},"required":["code","error","jobId","amountUsd","rails","docs"]}}}},"403":{"description":"Not paid, and no agent rail is configured (see `agentPaymentsAvailable` on the results endpoint).","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Unknown or expired job.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}},"410":{"description":"The captured slides are no longer available; re-run POST /api/convert with `force=true`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}},"503":{"description":"`PAYMENT_RAIL_UNAVAILABLE`: a configured rail is unreachable. Nothing was charged; retry later.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]}}}}}}}},"components":{"schemas":{"PaidUrls":{"type":"object","description":"Signed download URLs by size, present once each size has been built.","properties":{"small":{"type":"string","format":"uri"},"medium":{"type":"string","format":"uri"},"large":{"type":"string","format":"uri"}}}}}}