PDF Workflows
PDF Workflows allow you to automate the process of sending physical mail from PDF files. Instead of manually splitting multi-page PDFs, extracting addresses, and creating individual letter orders, you can define a reusable workflow that does it all in one step.
This is ideal for businesses that receive bulk PDFs (e.g. invoices, statements, notices) and need to extract recipient addresses directly from the pages and send each one as a separate letter. It also supports sending pre-formatted PDFs as letters when you already know the recipient and sender details.
Overview
There are two stages in the process of sending mail with PDF Workflows:
- Create a Workflow — Define a reusable set of jobs (e.g. rotate pages, resize, extract addresses and send letters).
- Run the Workflow — Upload a PDF to execute the workflow. PostGrid processes the PDF, extracts the necessary information, and creates letter orders automatically.
If you want to review orders before they are sent, you can enable confirmation mode, which pauses the workflow after processing so you can inspect the pending orders and confirm before any mail goes out.
Getting Started
To use PDF Workflows, you will need your PostGrid API key. You can find your API key on your PostGrid dashboard settings page.
All requests are made to the base URL:
https://api.postgrid.com/print-mail/v1/pdf_workflows
Note: PDF Workflows are available in both test and live modes. In test mode, letter orders are created but no actual mail is sent. Use test mode to verify that addresses are being extracted correctly and letters look as expected before switching to live mode.
Step 1: Create a Workflow
A workflow is a reusable definition that describes what to do with a PDF when it is uploaded. You define it once and can run it as many times as you like with different PDFs.
Each workflow contains an ordered list of jobs. Jobs are processed sequentially - the output of one job feeds into the next.
Available Job Types
| Job | Key | Description |
|---|---|---|
| Landscape to Portrait | landscapeToPortrait | Rotates any landscape-oriented pages to portrait orientation. |
| Auto Resize | autoResize | Resizes the PDF pages to a target letter size (us_letter or us_legal). |
| Extract Info & Send Letter | extractInfoSendLetter | Extracts recipient and sender addresses from defined regions on each page, then creates and sends a letter order for each one. |
| Send Letter | sendLetter | Sends the uploaded PDF as a letter using contact details you provide directly (via defaultParams on the workflow and params on the run), rather than extracting addresses from the PDF. |
Important: Workflows must end with a send job (
extractInfoSendLetterorsendLetter). You cannot have multiple send jobs in a single workflow, and the send job must always be the last one in the chain.
Job Sequencing Rules
Not every combination of jobs is valid. The table below shows which job types can precede each other:
| Job | Can follow |
|---|---|
landscapeToPortrait | autoResize, or be the first job |
autoResize | landscapeToPortrait, or be the first job |
extractInfoSendLetter | landscapeToPortrait, autoResize, or be the first job |
sendLetter | landscapeToPortrait, autoResize, or be the first job |
For example, a valid three-job workflow might be: landscapeToPortrait → autoResize → extractInfoSendLetter.
Creating the Workflow
To create a workflow, send a POST request to /pdf_workflows.
curl https://api.postgrid.com/print-mail/v1/pdf_workflows \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
--data '{
"requireConfirmationBeforeSending": false,
"jobs": [
{
"extractInfoSendLetter": {
"color": true,
"doubleSided": false,
"addressPlacement": "insert_blank_page",
"fromRegion": {
"left": 3.18,
"top": 0.98,
"width": 1.92,
"height": 0.54
},
"fromCountryCode": "CA",
"toRegion": {
"left": 0.35,
"top": 2.1,
"width": 3.13,
"height": 0.51
},
"toCountryCode": "CA"
}
}
]
}'This creates a workflow with a single job that extracts addresses from defined regions on each page and sends coloured letters with the address printed on a separate blank page.
Workflow Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
jobs | array | Yes | An ordered list of jobs to run. Minimum 1, maximum 3. |
requireConfirmationBeforeSending | boolean | No | If true (default), the workflow pauses after processing so you can review pending orders before they are sent. Set to false to send automatically. |
description | string | No | An internal description for your reference. |
metadata | object | No | Arbitrary key-value pairs to attach to the workflow. |
Extract Info & Send Letter Parameters
The extractInfoSendLetter job is the most common job type. It extracts recipient and sender addresses from specific regions of the PDF and creates letter orders.
| Parameter | Type | Required | Description |
|---|---|---|---|
toRegion | object | Yes | The region on the page where the recipient's address is located. |
toCountryCode | string | Yes | The recipient's country code in ISO 3166-1 Alpha-2 format (e.g., CA, US, GB). |
fromRegion | object | No* | The region on the page where the sender's address is located. |
fromCountryCode | string | No* | The sender's country code in ISO 3166-1 Alpha-2 format. |
fromContact | string | No* | A PostGrid contact ID to use as the sender instead of extracting from the PDF. |
color | boolean | No | Print in color. Defaults to false. |
doubleSided | boolean | No | Print double-sided. Defaults to false. |
addressPlacement | string | No | Where to place the address: top_first_page (default) or insert_blank_page. |
mailingClass | string | No | The mailing class for delivery: first_class, standard_class, express, certified, certified_return_receipt, or registered. |
Note: You must provide either
fromRegionandfromCountryCodetogether, orfromContact- but not both. UsefromContactwhen the sender address is not printed on the PDF or is difficult to extract.
Region Object
Regions define a rectangular area on the PDF page (in inches) where an address can be found. PostGrid reads the text within this region and parses it as an address.
| Field | Type | Description |
|---|---|---|
left | number | Distance in inches from the left edge of the page. |
top | number | Distance in inches from the top edge of the page. |
width | number | Width of the region in inches. |
height | number | Height of the region in inches. |
To determine the correct region coordinates, open your PDF and measure the position of the address block. Most PDF viewers display dimensions in inches or have a measurement tool available.
Send Letter Parameters
The sendLetter job is for cases where you already know the recipient and sender — you provide the contact details directly rather than extracting them from the PDF. The uploaded PDF is used as the letter content as-is.
This job uses two sets of parameters that are merged together at run time:
defaultParams— Defined on the workflow. These are the parameters that stay the same across every run (e.g. the sender address).params— Provided when creating a run. These are the parameters that change per run (e.g. the recipient address).
The combined parameters must satisfy the requirements for creating a letter (see Sending Letters using the API). At minimum, you need to and from contacts between the two.
| Parameter | Type | Required | Description |
|---|---|---|---|
defaultParams | object | Yes | Default letter creation parameters. Typically includes the from contact and any print options. |
Example defaultParams:
{
"from": {
"firstName": "Jane",
"addressLine1": "145 Mulberry St",
"city": "New York",
"provinceOrState": "NY",
"postalOrZip": "10013"
}
}Note: When using
sendLetter, theparamsfield on the run is required to supply any remaining letter fields not covered bydefaultParams. If the combineddefaultParamsandparamsdo not contain all required letter fields (such asto), the run creation will return a400error.
Step 2: Run the Workflow
Once your workflow is created, you can run it by uploading a PDF. Each run processes the PDF through all the jobs defined in the workflow.
To create a run, send a POST request to /pdf_workflows/<pdf_workflow_id>/runs with the PDF file attached.
curl https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id>/runs \
-H "x-api-key: <your-api-key>" \
-F "pdf=@/path/to/your/file.pdf"You can also provide a publicly accessible URL to a PDF instead of uploading the file directly:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id>/runs \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
--data '{
"pdf": "https://example.com/your-file.pdf"
}'Run Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
pdf | file or URL | Yes | The PDF to process. Either upload a file or provide a publicly accessible URL. |
params | object | No | Additional parameters to pass to the workflow run. When using a sendLetter job, these are merged with the workflow's defaultParams to form the full letter creation request (e.g. the to contact). |
description | string | No | An internal description for your reference. |
metadata | object | No | Arbitrary key-value pairs to attach to the run. |
Workflow Run Statuses
After you create a run, it progresses through the following statuses:
| Status | Description |
|---|---|
queued | The run has been created and is waiting to be processed. |
processing | The PDF is being processed (pages rotated, resized, addresses extracted). |
waiting_for_confirmation | Processing is complete. Pending orders have been created and are waiting for your confirmation before any mail is sent. Only applies when requireConfirmationBeforeSending is true. |
creating_orders | Confirmation received. Letter orders are being created. |
completed | All orders have been created. A CSV report is available. |
failed | Something went wrong during processing. Check the failure.note field for details. |
Step 3: Review and Confirm (Optional)
If your workflow has requireConfirmationBeforeSending set to true (the default), the run will pause at waiting_for_confirmation after processing. This gives you the opportunity to review exactly what PostGrid is about to send before any mail goes out.
List Pending Orders
To see the pending orders for a run:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id>/runs/<run_id>/pending_orders \
-H "x-api-key: <your-api-key>"Each pending order includes the extracted address information and a link to download the PDF that would be sent. Review these to make sure the addresses were extracted correctly and the letter content looks right.
Confirm the Run
Once you are satisfied, confirm the run to proceed with creating the letter orders:
curl -X POST https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id>/runs/<run_id>/confirm \
-H "x-api-key: <your-api-key>"After confirmation, the run status changes to creating_orders and then completed once all letters have been created.
Important: You can only confirm a run that is in the
waiting_for_confirmationstatus. Attempting to confirm a run in any other status will return an error.
Tracking and Reports
Once a run reaches the completed status, a CSV report is generated that shows the result for each pending order — whether the letter was successfully created or if there was an error (e.g., an invalid address).
Retrieve a Run
To check the status of a run and access the report:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id>/runs/<run_id> \
-H "x-api-key: <your-api-key>"The response includes:
status— The current status of the run.uploadedPDF— A URL to download the original PDF that was uploaded.report— A URL to download the CSV report (available once the run iscompleted).failure— If the run failed, this object contains anoteexplaining what went wrong.
List All Runs
To see all runs for a specific workflow:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id>/runs \
-H "x-api-key: <your-api-key>"Managing Workflows
Retrieve a Workflow
curl https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id> \
-H "x-api-key: <your-api-key>"List All Workflows
curl https://api.postgrid.com/print-mail/v1/pdf_workflows \
-H "x-api-key: <your-api-key>"Delete a Workflow
curl -X DELETE https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id> \
-H "x-api-key: <your-api-key>"Chaining Multiple Jobs
For PDFs that need pre-processing before addresses can be extracted, you can chain multiple jobs together. Jobs run in order — the output of one job is the input to the next.
Example: Rotate and Send
If your PDF contains a mix of landscape and portrait pages, add a landscapeToPortrait job before the send job to ensure all pages are in the correct orientation:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
--data '{
"requireConfirmationBeforeSending": true,
"jobs": [
{
"landscapeToPortrait": {
"rotateCounterClockwise": false
}
},
{
"extractInfoSendLetter": {
"color": true,
"doubleSided": false,
"addressPlacement": "insert_blank_page",
"toRegion": {
"left": 0.35,
"top": 2.1,
"width": 3.13,
"height": 0.51
},
"toCountryCode": "US",
"fromContact": "contact_abc123"
}
}
]
}'In this example, we use
fromContactinstead offromRegionto specify the sender. This is useful when the sender address is not printed on the PDF or when the same sender is used for all letters.
Example: Resize and Send
If your PDF pages are not standard letter size, add an autoResize job to resize them before sending:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
--data '{
"jobs": [
{
"autoResize": {
"size": "us_letter"
}
},
{
"extractInfoSendLetter": {
"color": false,
"addressPlacement": "top_first_page",
"toRegion": {
"left": 0.5,
"top": 2.0,
"width": 3.0,
"height": 0.5
},
"toCountryCode": "US",
"fromRegion": {
"left": 3.5,
"top": 0.5,
"width": 2.0,
"height": 0.5
},
"fromCountryCode": "US"
}
}
]
}'Example: Send a PDF Directly
If you already know the recipient and sender addresses and just want to send a PDF as a letter, use the sendLetter job. Define the sender in the workflow's defaultParams, and pass the recipient when creating each run:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
--data '{
"requireConfirmationBeforeSending": false,
"jobs": [
{
"sendLetter": {
"defaultParams": {
"from": {
"firstName": "Jane",
"addressLine1": "145 Mulberry St",
"city": "New York",
"provinceOrState": "NY",
"postalOrZip": "10013"
}
}
}
}
]
}'Then create a run, providing the recipient via params:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows/<pdf_workflow_id>/runs \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
--data '{
"pdf": "https://example.com/invoice.pdf",
"params": {
"to": {
"firstName": "John",
"addressLine1": "200 University Ave W",
"city": "Waterloo",
"provinceOrState": "ON",
"postalOrZip": "N2L 3G1"
}
}
}'This approach is useful when you have pre-formatted PDFs that don't contain addresses on the page, or when you want to leverage the workflow's async processing, confirmation, and reporting features for straightforward letter sends.
Example: Full Pipeline
For the most robust setup, combine all three jobs — rotate, resize, then extract and send:
curl https://api.postgrid.com/print-mail/v1/pdf_workflows \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
--data '{
"requireConfirmationBeforeSending": true,
"jobs": [
{
"landscapeToPortrait": {}
},
{
"autoResize": {
"size": "us_letter"
}
},
{
"extractInfoSendLetter": {
"color": true,
"doubleSided": true,
"addressPlacement": "insert_blank_page",
"toRegion": {
"left": 0.35,
"top": 2.1,
"width": 3.13,
"height": 0.51
},
"toCountryCode": "CA",
"fromRegion": {
"left": 3.18,
"top": 0.98,
"width": 1.92,
"height": 0.54
},
"fromCountryCode": "CA"
}
}
]
}'Quick Reference
| Action | Method | Endpoint |
|---|---|---|
| Create a workflow | POST | /pdf_workflows |
| Retrieve a workflow | GET | /pdf_workflows/:id |
| List workflows | GET | /pdf_workflows |
| Delete a workflow | DELETE | /pdf_workflows/:id |
| Create a run | POST | /pdf_workflows/:id/runs |
| Retrieve a run | GET | /pdf_workflows/:id/runs/:runID |
| List runs | GET | /pdf_workflows/:id/runs |
| List pending orders | GET | /pdf_workflows/:id/runs/:runID/pending_orders |
| Confirm a run | POST | /pdf_workflows/:id/runs/:runID/confirm |
Updated about 1 month ago
