PodPDF - Transform Your Content into Professional PDFs

PodPDF Documentation & Product Guide

Transform Your Content into Professional PDFs

PodPDF is a powerful PDF generation platform that converts HTML, Markdown, and images into high-quality PDFs in seconds. Use our intuitive web application for instant conversions, or integrate our API into your applications for automated PDF generation.

We operate globally using cloud infrastructure. Built on Amazon Web Services (AWS) with worldwide availability, PodPDF serves customers in all countries with industry-leading reliability and scale.


🎯 Two Ways to Use PodPDF

Web Application (No Coding Required)

Perfect for business users, designers, and anyone who needs to convert documents to PDF without technical knowledge.

Access: Log in at https://app.podpdf.com and use the Convert page

Features: - ✅ Visual drag-and-drop interface - ✅ Upload HTML, Markdown, or image files - ✅ Real-time preview - ✅ Instant download - ✅ No programming knowledge needed - ✅ Perfect for one-off conversions

Ideal for: - Creating invoices and receipts manually - Converting documents for personal use - Testing layouts and formatting - Non-technical team members - Quick ad-hoc PDF generation

API (For Developers)

Perfect for developers who need to integrate PDF generation into applications, automate workflows, or process documents at scale.

Access: Create API keys in Settings and integrate into your application

Features: - ✅ RESTful API with comprehensive documentation - ✅ Support for multiple programming languages - ✅ Webhook notifications for long jobs - ✅ Batch processing capabilities - ✅ Automated PDF generation - ✅ Full programmatic control

Ideal for: - Automated invoice/receipt generation - Bulk document processing - Integration into web/mobile apps - Workflow automation - SaaS product features - High-volume PDF generation

Both methods use the same infrastructure and count toward your quota, so you can mix and match based on your needs!


🚀 Why Choose PodPDF?

Key Benefits

  • ⚡ Fast & Reliable - Generate PDFs in under 30 seconds using our web app or API
  • 🌍 Global Availability - We operate globally using cloud infrastructure, serving customers worldwide
  • 📈 99.9% Uptime SLA - Guaranteed availability for paid plans with SLA credits
  • đŸ–„ïž Two Ways to Use - Interactive web application for manual conversions OR powerful API for automation
  • 🎹 Flexible Input - Support for HTML, Markdown, and images (PNG/JPEG)
  • 🎯 Precise Control - Customize page size, margins, orientation, scaling, and more
  • 💰 Cost-Effective - Start free with 100 PDFs, then pay only $0.01 per PDF with credit-based billing
  • 🔒 Secure - Built on AWS with Cognito authentication and API key support
  • 📊 Full Visibility - Monitor all jobs through our dashboard with webhook notifications
  • 🌐 No Infrastructure - Fully serverless, no servers to manage
  • đŸ‘€ User-Friendly - No coding required when using the web application

Common Use Cases

For Non-Technical Users (Web Application): - Quick Document Conversion - Convert HTML, Markdown files, or images to PDF instantly - Manual Invoice Creation - Create one-off invoices and receipts using the visual editor - Document Formatting - Style and format documents before converting to PDF - Photo Albums - Upload and arrange photos into beautiful PDF albums - Content Archiving - Save web content as PDFs for personal records

For Developers (API Integration): - Automated Invoice Generation - Generate invoices programmatically from your app - Report Creation - Automatically convert analytics data and reports into PDFs - Bulk Processing - Convert large batches of documents to PDF - Receipt & Ticket Generation - Create printable tickets and receipts on demand - Marketing Automation - Generate personalized PDFs from templates at scale - Workflow Integration - Add PDF generation to your existing business processes


💎 Pricing & Plans

Free Tier

Perfect for testing and small projects

  • 100 PDFs - Lifetime quota (one-time, non-renewable, cumulative)
  • 20 requests/minute - Rate limit
  • $0/PDF - Completely free
  • Full API Access - All features included (subject to conversion type restrictions)
  • Dashboard Access - Monitor jobs and usage
  • 1 Webhook - Maximum webhook configuration
  • Upgrade Path - Purchase credits to automatically upgrade to paid plan

For production applications and high-volume needs

  • Unlimited PDFs - No quota limit (subject to credit balance)
  • Unlimited Requests - No rate limiting
  • $0.01/PDF - Just one cent per PDF (credit-based billing)
  • Credit System - Purchase credits upfront, deducted per PDF
  • Automatic Upgrade - Free tier users automatically upgraded when purchasing credits
  • Full API Access - All features included (subject to conversion type restrictions)
  • 99.9% Uptime SLA - Guaranteed availability with SLA credits
  • Priority Support - Get help when you need it
  • 5 Webhooks - Multiple webhook configurations with event subscriptions
  • Webhook Delivery History - Permanent retention of delivery records

Plan Comparison

Feature Free Tier Paid Standard
Quota 100 PDFs (lifetime) Unlimited (credit-based)
Rate Limit 20 req/min Unlimited
Price per PDF $0 $0.01
Billing Model Free Credit-based (purchase upfront)
Upgrade Purchase credits to upgrade Automatic when purchasing credits
Uptime SLA Best-effort 99.9% guaranteed
HTML to PDF ✅ (if enabled) ✅ (if enabled)
Markdown to PDF ✅ (if enabled) ✅ (if enabled)
Images to PDF ✅ (if enabled) ✅ (if enabled)
Conversion Types Plan-dependent Plan-dependent
Custom Styling ✅ ✅
API Keys ✅ ✅
Dashboard ✅ ✅
Webhooks 1 webhook 5 webhooks (default)
Webhook Events ✅ ✅ (event subscriptions)
Job History ✅ ✅

