Adobe Core Workflow B — PDF Services
Overview
Document automation using Adobe PDF Services API: create PDFs from HTML/DOCX, extract structured text and tables with Sensei AI, generate documents from Word templates with JSON data, and convert PDFs to LLM-friendly Markdown.
Prerequisites
- Completed
adobe-install-auth with PDF Services credentials
npm install @adobe/pdfservices-node-sdk (v4.x+)
- 500 free document transactions/month on the free tier
Instructions
Step 1: Create PDF from HTML
import {
ServicePrincipalCredentials,
PDFServices,
MimeType,
CreatePDFJob,
CreatePDFResult,
} from '@adobe/pdfservices-node-sdk';
import * as fs from 'fs';
const credentials = new ServicePrincipalCredentials({
clientId: process.env.ADOBE_CLIENT_ID!,
clientSecret: process.env.ADOBE_CLIENT_SECRET!,
});
const pdfServices = new PDFServices({ credentials });
export async function htmlToPdf(htmlPath: string, outputPath: string): Promise<void> {
const inputStream = fs.createReadStream(htmlPath);
const inputAsset = await pdfServices.upload({
readStream: inputStream,
mimeType: MimeType.HTML,
});
const job = new CreatePDFJob({ inputAsset });
const pollingURL = await pdfServices.submit({ job });
const result = await pdfServices.getJobResult({
pollingURL,
resultType: CreatePDFResult,
});
const resultAsset = result.result!.asset;
const streamAsset = await pdfServices.getContent({ asset: resultAsset });
const output = fs.createWriteStream(outputPath);
streamAsset.readStream.pipe(output);
await new Promise((resolve, reject) => {
output.on('finish', resolve);
output.on('error', reject);
});
console.log(`PDF created: ${outputPath}`);
}
Step 2: Extract Text and Tables from PDF (Sensei AI)
import {
PDFServices,
MimeType,
ExtractPDFParams,
ExtractElementType,
ExtractPDFJob,
ExtractPDFResult,
ExtractRenditionsElementType,
} from '@adobe/pdfservices-node-sdk';
import * as fs from 'fs';
import AdmZip from 'adm-zip';
export async function extractPdfContent(
pdfPath: string,
options?: { tables?: boolean; figures?: boolean }
): Promise<{ text: string; tables: any[]; }> {
const inputStream = fs.createReadStream(pdfPath);
const inputAsset = await pdfServices.upload({
readStream: inputStream,
mimeType: MimeType.PDF,
});
const elements = [ExtractElementType.TEXT];
if (options?.tables !== false) elements.push(.);
params = ({
: elements,
...(options?. && {
: [.],
}),
});
job = ({ inputAsset, params });
pollingURL = pdfServices.({ job });
result = pdfServices.({
pollingURL,
: ,
});
resultAsset = result.!.;
streamAsset = pdfServices.({ : resultAsset });
: [] = [];
( chunk streamAsset.) {
chunks.(.(chunk));
}
zip = (.(chunks));
structuredData = .(
zip.()
);
textElements = structuredData.
.( el.)
.( el.);
tableElements = structuredData.
.( el.?.());
{ : textElements.(), : tableElements };
}
Step 3: Document Generation from Word Template
import {
PDFServices,
MimeType,
DocumentMergeJob,
DocumentMergeParams,
DocumentMergeResult,
OutputFormat,
} from '@adobe/pdfservices-node-sdk';
import * as fs from 'fs';
export async function generateDocument(
templatePath: string,
data: Record<string, any>,
outputPath: string,
format: 'pdf' | 'docx' = 'pdf'
): Promise<void> {
const inputStream = fs.createReadStream(templatePath);
const inputAsset = await pdfServices.upload({
readStream: inputStream,
mimeType: MimeType.DOCX,
});
const params = new DocumentMergeParams({
jsonDataForMerge: data,
outputFormat: format === 'pdf' ? OutputFormat. : .,
});
job = ({ inputAsset, params });
pollingURL = pdfServices.({ job });
result = pdfServices.({
pollingURL,
: ,
});
resultAsset = result.!.;
streamAsset = pdfServices.({ : resultAsset });
output = fs.(outputPath);
streamAsset..(output);
.();
}
Step 4: PDF to Markdown (LLM-Friendly)
export async function pdfToMarkdown(pdfPath: string): Promise<string> {
const { text } = await extractPdfContent(pdfPath, { tables: false });
return text;
}
Output
- PDF files created from HTML, DOCX, or other formats
- Structured JSON with text, tables, and figures extracted from PDFs
- Dynamic documents generated from Word templates with JSON data
- Markdown text extracted from PDFs for LLM consumption
Error Handling
| Error | Cause | Solution |
|---|
DISQUALIFIED | Encrypted or DRM-protected PDF | Remove encryption before processing |
BAD_PDF | Corrupted PDF file | Validate PDF with pdfinfo before upload |
TIMEOUT | Large PDF (100+ pages) | Split into smaller PDFs first |
QUOTA_EXCEEDED | Free tier limit (500 tx/month) | Upgrade plan or wait for monthly reset |
UNSUPPORTED_MEDIA_TYPE | Wrong MimeType for input | Match MimeType to actual file format |
Resources
Next Steps
For common errors, see adobe-common-errors.