File Storage

Store, retrieve, and manage generated PDF files.

File Storage

Store generated PDFs for later retrieval. Files are securely stored and can be accessed, downloaded, or deleted via the API.


Enable Storage on PDF Generation

To store a generated PDF, add the storage option to any PDF generation request:

{
  "markdown": "# My Document",
  "storage": {
    "enabled": true,
    "filename": "my-document.pdf"
  }
}

When storage is enabled, the response includes file information in headers:

X-File-ID: f47ac10b-58cc-4372-a567-0e02b2c3d479
X-File-URL: https://api.pdfapi.dev/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479

List Files

Retrieve a list of all stored files for your account.

GET /v1/files

Query Parameters

ParameterTypeDefaultDescription
pageinteger1Page number for pagination
limitinteger20Items per page (max 100)
sortstring"created_at"Sort field (created_at, filename, size)
orderstring"desc"Sort order (asc, desc)

Code Examples

curl https://api.pdfapi.dev/v1/files \
  -H "Authorization: Bearer sk_live_xxx"
const response = await fetch('https://api.pdfapi.dev/v1/files?limit=50', {
  headers: {
    'Authorization': `Bearer ${process.env.PDFAPI_KEY}`,
  },
});

const { data, pagination } = await response.json();
console.log(`Found ${pagination.total} files`);
data.forEach(file => {
  console.log(`${file.filename} - ${file.size} bytes`);
});
import requests
import os

response = requests.get(
    'https://api.pdfapi.dev/v1/files',
    headers={'Authorization': f'Bearer {os.environ["PDFAPI_KEY"]}'},
    params={'limit': 50, 'sort': 'created_at', 'order': 'desc'}
)

data = response.json()
for file in data['data']:
    print(f"{file['filename']} - {file['size']} bytes - {file['created_at']}")

Response

{
  "data": [
    {
      "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
      "filename": "invoice-2025-001.pdf",
      "size": 125430,
      "content_type": "application/pdf",
      "created_at": "2025-01-20T10:30:00Z",
      "expires_at": "2025-02-20T10:30:00Z",
      "download_url": "https://api.pdfapi.dev/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479/download"
    },
    {
      "id": "a1b2c3d4-5678-9012-3456-789012345678",
      "filename": "report-q4.pdf",
      "size": 2456789,
      "content_type": "application/pdf",
      "created_at": "2025-01-19T15:45:00Z",
      "expires_at": "2025-02-19T15:45:00Z",
      "download_url": "https://api.pdfapi.dev/v1/files/a1b2c3d4-5678-9012-3456-789012345678/download"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 45,
    "total_pages": 3
  }
}

Get File Details

Retrieve details for a specific stored file.

GET /v1/files/:id

Path Parameters

ParameterTypeDescription
idstringFile UUID

Code Examples

curl https://api.pdfapi.dev/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
  -H "Authorization: Bearer sk_live_xxx"
const fileId = 'f47ac10b-58cc-4372-a567-0e02b2c3d479';
const response = await fetch(`https://api.pdfapi.dev/v1/files/${fileId}`, {
  headers: {
    'Authorization': `Bearer ${process.env.PDFAPI_KEY}`,
  },
});

const { data } = await response.json();
console.log(`File: ${data.filename}`);
console.log(`Size: ${data.size} bytes`);
console.log(`Download: ${data.download_url}`);
import requests
import os

file_id = 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
response = requests.get(
    f'https://api.pdfapi.dev/v1/files/{file_id}',
    headers={'Authorization': f'Bearer {os.environ["PDFAPI_KEY"]}'}
)

file_info = response.json()['data']
print(f"File: {file_info['filename']}")
print(f"Expires: {file_info['expires_at']}")

Response

{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "filename": "invoice-2025-001.pdf",
    "size": 125430,
    "content_type": "application/pdf",
    "created_at": "2025-01-20T10:30:00Z",
    "expires_at": "2025-02-20T10:30:00Z",
    "download_url": "https://api.pdfapi.dev/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479/download",
    "metadata": {
      "source": "markdown",
      "theme": "corporate",
      "page_count": 3
    }
  }
}

Download File

Download a stored PDF file.

GET /v1/files/:id/download

Code Examples