Credit Purchase & Billing

How It Works: - Free Tier: Start with 100 free PDFs. Once exhausted, purchase credits to continue. - Automatic Upgrade: When you purchase credits for the first time, your account automatically upgrades to the paid plan ($0.01 per PDF). - Credit-Based Billing: Paid plans use a credit system - purchase credits upfront, and they’re deducted after each PDF generation. - Credit Balance: You must have sufficient credits (or free credits) to generate PDFs. Requests are rejected if balance is insufficient. - Transaction History: All credit purchases and deductions are logged for audit purposes.

Purchasing Credits: - Credits can be purchased at any time through your account dashboard - Credits are added to your balance immediately upon successful payment - Credits do not expire (unless otherwise specified) - Unused credits remain in your account until consumed

Important Notes: - Plan upgrade is permanent - you cannot revert to free tier after upgrading - Credits are forfeited upon account deletion - Credit purchase automatically clears quota exceeded flags - Free credits (if included in your plan) are consumed before purchased credits


🎯 Features & Capabilities

Input Formats

1. HTML to PDF

Convert any HTML content into PDFs with full CSS support.

Features: - Complete HTML5 and CSS3 support - Custom fonts and web fonts - Background graphics and colors - Responsive layouts - Print media queries

Example Use Cases: - Invoices and receipts - Reports and dashboards - Email templates - Web pages for archiving

2. Markdown to PDF

Transform Markdown documents into professional PDFs.

Features: - GitHub-flavored Markdown - Tables, lists, and code blocks - Automatic styling - Syntax highlighting - Headings and formatting

Example Use Cases: - Technical documentation - Blog posts - README files - Meeting notes and reports

3. Images to PDF

Combine multiple images into organized PDF documents.

Features: - PNG and JPEG support - Multiple images per PDF - Fit modes: contain, cover, fill - Custom page sizes - Configurable margins

Example Use Cases: - Photo albums - Scanned documents - Image catalogs - Product sheets

Conversion Type Restrictions

Plan-Based Restrictions: - Plans may have restrictions on which conversion types are enabled - Enabled Conversion Types: Plans may specify which input types are allowed: - html - HTML to PDF conversion - markdown - Markdown to PDF conversion - image - Image to PDF conversion - If your plan has enabled_conversion_types configured, only those types are allowed - If your plan does not specify restrictions, all types are enabled (backward compatible) - Requests for disabled conversion types will be rejected with 403 CONVERSION_TYPE_NOT_ENABLED error - Check your plan details via GET /plans or GET /accounts/me to see which conversion types are enabled

Customization Options

Page Settings

  • Formats: A4, Letter, Legal, Tabloid, A3, A5
  • Orientation: Portrait or Landscape
  • Margins: Customizable (top, right, bottom, left)
  • Scale: 0.5x to 2.0x zoom control

Advanced Options

  • Print Background: Include/exclude background graphics
  • Fit Mode (Images): Control how images fit on pages
  • Page Limits: Up to 100 pages per document (production)

Output Features

  • High-quality PDF output
  • Configurable page size and orientation
  • Searchable text (HTML/Markdown)
  • Embedded fonts and images

🏁 Getting Started

Step 1: Sign Up

  1. Visit the PodPDF dashboard at https://app.podpdf.com
  2. Sign up with your email
  3. Confirm your email address
  4. Start generating PDFs immediately

Step 2: Choose Your Method

Option A: Web Application (No Coding Required)

Perfect for: Non-technical users, one-off conversions, quick testing

  1. Log in to the dashboard
  2. Navigate to Convert page
  3. Choose your input method:
    • HTML - Write or paste HTML code directly
    • Markdown - Write or paste Markdown content
    • File Upload - Upload .html or .md files
    • Images - Upload and arrange multiple images
  4. Configure PDF options (page size, margins, orientation)
  5. Click Generate PDF and download instantly

No API key needed! Your login session handles everything.

Option B: API Integration (For Developers)

Perfect for: Automated workflows, bulk processing, app integration

  1. Log in to the dashboard
  2. Navigate to Settings → API Keys
  3. Click Create New API Key
  4. Give it a name (e.g., “Production”, “Development”)
  5. Copy and securely store your API key
  6. Use it in your API requests

Step 3: Make Your First Request (API Users)

Quick Example: HTML to PDF

bash curl -X POST https://api.podpdf.com/quickjob \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "input_type": "html", "html": "<!DOCTYPE html><html><head><title>Invoice</title></head><body><h1>Invoice #1234</h1><p>Thank you for your business!</p></body></html>", "options": { "format": "A4", "margin": { "top": "20mm", "right": "20mm", "bottom": "20mm", "left": "20mm" } } }' \ --output invoice.pdf

Quick Example: Markdown to PDF

bash curl -X POST https://api.podpdf.com/quickjob \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "input_type": "markdown", "markdown": "# Monthly Report\n\n## Summary\n\nThis is a **bold** statement.\n\n| Metric | Value |\n|--------|-------|\n| Sales | $1,000 |\n| Costs | $500 |", "options": { "format": "A4", "margin": { "top": "20mm", "right": "20mm", "bottom": "20mm", "left": "20mm" } } }' \ --output report.pdf

