I built a shipping document processor in n8n — parses Bills of Lading and packing lists from Gmail, tracks ETAs, and fires an urgent Slack alert when a shipment is arriving within 3 days

Logistics teams get shipping documents by email all day — Bills of Lading, packing lists, arrival notices, customs declarations. Someone has to open each one, pull out the B/L number, route, vessel, ETA, container details, and log it somewhere. When you’re tracking 30+ active shipments, that’s a lot of manual work. And when a shipment arrives with 1 day notice because nobody caught the ETA, that’s an expensive scramble.

Built a workflow that processes every shipping document the moment it hits Gmail.

What it does

Shipping document arrives in Gmail → downloads attachment → extracts all shipment data → calculates days to arrival → logs to shipment tracker → routes to urgent alert (≤3 days) or standard notification

Takes about 10-15 seconds per document.

Document types it handles

  • Bills of Lading (B/L)

  • Packing Lists

  • Commercial Invoices

  • Customs Declarations

  • Shipping Manifests

  • Arrival Notices

  • Delivery Orders

What gets extracted

Identification:

  • Document type, B/L number, booking reference number

  • Shipment ID (uses B/L number if available, generates one if not)

Parties:

  • Shipper — name, address, country

  • Consignee — name, address, country

  • Notify party — name and contact

Route and vessel:

  • Port of loading, port of discharge, place of delivery

  • Route formatted as Shanghai → Los Angeles

  • Vessel name and voyage number

Dates:

  • ETD (Estimated Time of Departure)

  • ETA (Estimated Time of Arrival)

  • Days to arrival — calculated automatically from today’s date

Containers:

  • Each container number, type (20GP, 40GP, 40HC, etc.), and seal number

  • Total container count

Cargo:

  • Cargo description, HS codes (tariff codes)

  • Number of packages, gross weight (kg), volume (CBM)

  • Total weight and total volume

Terms:

  • Freight terms (Prepaid / Collect)

  • Incoterms (FOB, CIF, EXW, etc.)

  • Special instructions

ETA status and routing

The Code node calculates days to arrival and tags each shipment:

  • Arrived/Overdue → ≤0 days

  • Arriving Soon → 1-3 days → urgent Slack alert

  • In Transit → more than 3 days → standard notification

Urgent alert (arriving within 3 days):


🚨 SHIPMENT ARRIVING SOON

Shipment: HLCUSHA2401234

Type: Bill of Lading

🚢 Route: Shanghai → Los Angeles

Vessel: EVER GIVEN / Voyage V024W

⏰ ETA: 2025-03-15

🔴 Only 2 days until arrival!

📦 Cargo:

• Containers: 3

• Weight: 18,400 kg

• Incoterms: FOB

Shipper: Shenzhen Electronics Co.

Consignee: Pacific Imports LLC

Standard notification (in transit):


📦 New Shipping Document Processed

Shipment: MAEU1234567

Type: Packing List

🚢 Route: Hamburg → New York

Vessel: MSC GULSUN / Voyage 024E

ETA: 2025-04-02 (18 days)

Details:

• Containers: 1

• Weight: 4,200 kg

• Incoterms: CIF

Shipper: European Auto Parts GmbH

Consignee: East Coast Distributors

What lands in Google Sheets

Each row: Shipment ID, Document Type, B/L Number, Shipper, Consignee, Route, Vessel, ETD, ETA, Days to Arrival, Containers, Container Count, Total Weight (kg), HS Codes, Incoterms, Received Date

Your full shipment tracker in one sheet. Filter by Days to Arrival to see what needs immediate attention.

Setup

You’ll need:

  • Gmail (where shipping documents arrive)

  • Google Sheets (free)

  • n8n instance (self-hosted — uses PDF Vector community node)

  • PDF Vector account (free tier: 100 credits/month, roughly 25-30 documents)

  • Slack (optional — delete the last two nodes if not needed)

About 15 minutes to configure.

Download

Workflow JSON:

github.com/khanhduyvt0101/workflows

Full workflow collection:

khanhduyvt0101/workflows


Setup Guide

Step 1: Get your PDF Vector API key

Sign up at https://www.pdfvector.com — free plan works for testing. Go to API Keys and generate a key.

Step 2: Set up your Google Sheet

Create a new spreadsheet with these exact headers in Row 1:


Shipment ID | Document Type | B/L Number | Shipper | Consignee | Route | Vessel | ETD | ETA | Days to Arrival | Containers | Container Count | Total Weight (kg) | HS Codes | Incoterms | Received Date

Copy the Sheet ID from the URL.

Step 3: Import the workflow

Download the JSON from GitHub and import into n8n via Import from File.

Step 4: Configure the nodes

Gmail Trigger:

  • Connect your Gmail account (OAuth2)

  • Add a label filter to limit to emails from your freight forwarder or carriers

Get a message:

  • Same Gmail credential

  • Downloads attachments automatically

PDF Vector - Extract Shipping:

  • Add new credential (Bearer Token type)

  • Paste your API key

  • Uses attachment_0 as the binary property — correct for Gmail attachments