curl https://api.pdfapi.dev/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479/download \
  -H "Authorization: Bearer sk_live_xxx" \
  --output downloaded.pdf
const fileId = 'f47ac10b-58cc-4372-a567-0e02b2c3d479';
const response = await fetch(`https://api.pdfapi.dev/v1/files/${fileId}/download`, {
  headers: {
    'Authorization': `Bearer ${process.env.PDFAPI_KEY}`,
  },
});

const buffer = await response.arrayBuffer();
// Save or process the PDF
import requests
import os

file_id = 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
response = requests.get(
    f'https://api.pdfapi.dev/v1/files/{file_id}/download',
    headers={'Authorization': f'Bearer {os.environ["PDFAPI_KEY"]}'}
)

with open('downloaded.pdf', 'wb') as f:
    f.write(response.content)

Response

Returns the PDF file directly:

Content-Type: application/pdf
Content-Disposition: attachment; filename="invoice-2025-001.pdf"
Content-Length: 125430

Delete File

Delete a stored file.

DELETE /v1/files/:id

Code Examples

curl -X DELETE https://api.pdfapi.dev/v1/files/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
  -H "Authorization: Bearer sk_live_xxx"
const fileId = 'f47ac10b-58cc-4372-a567-0e02b2c3d479';
const response = await fetch(`https://api.pdfapi.dev/v1/files/${fileId}`, {
  method: 'DELETE',
  headers: {
    'Authorization': `Bearer ${process.env.PDFAPI_KEY}`,
  },
});

if (response.status === 204) {
  console.log('File deleted successfully');
}
import requests
import os

file_id = 'f47ac10b-58cc-4372-a567-0e02b2c3d479'
response = requests.delete(
    f'https://api.pdfapi.dev/v1/files/{file_id}',
    headers={'Authorization': f'Bearer {os.environ["PDFAPI_KEY"]}'}
)

if response.status_code == 204:
    print('File deleted successfully')

Response

Returns 204 No Content on success.


Error Responses

File Not Found (404)

{
  "error": {
    "code": "FILE_NOT_FOUND",
    "message": "File not found or already deleted"
  }
}

Storage Limit Exceeded (403)

{
  "error": {
    "code": "STORAGE_LIMIT_EXCEEDED",
    "message": "Storage limit exceeded. Delete files or upgrade your plan."
  }
}

See Error Codes for complete reference.


Storage Limits by Plan

PlanStorageRetention
Free100 MB7 days
Pro5 GB30 days
Business25 GB90 days
EnterpriseCustomCustom

Use Cases

Generate and Share

Store a PDF and share the download link:

async function generateAndShare(markdown) {
  const response = await fetch('https://api.pdfapi.dev/v1/pdf/markdown', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.PDFAPI_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      markdown,
      storage: { enabled: true, filename: 'shared-document.pdf' }
    }),
  });

  const fileId = response.headers.get('X-File-ID');
  const downloadUrl = `https://api.pdfapi.dev/v1/files/${fileId}/download`;

  // Share this URL with your users (requires authentication)
  return { fileId, downloadUrl };
}

Batch Processing with Storage

Generate multiple PDFs and store them for later retrieval:

import requests
import os

documents = [
    {'name': 'Invoice 001', 'content': '# Invoice 001\n...'},
    {'name': 'Invoice 002', 'content': '# Invoice 002\n...'},
    {'name': 'Invoice 003', 'content': '# Invoice 003\n...'},
]

file_ids = []
for doc in documents:
    response = requests.post(
        'https://api.pdfapi.dev/v1/pdf/markdown',
        headers={
            'Authorization': f'Bearer {os.environ["PDFAPI_KEY"]}',
            'Content-Type': 'application/json',
        },
        json={
            'markdown': doc['content'],
            'storage': {
                'enabled': True,
                'filename': f"{doc['name']}.pdf"
            }
        }
    )

    file_id = response.headers.get('X-File-ID')
    file_ids.append({'name': doc['name'], 'id': file_id})

print('Generated files:', file_ids)

Notes

  • Files are automatically deleted after the retention period
  • Deleted files cannot be recovered
  • File IDs are unique UUIDs
  • Download URLs require authentication
  • Files count toward your storage quota
  • Filename is for display purposes; the actual file is identified by ID