Quick Example: Images to PDF

bash curl -X POST https://api.podpdf.com/quickjob \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "input_type=image" \ -F "images=@photo1.jpg" \ -F "images=@photo2.jpg" \ -F 'options={"format":"A4","fit":"contain","margin":{"top":"10mm","right":"10mm","bottom":"10mm","left":"10mm"}}' \ --output photos.pdf


📚 API Reference

Note: This section is for developers integrating PodPDF into their applications. If you’re looking to convert documents manually, use our web application instead - no coding required!

Base URL

https://api.podpdf.com

Authentication

All API requests require authentication using one of these methods:

Method 1: API Key (Recommended for programmatic access) http Authorization: Bearer YOUR_API_KEY or http X-API-Key: YOUR_API_KEY

Method 2: JWT Token (For web dashboard) http Authorization: Bearer YOUR_JWT_TOKEN

Available Endpoints

1. POST /quickjob

Synchronous PDF generation - Returns PDF immediately (completes in <30 seconds)

Request: json { "input_type": "html|markdown|image", "html": "string (required if input_type=html)", "markdown": "string (required if input_type=markdown)", "options": { "format": "A4|Letter|Legal|Tabloid|A3|A5", "margin": { "top": "20mm", "right": "20mm", "bottom": "20mm", "left": "20mm" }, "printBackground": true, "scale": 1.0, "landscape": false } }

Response: - Binary PDF file - Headers include: X-PDF-Pages, X-Job-Id, X-PDF-Truncated

Limits: - Content size: ≀ 5 MB - Image size: ≀ 5 MB per image, 10 MB total - Image dimensions: ≀ 10,000 x 10,000 pixels - Page limit: 100 pages (production environment)

2. POST /longjob

Asynchronous PDF generation - For larger documents (>30 seconds)

Request: json { "input_type": "html|markdown|image", "html": "string", "options": { ... }, "webhook_url": "https://your-domain.com/webhook (optional)" }

Response: json { "job": { "job_id": "uuid", "status": "queued", "created_at": "2024-01-15T10:30:00Z" } }

Webhook Notification: When job completes, receives POST with: json { "job_id": "uuid", "status": "completed|failed", "s3_url": "https://...", "pages": 42, "completed_at": "2024-01-15T10:30:45Z" }

3. GET /jobs

List all jobs - Paginated job history

Query Parameters: - limit: Number of results (default: 20, max: 100) - offset: Pagination offset - status: Filter by status (queued, processing, completed, failed)

Response: json { "jobs": [...], "count": 150, "limit": 20, "offset": 0 }

4. GET /jobs/{job_id}

Get job details - Retrieve specific job information

Response: json { "job": { "job_id": "uuid", "user_id": "uuid", "status": "completed", "job_type": "quick|long", "input_type": "html|markdown|image", "pages": 42, "s3_url": "https://...", "s3_url_expires_at": "2024-01-15T11:30:00Z", "created_at": "2024-01-15T10:30:00Z", "completed_at": "2024-01-15T10:30:45Z" } }

5. GET /accounts/me

Get account information - View your account details and usage

Response: json { "account": { "user_id": "uuid", "email": "user@example.com", "account_status": "free|paid", "plan_id": "free-basic", "total_pdf_count": 45, "quota_exceeded": false, "created_at": "2024-01-01T00:00:00Z" }, "plan": { "name": "Free Basic", "type": "free", "monthly_quota": 50, "rate_limit_per_minute": 20 } }

6. GET /plans

List available plans - View pricing options (No authentication required)

Response: json { "plans": [ { "plan_id": "free-basic", "name": "Free Basic", "type": "free", "monthly_quota": 100, "price_per_pdf": 0, "rate_limit_per_minute": 20, "enabled_conversion_types": ["html", "markdown", "image"], "max_webhooks": 1 }, { "plan_id": "paid-standard", "name": "Paid Standard", "type": "paid", "monthly_quota": null, "price_per_pdf": 0.01, "rate_limit_per_minute": null, "enabled_conversion_types": ["html", "markdown", "image"], "max_webhooks": 5 } ] }

7. POST /accounts/me/credits/purchase

Purchase credits - Add credits to your account balance (automatically upgrades free users to paid plan)

Request: json { "amount": 10.50 }

Response: json { "message": "Credits purchased successfully. Account upgraded to paid plan.", "credits_balance": 10.50, "amount_purchased": 10.50, "transaction_id": "01ARZ3NDEKTSV4RRFFQ69G5FAV", "purchased_at": "2025-12-24T15:30:00.000Z", "upgraded": true, "plan": { "plan_id": "paid-standard", "name": "Paid Standard", "type": "paid", "price_per_pdf": 0.01 } }

8. POST /accounts/me/webhooks

Create webhook - Create a new webhook configuration

Request: json { "name": "Production Webhook", "url": "https://api.example.com/webhooks/podpdf", "events": ["job.completed", "job.failed"], "is_active": true }

9. GET /accounts/me/webhooks

List webhooks - Get all webhook configurations for your account

10. GET /accounts/me/webhooks/{webhook_id}/history

Webhook delivery history - View delivery history for a specific webhook

11. GET /accounts/me/api-keys