Process Shipping Data:

  • No config needed — ETA calculation and status tagging happen automatically

Log to Shipment Tracker:

  • Connect Google Sheets

  • Paste your Sheet ID

Urgent - Arriving Soon (Slack):

  • Connect Slack

  • Paste your logistics channel ID

Notify Logistics Team (Slack):

  • Same Slack credential and channel

Step 5: Test it

Send yourself a test email with a Bill of Lading PDF attached. Check your Sheet and Slack after about 30 seconds.


Accuracy

Tested on Bills of Lading from major carriers (Maersk, MSC, CMA CGM, Evergreen) and freight forwarder packing lists.

  • B/L number, vessel, route: ~97% on digital PDFs

  • ETA and ETD dates: ~94% — handles most formats including DD/MM/YYYY and written dates

  • Container details: ~93% — container numbers and types extract reliably; seal numbers occasionally missed

  • HS codes: ~90% — reliable when clearly listed; misses codes embedded in description text

  • Weight and volume: ~95% on digital, drops to ~82% on scanned documents

Handwritten or stamped documents: accuracy drops significantly. Digital PDFs from carriers work best.

Cost

Each document uses about 3-4 PDF Vector credits. Free tier of 100 credits gets you roughly 25-30 documents per month.

Basic plan is $25/month for 3,000 credits if you’re processing volume.

Customizing it

Change the “arriving soon” threshold:

In the IF node condition, daysToArrival <= 3 is the trigger. Change 3 to 5 or 7 if you need more lead time for your operation.

Add Gmail label filter:

In the Gmail Trigger, add a label filter like “shipping” or filter by sender domain to avoid processing unrelated attachments.

Add customs clearance tracking:

After logging to Sheets, add a second sheet tab for customs status and update it via a separate manual trigger when clearance is confirmed.

Connect to a TMS or ERP:

Replace or supplement the Sheets node with an HTTP Request node to create shipment records in your transportation management system or ERP directly.

Handle multiple attachments:

If emails regularly contain multiple documents (B/L + packing list together), add a loop after “Get a message” to process each attachment separately.


Limitations

  • Requires self-hosted n8n (PDF Vector is a community node)

  • Watches all Gmail — add sender or label filters for production use

  • Only processes attachment_0 — emails with multiple attachments need additional handling

  • ETA calculation is point-in-time — doesn’t automatically update when carriers send revised ETAs

  • Doesn’t integrate with carrier tracking APIs for real-time status updates


Links


Questions? Drop a comment if something’s not working or you want to extend it for a specific carrier format.

truong you’re on a roll with these workflows. the ETA threshold routing is a nice touch — in logistics every day of warning matters. curious how it handles revised ETAs though — when a carrier sends an updated B/L with a different arrival date, does it overwrite the existing row or create a new entry? that’s usually where tracking gets messy.

Hey Benjamin :blush:

Red flag detection: AI-based, not rules. The prompt tells it to flag “potentially unfair clauses” - so it’s making judgment calls, not matching keywords.

Big limitation: It’s US-centric. The model doesn’t know DE/AT/CH tenant law. It’s applying generic “tenant advocacy” logic, which works okay for US leases but breaks down fast elsewhere.

To work cross-jurisdiction you’d need:

  • Country-specific prompts with local law references
  • Different thresholds per region

Right now it’s a sanity check tool, not legal compliance.

Are you building something for DACH region? Curious what lease terms are most problematic there.

ha Truong — i think this reply ended up in the wrong thread (the red flag detection / tenant law stuff sounds like your lease analyzer post). to loop back to the original question about the shipping doc processor: how does it handle revised ETAs from carriers? when Maersk sends an updated B/L with a different arrival date, does the workflow overwrite the existing row in Sheets or create a new entry? that’s usually where shipment tracking gets messy in practice.

the revised ETA thing is where most shipment trackers fall apart. we had this exact issue a while back. ended up adding a “find rows” step before the append, querying by B/L number, and just overwriting the ETA if the row already exists. also worth keeping an original ETA column that you only write on first insert, so you can see how much a shipment drifted. for multiple attachments, loop over items after the gmail node handles it fine since gmail indexes them as attachment_0, attachment_1, etc. just watch out for emails with a B/L and packing list together — youll get two rows for the same shipment, might need a dedup step.

omg yeah Benjamin, totally replied to the wrong thread. My bad :sweat_smile:

And thanks for actually answering your own question with the solution! The “find rows” before append is smart - way cleaner than creating duplicate entries.

The original ETA column idea is clutch too. Being able to see drift (“promised March 5, actually arrived March 19”) is super valuable for accountability with carriers.

Haven’t hit the multiple attachment issue yet but you’re right - B/L + packing list would create duplicates. Might add a filter checking document type before logging.

Appreciate you sharing the dedup approach. Saves me from having to figure it out the hard way.

the document type filter is the right call — otherwise youre logging duplicate rows for the same shipment and the tracker gets messy fast. might also be worth flagging Commercial Invoice separately since those often arrive weeks after the B/L and could throw off your arrival counts if youre tracking by document type.