This workflow corresponds to n8n.io template #16394 — we link there as the canonical source.
This workflow follows the Gmail Trigger → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "LWWXKqrEi3hdNOy2",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Extract tracking numbers from Gmail PDF attachments to Google Sheets with okraPDF OCR",
"tags": [],
"nodes": [
{
"id": "ec424789-3e22-4124-9dd2-2308393103d2",
"name": "Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2480,
-352
],
"parameters": {
"width": 480,
"height": 560,
"content": "## Extract tracking numbers from Gmail PDF attachments to Google Sheets with okraPDF OCR\n\nFor operations, ecommerce, logistics, and support teams that get scanned shipping labels or delivery PDFs in Gmail and need the tracking numbers logged in Google Sheets \u2014 without copying from images by hand.\n\n### How it works\n\n1. The Gmail trigger watches for messages with PDF attachments and downloads the first one.\n2. An IF node confirms the attachment is really a PDF.\n3. The PDF is uploaded to okraPDF and an OCR parse job is started.\n4. The workflow waits and polls the job until it reaches a terminal state.\n5. A row is appended to Google Sheets with the sender, subject, job status, tracking-number candidates found in the OCR text, and a short preview.\n\n### Setup\n\n- Add Gmail, Google Sheets, and okraPDF (HTTP Header Auth) credentials.\n- Get an okraPDF API key at okrapdf.com/settings/keys.\n- Pick your destination spreadsheet and sheet in the Google Sheets node.\n- In \"Configure OCR Options\", raise okra_parse_pages if labels span more than one page.\n\n### Customization\n\nEdit the tracking-number expression for carrier-specific formats, or duplicate the PDF branch to handle attachment_1 and beyond."
},
"typeVersion": 1
},
{
"id": "ce773849-4aac-4568-a005-406476a9a5d1",
"name": "Section - Receive",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1952,
-336
],
"parameters": {
"color": 7,
"width": 420,
"height": 360,
"content": "## 1. Receive & filter PDF emails\n\nThe Gmail trigger downloads the first attachment; the IF node lets only real PDFs continue."
},
"typeVersion": 1
},
{
"id": "c50f31f6-3dfa-4f9a-9aa7-1553b7e889a1",
"name": "Section - Upload & parse",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1488,
-336
],
"parameters": {
"color": 7,
"width": 620,
"height": 360,
"content": "## 2. Upload & start OCR\n\nSet OCR options, upload the PDF to okraPDF, and start an OCR parse job."
},
"typeVersion": 1
},
{
"id": "4681f65b-2c6f-4d39-916c-fa7ae781507b",
"name": "Section - Poll & log",
"type": "n8n-nodes-base.stickyNote",
"position": [
-816,
-336
],
"parameters": {
"color": 7,
"width": 840,
"height": 360,
"content": "## 3. Poll, then log to Sheets\n\nWait and re-poll the job until it's terminal, then append a tracking-number row to Google Sheets."
},
"typeVersion": 1
},
{
"id": "fb3f664e-48a2-48d2-915d-307dc713f4cf",
"name": "Gmail Trigger - PDF Attachments",
"type": "n8n-nodes-base.gmailTrigger",
"position": [
-1904,
-128
],
"parameters": {
"simple": false,
"filters": {
"q": "has:attachment filename:pdf",
"readStatus": "unread"
},
"options": {
"downloadAttachments": true,
"dataPropertyAttachmentsPrefixName": "attachment_"
},
"pollTimes": {
"item": [
{
"mode": "everyMinute"
}
]
}
},
"credentials": {
"gmailOAuth2": {
"name": "<your credential>"
}
},
"typeVersion": 1.4
},
{
"id": "de87d992-c4fe-46c6-817b-5adab6359f9e",
"name": "IF attachment_0 is PDF",
"type": "n8n-nodes-base.if",
"position": [
-1680,
-128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "has-attachment-0",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ $binary.attachment_0?.mimeType || '' }}",
"rightValue": "application/pdf"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "980fa6e5-dd29-47f5-9648-9ddc0efb1cdf",
"name": "Configure OCR Options",
"type": "n8n-nodes-base.set",
"position": [
-1456,
-128
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "okra-parser",
"name": "okra_parser",
"type": "string",
"value": "gemini-vision"
},
{
"id": "okra-parse-pages",
"name": "okra_parse_pages",
"type": "string",
"value": "1"
},
{
"id": "okra-metadata-source",
"name": "okra_metadata_source",
"type": "string",
"value": "n8n-gmail-tracking"
}
]
},
"includeOtherFields": true
},
"typeVersion": 3.4
},
{
"id": "6d93d0d4-4914-4fe3-bf32-404fec48f98b",
"name": "Upload attachment_0 to okraPDF",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1232,
-128
],
"parameters": {
"url": "https://api.okrapdf.com/v1/files",
"method": "POST",
"options": {
"timeout": 300000
},
"sendBody": true,
"contentType": "multipart-form-data",
"authentication": "genericCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "file",
"parameterType": "formBinaryData",
"inputDataFieldName": "attachment_0"
}
]
},
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "e7068726-2075-479a-911f-df67b1c1305c",
"name": "OCR Parse Uploaded PDF",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1008,
-128
],
"parameters": {
"url": "https://api.okrapdf.com/v1/parse",
"method": "POST",
"options": {
"timeout": 300000
},
"jsonBody": "={\n \"parser\": \"{{ $('Configure OCR Options').item.json.okra_parser || 'gemini-vision' }}\",\n \"file\": { \"id\": \"{{ $json.id }}\" },\n \"pages\": \"{{ $('Configure OCR Options').item.json.okra_parse_pages || '1' }}\",\n \"metadata\": { \"source\": \"{{ $('Configure OCR Options').item.json.okra_metadata_source || 'n8n-gmail-tracking' }}\" }\n}",
"sendBody": true,
"sendHeaders": true,
"specifyBody": "json",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "824c49c6-5b94-46d3-9695-18f8849b6916",
"name": "Wait for Parse Result",
"type": "n8n-nodes-base.wait",
"position": [
-784,
-128
],
"parameters": {
"amount": 15
},
"typeVersion": 1.1
},
{
"id": "ca06c61e-0fea-4fad-bdac-03f17a351930",
"name": "Get Job Result",
"type": "n8n-nodes-base.httpRequest",
"position": [
-560,
-208
],
"parameters": {
"url": "={{ ($json.status_url && $json.status_url.startsWith('http')) ? $json.status_url : ('https://api.okrapdf.com/v1/jobs/' + ($json.id || $json.job_id)) }}",
"options": {
"timeout": 300000,
"response": {
"response": {
"responseFormat": "json"
}
}
},
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth"
},
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "78fa88fc-cec5-4c27-bacc-7ef036809c77",
"name": "If Job Finished?",
"type": "n8n-nodes-base.if",
"position": [
-336,
-128
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 2,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "terminal-status",
"operator": {
"type": "string",
"operation": "equals"
},
"leftValue": "={{ ['succeeded','completed','completed_with_errors','failed','canceled','cancelled'].includes(($json.status || $json.internal_status || '').toLowerCase()) ? 'done' : 'pending' }}",
"rightValue": "done"
}
]
}
},
"typeVersion": 2.2
},
{
"id": "76063812-ff91-4546-bbea-29592e4a7e9a",
"name": "Append Tracking Row to Sheets",
"type": "n8n-nodes-base.googleSheets",
"position": [
-112,
-128
],
"parameters": {
"columns": {
"value": {
"result": "={{ $json.result.formats.nodes.pages }}"
},
"schema": [
{
"id": "object",
"type": "string",
"display": true,
"required": false,
"displayName": "object",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "id",
"type": "string",
"display": true,
"removed": false,
"required": false,
"displayName": "id",
"defaultMatch": true,
"canBeUsedToMatch": true
},
{
"id": "type",
"type": "string",
"display": true,
"required": false,
"displayName": "type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "url",
"type": "string",
"display": true,
"required": false,
"displayName": "url",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "created",
"type": "string",
"display": true,
"required": false,
"displayName": "created",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "livemode",
"type": "string",
"display": true,
"required": false,
"displayName": "livemode",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "job_id",
"type": "string",
"display": true,
"required": false,
"displayName": "job_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "owner_user_id",
"type": "string",
"display": true,
"required": false,
"displayName": "owner_user_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "job_type",
"type": "string",
"display": true,
"required": false,
"displayName": "job_type",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "job_label",
"type": "string",
"display": true,
"required": false,
"displayName": "job_label",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "status",
"type": "string",
"display": true,
"required": false,
"displayName": "status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "internal_status",
"type": "string",
"display": true,
"required": false,
"displayName": "internal_status",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "document_id",
"type": "string",
"display": true,
"required": false,
"displayName": "document_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "file_name",
"type": "string",
"display": true,
"required": false,
"displayName": "file_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "run_id",
"type": "string",
"display": true,
"required": false,
"displayName": "run_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "workflow_name",
"type": "string",
"display": true,
"required": false,
"displayName": "workflow_name",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "workflow_id",
"type": "string",
"display": true,
"required": false,
"displayName": "workflow_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "engine_id",
"type": "string",
"display": true,
"required": false,
"displayName": "engine_id",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "provider",
"type": "string",
"display": true,
"required": false,
"displayName": "provider",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "model",
"type": "string",
"display": true,
"required": false,
"displayName": "model",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "progress_current",
"type": "string",
"display": true,
"required": false,
"displayName": "progress_current",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "progress_total",
"type": "string",
"display": true,
"required": false,
"displayName": "progress_total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "progress",
"type": "string",
"display": true,
"required": false,
"displayName": "progress",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "pages_completed",
"type": "string",
"display": true,
"required": false,
"displayName": "pages_completed",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "pages_failed",
"type": "string",
"display": true,
"required": false,
"displayName": "pages_failed",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "pages_running",
"type": "string",
"display": true,
"required": false,
"displayName": "pages_running",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "pages_pending",
"type": "string",
"display": true,
"required": false,
"displayName": "pages_pending",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "pages_total",
"type": "string",
"display": true,
"required": false,
"displayName": "pages_total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "chunks_completed",
"type": "string",
"display": true,
"required": false,
"displayName": "chunks_completed",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "chunks_total",
"type": "string",
"display": true,
"required": false,
"displayName": "chunks_total",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "cost_usd",
"type": "string",
"display": true,
"required": false,
"displayName": "cost_usd",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "duration_ms",
"type": "string",
"display": true,
"required": false,
"displayName": "duration_ms",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "error",
"type": "string",
"display": true,
"required": false,
"displayName": "error",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "latest_error",
"type": "string",
"display": true,
"required": false,
"displayName": "latest_error",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "last_error",
"type": "string",
"display": true,
"required": false,
"displayName": "last_error",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "request",
"type": "string",
"display": true,
"required": false,
"displayName": "request",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "result",
"type": "string",
"display": true,
"required": false,
"displayName": "result",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "metadata",
"type": "string",
"display": true,
"required": false,
"displayName": "metadata",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "created_at",
"type": "string",
"display": true,
"required": false,
"displayName": "created_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "updated_at",
"type": "string",
"display": true,
"required": false,
"displayName": "updated_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "completed_at",
"type": "string",
"display": true,
"required": false,
"displayName": "completed_at",
"defaultMatch": false,
"canBeUsedToMatch": true
},
{
"id": "completed",
"type": "string",
"display": true,
"required": false,
"displayName": "completed",
"defaultMatch": false,
"canBeUsedToMatch": true
}
],
"mappingMode": "defineBelow",
"matchingColumns": [
"id"
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {},
"operation": "append",
"sheetName": {
"__rl": true,
"mode": "list",
"value": "gid=0",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Gg7QzB8Ap6XFBUsqAHKe865V-lt2e6QPm4rNqFud39I/edit#gid=0",
"cachedResultName": "Sheet1"
},
"documentId": {
"__rl": true,
"mode": "list",
"value": "1Gg7QzB8Ap6XFBUsqAHKe865V-lt2e6QPm4rNqFud39I",
"cachedResultUrl": "https://docs.google.com/spreadsheets/d/1Gg7QzB8Ap6XFBUsqAHKe865V-lt2e6QPm4rNqFud39I/edit?usp=drivesdk",
"cachedResultName": "n8n-okra"
}
},
"credentials": {
"googleSheetsOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.4
}
],
"active": true,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "f41866bd-a4f3-476e-a573-762e57596745",
"nodeGroups": [],
"connections": {
"Get Job Result": {
"main": [
[
{
"node": "If Job Finished?",
"type": "main",
"index": 0
}
]
]
},
"If Job Finished?": {
"main": [
[
{
"node": "Append Tracking Row to Sheets",
"type": "main",
"index": 0
}
],
[
{
"node": "Wait for Parse Result",
"type": "main",
"index": 0
}
]
]
},
"Configure OCR Options": {
"main": [
[
{
"node": "Upload attachment_0 to okraPDF",
"type": "main",
"index": 0
}
]
]
},
"Wait for Parse Result": {
"main": [
[
{
"node": "Get Job Result",
"type": "main",
"index": 0
}
]
]
},
"IF attachment_0 is PDF": {
"main": [
[
{
"node": "Configure OCR Options",
"type": "main",
"index": 0
}
]
]
},
"OCR Parse Uploaded PDF": {
"main": [
[
{
"node": "Wait for Parse Result",
"type": "main",
"index": 0
}
]
]
},
"Upload attachment_0 to okraPDF": {
"main": [
[
{
"node": "OCR Parse Uploaded PDF",
"type": "main",
"index": 0
}
]
]
},
"Gmail Trigger - PDF Attachments": {
"main": [
[
{
"node": "IF attachment_0 is PDF",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
gmailOAuth2googleSheetsOAuth2ApihttpHeaderAuth
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow monitors unread Gmail messages with PDF attachments, sends the first PDF to okraPDF for OCR parsing, then extracts likely tracking numbers from the OCR text and appends the email and parse details as a new row in Google Sheets. Triggers every minute when an unread…
Source: https://n8n.io/workflows/16394/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
📘 Description
This n8n workflow is designed for IT security professionals, email administrators, and organizations that want to automatically scan URLs received in emails for potential security threats. It provides
This workflow automatically detects duplicate invoices from Gmail. Incoming PDF attachments are scanned by the easybits AI Extractor, then checked against the Master Finance File in Google Sheets. Dup
Gmail分類PoC ワークフロー. Uses gmailTrigger, httpRequest, line, googleSheets. Event-driven trigger; 8 nodes.
Receive any business document via email. The attachment is automatically classified (Invoice, Contract, or Purchase Order) using easybits Extractor, then routed down the correct path where a second Ex