List API keys - View all API keys (shows prefixes only, not full keys)

12. POST /accounts/me/api-keys

Create API key - Generate a new API key (full key shown only once)

Note: For complete API documentation, see ENDPOINTS.md


đŸ’» Code Examples

JavaScript / Node.js

```javascript const fetch = require(‘node-fetch’); const fs = require(‘fs’);

async function generatePDF() { const response = await fetch(‘https://api.podpdf.com/quickjob’, { method: ‘POST’, headers: { ‘Authorization’: Bearer ${process.env.PODPDF_API_KEY}, ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ input_type: ‘html’, html: ` <!DOCTYPE html> <html> <head> Invoice </head> <body> <div class="header"> <h1>Invoice #1234</h1> </div> <div class="content"> <p>Date: ${new Date().toLocaleDateString()}</p> <p>Amount: $500.00</p> </div> </body> </html> `, options: { format: ‘A4’, margin: { top: ‘20mm’, right: ‘20mm’, bottom: ‘20mm’, left: ‘20mm’ }, printBackground: true } }) });

if (response.ok) { const buffer = await response.buffer(); fs.writeFileSync(‘invoice.pdf’, buffer); console.log(‘PDF generated successfully!’); console.log(‘Pages:’, response.headers.get(‘X-PDF-Pages’)); console.log(‘Job ID:’, response.headers.get(‘X-Job-Id’)); } else { const error = await response.json(); console.error(‘Error:’, error); } }

generatePDF(); ```

Python

```python import requests import os

def generate_pdf(): api_key = os.environ.get(‘PODPDF_API_KEY’)

response = requests.post(
    'https://api.podpdf.com/quickjob',
    headers={
        'Authorization': f'Bearer {api_key}',
        'Content-Type': 'application/json'
    },
    json={
        'input_type': 'html',
        'html': '''
            <!DOCTYPE html>
            <html>
              <head><title>Report</title></head>
              <body>
                <h1>Monthly Report</h1>
                <p>Generated on: {}</p>
              </body>
            </html>
        '''.format(datetime.now().strftime('%Y-%m-%d')),
        'options': {
            'format': 'A4',
            'margin': {
                'top': '20mm',
                'right': '20mm',
                'bottom': '20mm',
                'left': '20mm'
            }
        }
    }
)

if response.status_code == 200:
    with open('report.pdf', 'wb') as f:
        f.write(response.content)
    print('PDF generated successfully!')
    print(f"Pages: {response.headers.get('X-PDF-Pages')}")
    print(f"Job ID: {response.headers.get('X-Job-Id')}")
else:
    print(f"Error: {response.json()}")

generate_pdf() ```

PHP

```php <?php

function generatePDF() { $apiKey = getenv(‘PODPDF_API_KEY’);

$data = [
    'input_type' => 'html',
    'html' => '<!DOCTYPE html><html><head><title>Invoice</title></head><body><h1>Invoice #1234</h1></body></html>',
    'options' => [
        'format' => 'A4',
        'margin' => [
            'top' => '20mm',
            'right' => '20mm',
            'bottom' => '20mm',
            'left' => '20mm'
        ]
    ]
];

$ch = curl_init('https://api.podpdf.com/quickjob');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Bearer ' . $apiKey,
    'Content-Type: application/json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

if ($httpCode == 200) {
    file_put_contents('invoice.pdf', $response);
    echo "PDF generated successfully!\n";
} else {
    echo "Error: " . $response . "\n";
}

curl_close($ch); }

generatePDF(); ?> ```

Ruby

```ruby require ‘net/http’ require ‘json’ require ‘uri’

def generate_pdf api_key = ENV[‘PODPDF_API_KEY’] uri = URI(‘https://api.podpdf.com/quickjob’)

request = Net::HTTP::Post.new(uri) request[‘Authorization’] = “Bearer #{api_key}” request[‘Content-Type’] = ‘application/json’ request.body = { input_type: ‘html’, html: ‘<!DOCTYPE html><html><head>Invoice</head><body><h1>Invoice #1234</h1></body></html>’, options: { format: ‘A4’, margin: { top: ‘20mm’, right: ‘20mm’, bottom: ‘20mm’, left: ‘20mm’ } } }.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end

if response.code == ‘200’ File.write(‘invoice.pdf’, response.body) puts ‘PDF generated successfully!’ puts “Pages: #{response[‘X-PDF-Pages’]}” puts “Job ID: #{response[‘X-Job-Id’]}” else puts “Error: #{response.body}” end end

generate_pdf ```


🎹 Advanced Examples

Styled Invoice with CSS

```javascript const invoiceHTML = ` <!DOCTYPE html>

Invoice

INVOICE

Invoice #INV-2024-001

Bill To:

Acme Corporation

123 Business St

New York, NY 10001

Invoice Date:

January 15, 2024

Due Date:

February 15, 2024

Description Quantity Price Total
Web Development Services 40 hours $150.00 $6,000.00
Design Consultation 10 hours $100.00 $1,000.00
Hosting & Maintenance 1 month $500.00 $500.00
Total Due: $7,500.00

`;

// Generate the PDF const response = await fetch(‘https://api.podpdf.com/quickjob’, { method: ‘POST’, headers: { ‘Authorization’: Bearer ${process.env.PODPDF_API_KEY}, ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ input_type: ‘html’, html: invoiceHTML, options: { format: ‘A4’, margin: { top: ‘15mm’, right: ‘15mm’, bottom: ‘15mm’, left: ‘15mm’ }, printBackground: true, scale: 1.0 } }) }); ```

Markdown Technical Documentation

```javascript const markdownDoc = ` # API Integration Guide

Overview

This guide will help you integrate our API into your application in less than 10 minutes.

Prerequisites

Before you begin, ensure you have:

  • An active account
  • An API key (available in dashboard)
  • Basic knowledge of REST APIs

Quick Start

Step 1: Install Dependencies

```bash npm install axios ```

Step 2: Set Up Authentication

```javascript const axios = require(‘axios’);

const client = axios.create({ baseURL: ‘https://api.example.com’, headers: { ‘Authorization’: ‘Bearer YOUR_API_KEY’ } }); ```

Step 3: Make Your First Request

```javascript async function getData() { const response = await client.get(‘/data’); console.log(response.data); } ```

API Endpoints

Endpoint Method Description
/users GET List all users
/users/:id GET Get user details
/users POST Create new user
/users/:id PUT Update user
/users/:id DELETE Delete user

Error Handling

The API returns standard HTTP status codes:

  • 200 OK - Request succeeded
  • 400 Bad Request - Invalid input
  • 401 Unauthorized - Missing or invalid auth
  • 404 Not Found - Resource not found
  • 500 Server Error - Internal error

Best Practices

  1. Cache responses when possible to reduce API calls
  2. Handle errors gracefully with proper retry logic
  3. Use webhooks for real-time notifications
  4. Monitor usage through the dashboard

Support

Need help? Contact us at support@example.com


Last updated: January 2024 `;

// Generate the PDF const response = await fetch(‘https://api.podpdf.com/quickjob’, { method: ‘POST’, headers: { ‘Authorization’: Bearer ${process.env.PODPDF_API_KEY}, ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ input_type: ‘markdown’, markdown: markdownDoc, options: { format: ‘A4’, margin: { top: ‘20mm’, right: ‘20mm’, bottom: ‘20mm’, left: ‘20mm’ } } }) }); ```


🔔 Webhook Integration

Multiple Webhooks System

PodPDF supports multiple webhook configurations per account with event-based subscriptions. This allows you to: - Configure different webhooks for different purposes (production, staging, monitoring) - Subscribe to specific events you care about - Track delivery history and statistics - Activate/deactivate webhooks without deletion

Plan-Based Limits: - Free Tier: Maximum 1 webhook configuration - Paid Standard: Maximum 5 webhook configurations (default) - Enterprise Plans: Up to 50 webhook configurations

Setting Up Webhooks

Create Webhook via API

```javascript // Create a new webhook const response = await fetch(‘https://api.podpdf.com/accounts/me/webhooks’, { method: ‘POST’, headers: { ‘Authorization’: Bearer ${process.env.PODPDF_API_KEY}, ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ name: ‘Production Webhook’, url: ‘https://api.example.com/webhooks/podpdf’, events: [‘job.completed’, ‘job.failed’], is_active: true }) });

const webhook = await response.json(); console.log(‘Webhook created:’, webhook.webhook_id); ```

Configure Webhook via Dashboard

  1. Navigate to Settings → Webhooks
  2. Click Create New Webhook
  3. Enter webhook name and URL (must be HTTPS)
  4. Select event types to subscribe to
  5. Click Save

Webhook Event Types

You can subscribe to the following event types:

  • job.completed - When a job successfully completes (default)
  • job.failed - When a job fails during processing
  • job.timeout - When a quick job exceeds 30-second timeout
  • job.queued - When a long job is queued
  • job.processing - When a long job starts processing

Example: Subscribe only to failures for monitoring: json { "name": "Error Monitoring", "url": "https://api.example.com/alerts", "events": ["job.failed", "job.timeout"], "is_active": true }

Webhook Payload Examples

job.completed Event

json { "event": "job.completed", "job_id": "9f0a4b78-2c0c-4d14-9b8b-123456789abc", "status": "completed", "job_type": "long", "mode": "html", "pages": 150, "truncated": false, "s3_url": "https://s3.amazonaws.com/podpdf-dev-pdfs/...", "s3_url_expires_at": "2025-12-21T11:32:15Z", "created_at": "2025-12-21T10:30:00Z", "completed_at": "2025-12-21T10:32:15Z", "timestamp": "2025-12-21T10:32:15Z" }

job.failed Event

json { "event": "job.failed", "job_id": "9f0a4b78-2c0c-4d14-9b8b-123456789abc", "status": "failed", "job_type": "long", "mode": "html", "error_message": "PDF generation failed: Chromium process crashed", "created_at": "2025-12-21T10:30:00Z", "failed_at": "2025-12-21T10:32:15Z", "timestamp": "2025-12-21T10:32:15Z" }

Webhook Headers

All webhook requests include standard headers:

http Content-Type: application/json User-Agent: PodPDF-Webhook/1.0 X-Webhook-Event: job.completed X-Webhook-Id: 01ARZ3NDEKTSV4RRFFQ69G5FAV X-Webhook-Delivery-Id: 01ARZ3NDEKTSV4RRFFQ69G5FAY X-Webhook-Timestamp: 2025-12-21T10:32:15Z

Important: Use X-Webhook-Delivery-Id for idempotency - deduplicate duplicate deliveries.

Webhook Delivery & Retry Logic

Retry Behavior: - 3 retries with exponential backoff (1s, 2s, 4s) - Retries on: network errors, timeouts (10 seconds), HTTP 5xx errors, HTTP 429 - Does NOT retry on: HTTP 2xx (success), HTTP 4xx client errors (except 429)

Delivery Guarantees: - At-least-once delivery: Webhooks may be delivered multiple times - Best-effort delivery: Failed webhooks are retried, but delivery is not guaranteed if all retries fail - Ordering: Webhooks are delivered in order, but order is not guaranteed across different webhooks

Webhook Delivery History: - All delivery attempts are permanently logged - View delivery history via GET /accounts/me/webhooks/{webhook_id}/history - History includes: delivery status, HTTP status codes, retry counts, timestamps, duration, payload sizes

Webhook Handler Example

```javascript const express = require(‘express’); const app = express();

app.use(express.json());

// Store processed delivery IDs for idempotency const processedDeliveries = new Set();

app.post(‘/webhook’, async (req, res) => { // Get delivery ID from headers for idempotency const deliveryId = req.headers[‘x-webhook-delivery-id’]; const eventType = req.headers[‘x-webhook-event’]; const webhookId = req.headers[‘x-webhook-id’];

// Idempotency check - skip if already processed if (processedDeliveries.has(deliveryId)) { console.log(Duplicate delivery ${deliveryId}, skipping); return res.status(200).send(‘OK’); }

const { event, job_id, status, s3_url, pages, error_message } = req.body;

try { // Handle different event types switch (event) { case ‘job.completed’: console.log(Job ${job_id} completed with ${pages} pages);

    // Download the PDF
    const pdfResponse = await fetch(s3_url);
    const pdfBuffer = await pdfResponse.buffer();
    
    // Process or store the PDF
    // ... your logic here ...
    
    break;
    
  case 'job.failed':
    console.error(`Job ${job_id} failed: ${error_message}`);
    // Send alert, log error, etc.
    break;
    
  case 'job.timeout':
    console.warn(`Job ${job_id} timed out`);
    // Handle timeout
    break;
    
  case 'job.queued':
    console.log(`Job ${job_id} queued`);
    break;
    
  case 'job.processing':
    console.log(`Job ${job_id} started processing`);
    break;
}

// Mark as processed
processedDeliveries.add(deliveryId);

// Return 200 quickly - process asynchronously if needed
res.status(200).send('OK');   } catch (error) {
console.error('Webhook processing error:', error);
// Still return 200 to prevent retries for processing errors
res.status(200).send('OK');   } });

app.listen(3000, () => { console.log(‘Webhook server listening on port 3000’); }); ```


📊 Dashboard & Web Application

Web Dashboard

Access your dashboard at https://app.podpdf.com

Perfect for non-technical users! You can convert documents to PDF entirely through the web interface without writing any code.

Available Pages

  1. Dashboard - Overview of account and usage statistics
  2. Convert - Interactive PDF generation tool (No coding required!)
  3. Jobs - Complete job history with filtering and search
  4. Settings - Account management and API keys

Convert Page (Interactive Web Application)

Generate PDFs directly in your browser without any coding!

How to Use:

  1. Choose Input Type:
    • HTML Tab - Write or paste HTML code directly in the editor
    • Markdown Tab - Write or paste Markdown content
    • File Upload Tab - Upload .html, .htm, .md, or .markdown files
    • Images Tab - Drag & drop or upload multiple PNG/JPEG images
  2. Configure Options:
    • Select page format (A4, Letter, Legal, etc.)
    • Choose orientation (Portrait or Landscape)
    • Set custom margins
    • Adjust scaling and other advanced options
  3. Generate & Download:
    • Click the Generate PDF button
    • Preview your PDF in the browser
    • Download the PDF file to your computer
    • View job details and history

Features:

  • No Coding Required - User-friendly visual interface
  • Real-time Preview - See your PDF before downloading
  • Example Templates - Load sample content to get started
  • Drag & Drop - Easy file and image uploads
  • Live Job Tracking - Monitor generation progress
  • Instant Download - Get your PDF in seconds
  • Options Panel - Full control over PDF settings
  • Image Reordering - Arrange images by dragging
  • Persistent Settings - Your preferences are saved

Perfect for: - Creating invoices manually - Converting documents one at a time - Testing layouts before API integration - Non-technical team members - Quick ad-hoc PDF generation

Jobs Page

Monitor all your PDF generation jobs:

  • Real-time Status - Track queued, processing, completed, and failed jobs
  • Job Details - View pages, creation time, completion time
  • Download PDFs - Direct download links for completed jobs
  • Filter & Search - Find jobs by status, type, or date
  • Pagination - Browse through job history

Settings Page

Manage your account:

  • Account Info - View user details and plan information
  • API Keys - Create, view, and revoke API keys (with names and usage tracking)
  • Webhooks Management - Create and manage multiple webhook configurations
    • Configure webhook URLs, names, and event subscriptions
    • View webhook delivery history and statistics
    • Activate/deactivate webhooks
    • Plan-based limits (1 for free, 5 for paid)
  • Credit Management - Purchase credits, view balance, and transaction history
  • Usage Statistics - Track quota, PDF generation count, and credit balance
  • Plan Information - View current plan and enabled conversion types

⚠ Error Handling

Common Error Codes

Code Status Description Solution
UNAUTHORIZED 401 Invalid or missing authentication Check your API key or JWT token
ACCOUNT_NOT_FOUND 403 User account doesn’t exist Sign up for an account
QUOTA_EXCEEDED 403 Free tier limit reached (100 PDFs) Purchase credits to upgrade
INSUFFICIENT_CREDITS 403 Insufficient credit balance Purchase credits to continue
CONVERSION_TYPE_NOT_ENABLED 403 Requested conversion type not enabled for plan Check plan details or upgrade
RATE_LIMIT_EXCEEDED 403 Too many requests Wait before retrying or upgrade
WEBHOOK_LIMIT_EXCEEDED 403 Maximum webhooks reached for plan Upgrade plan or delete unused webhooks
INVALID_INPUT_TYPE 400 Invalid input_type value Use ‘html’, ‘markdown’, or ‘image’
MISSING_CONTENT_FIELD 400 Missing required content Include html, markdown, or images
CONTENT_TOO_LARGE 400 Content exceeds size limit Reduce content size (max 5 MB)
PAGE_LIMIT_EXCEEDED 400 PDF exceeds page limit Reduce content (max 100 pages)
PDF_GENERATION_FAILED 500 PDF generation error Check content format and try again
IMAGE_TOO_LARGE 400 Image file too large Reduce image size (max 5 MB each)
INVALID_IMAGE_FORMAT 400 Unsupported image format Use PNG or JPEG only
INVALID_WEBHOOK_URL 400 Invalid webhook URL Use valid HTTPS URL
INVALID_EVENTS 400 Invalid webhook event types Use valid event types

Error Response Format

json { "error": { "code": "QUOTA_EXCEEDED", "message": "You have reached your quota limit of 100 PDFs. Please purchase credits to continue.", "details": { "current_usage": 100, "quota_limit": 100, "action_required": "purchase_credits" } } }

Example: Insufficient Credits Error json { "error": { "code": "INSUFFICIENT_CREDITS", "message": "Insufficient credits. Current balance: $0.05, required: $0.01 per PDF.", "details": { "credits_balance": 0.05, "price_per_pdf": 0.01, "action_required": "purchase_credits" } } }

Example: Conversion Type Not Enabled Error json { "error": { "code": "CONVERSION_TYPE_NOT_ENABLED", "message": "Conversion type 'markdown' is not enabled for your plan.", "details": { "requested_type": "markdown", "enabled_types": ["html"], "plan_id": "free-basic", "action_required": "upgrade_plan" } } }

Retry Logic Example

```javascript async function generatePDFWithRetry(data, maxRetries = 3) { for (let attempt = 1; attempt <= maxRetries; attempt++) { try { const response = await fetch(‘https://api.podpdf.com/quickjob’, { method: ‘POST’, headers: { ‘Authorization’: Bearer ${process.env.PODPDF_API_KEY}, ‘Content-Type’: ‘application/json’ }, body: JSON.stringify(data) });

  if (response.ok) {
    return await response.buffer();
  }

  const error = await response.json();
  
  // Don't retry on client errors (4xx)
  if (response.status >= 400 && response.status < 500) {
    throw new Error(`Client error: ${error.error.message}`);
  }

  // Retry on server errors (5xx)
  if (attempt < maxRetries) {
    const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
    await new Promise(resolve => setTimeout(resolve, delay));
    continue;
  }

  throw new Error(`Server error after ${maxRetries} attempts`);
} catch (err) {
  if (attempt === maxRetries) throw err;
}   } } ```

🔒 Security Best Practices

API Key Security

  1. Never commit API keys to version control
  2. Use environment variables to store keys
  3. Rotate keys regularly for production systems
  4. Use separate keys for development and production
  5. Revoke unused keys immediately

Example: Using Environment Variables

bash # .env file (never commit this!) PODPDF_API_KEY=pk_live_your_secret_key_here

javascript // Load from environment require('dotenv').config(); const apiKey = process.env.PODPDF_API_KEY;

Content Validation

Always validate and sanitize user input before generating PDFs:

```javascript function sanitizeHTML(html) { // Remove potentially dangerous scripts const sanitized = html .replace(/<script\b[^<](?:(?!<\/script>)<[^<])<\/script>/gi, ‘’) .replace(/on\w+=”[^”]“/gi, ‘’);

return sanitized; }

const safeHTML = sanitizeHTML(userProvidedHTML); ```


📈 Performance Optimization

Best Practices

  1. Use Quick Jobs for documents that generate in <30 seconds
  2. Use Long Jobs for larger documents with webhooks
  3. Optimize HTML/CSS - Reduce unnecessary styling and scripts
  4. Compress images before converting to PDF
  5. Cache generated PDFs when possible to avoid regeneration
  6. Use appropriate page limits - Don’t generate unnecessarily large PDFs
  7. Batch operations when generating multiple PDFs

Image Optimization

```javascript // Before uploading images, compress them const sharp = require(‘sharp’);

async function compressImage(inputPath, outputPath) { await sharp(inputPath) .resize(1920, 1920, { fit: ‘inside’, withoutEnlargement: true }) .jpeg({ quality: 85 }) .toFile(outputPath); } ```

Caching Strategy

```javascript const crypto = require(‘crypto’);

// Generate hash of content to use as cache key function getCacheKey(html, options) { const content = JSON.stringify({ html, options }); return crypto.createHash(‘md5’).update(content).digest(‘hex’); }

// Check cache before generating async function getCachedOrGenerate(html, options) { const cacheKey = getCacheKey(html, options);

// Check if PDF exists in your cache/storage const cached = await getFromCache(cacheKey); if (cached) return cached;

// Generate new PDF const pdf = await generatePDF(html, options);

// Store in cache await saveToCache(cacheKey, pdf);

return pdf; } ```


🆘 Support & Resources

Getting Help

We serve customers worldwide and provide support in English.

  • Documentation: https://podpdf.com/docs
  • Dashboard: https://app.podpdf.com
  • Email Support: podpdf@gmail.com
  • Status Page: https://status.podpdf.com
  • Global Service: Available to customers in all countries

Response Times

  • Free Tier: Best-effort support, no guaranteed response time
  • Paid Standard: Priority support with target response times:
    • Critical issues (service down): 4 business hours
    • High priority: 1 business day
    • Normal priority: 2 business days
    • Low priority: 5 business days
  • API Reference: https://podpdf.com/docs
  • Changelog: https://podpdf.com/changelog
  • Community Forum: https://community.podpdf.com
  • GitHub Examples: https://github.com/podpdf/examples

📋 Limits & Quotas Summary

Resource Free Tier Paid Standard
PDF Quota 100 (lifetime) Unlimited (credit-based)
Billing Model Free Credit-based ($0.01/PDF)
Rate Limit 20 requests/min Unlimited
Content Size 5 MB 5 MB
Image Size 5 MB per image 5 MB per image
Total Upload 10 MB 10 MB
Image Dimensions 10,000 x 10,000 px 10,000 x 10,000 px
Page Limit 100 pages 100 pages
Job History 90 days 365 days
API Keys Unlimited Unlimited
Webhooks 1 webhook 5 webhooks (default)
Webhook Events Event subscriptions Event subscriptions
Conversion Types Plan-dependent Plan-dependent
Uptime SLA Best-effort 99.9% guaranteed
Support Email (best-effort) Priority Email

🚩 Getting Started Checklist

For All Users:

  • [ ] Sign up for a PodPDF account
  • [ ] Confirm your email address
  • [ ] Explore the dashboard
  • [ ] Monitor usage and quota

Web Application Users:

  • [ ] Navigate to the Convert page
  • [ ] Try converting an HTML, Markdown, or image file
  • [ ] Experiment with different PDF options
  • [ ] Download your first PDF
  • [ ] Check job history in the Jobs page

API Integration Users:

  • [ ] Generate your first PDF in the web app (optional, for testing)
  • [ ] Create an API key in Settings
  • [ ] Test the API with one of our code examples
  • [ ] Set up webhook notifications (optional)
  • [ ] Integrate into your application
  • [ ] Implement error handling and retry logic

When Ready:

  • [ ] Purchase credits to automatically upgrade to paid plan
  • [ ] Set up production API keys
  • [ ] Configure multiple webhooks with event subscriptions
  • [ ] Set up monitoring and alerts

📜 Terms & Compliance

Fair Use Policy

  • API is for legitimate PDF generation purposes
  • No abuse, spam, or illegal content
  • Rate limits are enforced to ensure service quality
  • We reserve the right to suspend accounts violating terms

Data & Privacy

  • Your content is processed securely on AWS infrastructure
  • Generated PDFs are stored temporarily (1 hour only)
  • Input content is processed in memory and not stored persistently
  • We do not read or analyze your content
  • GDPR and CCPA compliant
  • Webhook delivery history is permanently retained for audit purposes
  • Credit transaction records are retained for accounting compliance

SLA (Service Level Agreement)

Paid Standard Plan: - 99.9% uptime guarantee (calculated monthly) - SLA credits as free PDFs if uptime commitment is not met: - 10% of monthly PDFs if uptime < 99.9% but ≄ 99.0% - 25% of monthly PDFs if uptime < 99.0% but ≄ 95.0% - 50% of monthly PDFs if uptime < 95.0% - Credits provided as free PDF generation quota (valid for 12 months) - Automatic failover and redundancy via AWS infrastructure - Real-time status monitoring - Excludes scheduled maintenance (48-hour notice) and force majeure events

Free Tier: - Best-effort service without uptime guarantees - Not eligible for SLA credits


🎉 Ready to Get Started?

Start generating professional PDFs today!

For Everyone:

  1. Sign Up - Create your free account (no credit card required)
  2. Try the Web App - Convert your first PDF in the browser
  3. View Pricing - Choose the right plan for you

For Developers:

  1. Create API Keys - Get your API credentials
  2. Read API Docs - Explore the full API reference
  3. View Examples - Check out code samples

Which Option Is Right for You?

Use the Web Application if you: - Want to convert documents manually - Don’t need automation - Prefer a visual interface - Need to generate PDFs occasionally - Are a non-technical user

Use the API if you: - Need automated PDF generation - Want to integrate into your app - Process documents in bulk - Need webhook notifications - Are building a product or service

Need Help?

Contact us at podpdf@gmail.com or visit our Help Center

Customers worldwide may use the Service - we serve users in all countries with our global cloud infrastructure.


© 2024 PodPDF. All rights reserved.

← Back