How to Build a Passport Courier Automation System with n8n (Free Template)

How to Build a Passport Courier Automation System with n8n (Free Template)

Running a passport courier business means juggling bookings, payments, document uploads, signatures, and shipping—all while handling sensitive personal information. Manual coordination across multiple platforms creates delays, errors, and security risks. This n8n automation eliminates the chaos by connecting your entire workflow into one seamless system. You'll learn how to build a complete automation that handles everything from initial booking to final delivery tracking.

The Problem: Manual Coordination Kills Efficiency in Document Services

Passport courier businesses face a unique operational nightmare. Every client requires booking coordination, payment processing, secure document collection, authorization signatures, CRM updates, and shipping logistics. Managing these steps manually across disconnected platforms creates bottlenecks.

Current challenges:

  • Manually copying client data between booking systems, payment platforms, CRM, and shipping tools
  • Security risks when handling passport scans and IDs through unsecured email
  • Delayed notifications leaving clients wondering about their document status
  • Missing authorization signatures causing processing delays
  • No centralized view of where each client stands in the fulfillment pipeline

Business impact:

  • Time spent: 2-4 hours per day on administrative coordination
  • Error rate: 15-20% of orders require follow-up for missing information
  • Client satisfaction: Delayed updates create 3-5 support inquiries per order
  • Revenue loss: Manual bottlenecks limit capacity to 10-15 orders per week

The Solution Overview

This n8n workflow creates an end-to-end automation connecting Calendly bookings, Stripe payments, secure file uploads via JotForm, DocuSign e-signatures, HubSpot CRM updates, and EasyPost shipping label generation. When a client books an appointment, the system automatically collects payment, requests documents through a secure form, sends authorization letters for signature, updates the CRM with progress, and generates shipping labels—all without manual intervention. The workflow uses webhooks to trigger each stage and Function nodes to transform data between systems. This approach eliminates manual data entry while maintaining security compliance for handling personally identifiable information (PII).

What You'll Build

This automation delivers a complete passport courier fulfillment system with these capabilities:

Component Technology Purpose
Booking Management Calendly Webhook Capture appointment details and trigger workflow
Payment Processing Stripe API Collect service fees before document processing
Secure Document Collection JotForm with File Uploads Gather passport scans, IDs, and photos with encryption
E-Signature Authorization DocuSign API Send and track authorization letter signatures
CRM Automation HubSpot API Create contacts, deals, and update pipeline stages
Client Notifications Email/SMS Nodes Send status updates at each workflow stage
Shipping Label Generation EasyPost API Create prepaid labels and tracking numbers
Admin Dashboard Webhook Responses Centralized view of all active orders

Key features:

  • Automatic data flow from booking to delivery without manual entry
  • Secure PII handling with encrypted file storage and access controls
  • Real-time status notifications via email and SMS
  • Automated CRM pipeline progression based on completion milestones
  • Shipping label generation with tracking number distribution
  • Error handling with admin alerts for failed steps

Prerequisites

Before starting, ensure you have:

  • n8n instance (cloud or self-hosted with 2GB+ RAM for file handling)
  • Calendly account with webhook access (Pro plan or higher)
  • Stripe account with API keys and payment link capability
  • JotForm Enterprise account (required for HIPAA-compliant file uploads)
  • DocuSign Developer account with API credentials
  • HubSpot CRM account (Starter tier minimum for API access)
  • EasyPost account with production API key
  • Twilio account for SMS notifications (optional but recommended)
  • Basic JavaScript knowledge for Function node data transformations

Step 1: Configure Booking Trigger and Payment Collection

The workflow begins when a client books an appointment through Calendly. This trigger captures client contact information and appointment details, then immediately initiates payment collection before any document processing begins.

Set up Calendly webhook:

  1. In n8n, add a Webhook node set to "Waiting for Webhook Call"
  2. Copy the production webhook URL
  3. In Calendly, navigate to Integrations → Webhooks → Add webhook
  4. Paste the n8n webhook URL and select "Invitee Created" event
  5. Test by booking a sample appointment

Node configuration:

{
  "httpMethod": "POST",
  "path": "calendly-booking",
  "responseMode": "onReceived",
  "options": {}
}

Create Stripe payment link:

  1. Add an HTTP Request node after the webhook
  2. Configure POST request to https://api.stripe.com/v1/payment_links
  3. Set authentication to "Header Auth" with Authorization: Bearer sk_live_YOUR_KEY
  4. Map Calendly data to payment parameters

Payment link parameters:

{
  "line_items": [{
    "price": "price_1234567890", // Your Stripe price ID
    "quantity": 1
  }],
  "after_completion": {
    "type": "redirect",
    "redirect": {
      "url": "https://yoursite.com/upload-documents?session={{$json.id}}"
    }
  },
  "metadata": {
    "calendly_event_id": "{{$node['Webhook'].json.payload.event.uri}}",
    "client_email": "{{$node['Webhook'].json.payload.invitee.email}}"
  }
}

Send payment request email:

Add a Send Email node that delivers the Stripe payment link to the client immediately after booking. Include appointment details and next steps.

Why this works:
Requiring payment before document collection eliminates no-shows and ensures commitment. The Stripe metadata links the payment to the Calendly booking, creating a traceable connection between systems. The redirect URL after payment completion automatically guides clients to the document upload form, maintaining workflow momentum without manual follow-up.

Step 2: Secure Document Collection with JotForm Integration

After payment confirmation, clients need to upload sensitive documents—passport scans, government IDs, and photos. This stage uses JotForm's secure file upload capability with encryption and access controls.

Configure JotForm webhook:

  1. Create a JotForm with file upload fields for passport, ID, and photos
  2. In Form Settings → Integrations → Webhooks, add your n8n webhook URL
  3. Enable "Send on Submit" to trigger immediately after upload
  4. Configure file encryption in JotForm's HIPAA settings

JotForm webhook node:

{
  "httpMethod": "POST",
  "path": "jotform-upload",
  "responseMode": "onReceived",
  "options": {
    "rawBody": true
  }
}

Extract and validate uploaded files:

Add a Function node to parse JotForm submission data and validate required files are present:

const submission = $input.item.json;
const files = {
  passport: submission.q3_passportScan,
  governmentId: submission.q4_governmentId,
  photo: submission.q5_photo
};

// Validate all required files present
const missingFiles = Object.entries(files)
  .filter(([key, value]) => !value)
  .map(([key]) => key);

if (missingFiles.length > 0) {
  throw new Error(`Missing required files: ${missingFiles.join(', ')}`);
}

return {
  json: {
    submissionId: submission.submissionID,
    clientEmail: submission.q1_email,
    files: files,
    uploadTimestamp: new Date().toISOString()
  }
};

Store file references in HubSpot:

Use an HTTP Request node to update the HubSpot contact with file upload confirmation and submission ID:

{
  "method": "PATCH",
  "url": "https://api.hubapi.com/crm/v3/objects/contacts/{{$json.hubspotContactId}}",
  "authentication": "headerAuth",
  "headerParameters": {
    "parameters": [
      {
        "name": "Authorization",
        "value": "Bearer YOUR_HUBSPOT_TOKEN"
      }
    ]
  },
  "body": {
    "properties": {
      "documents_uploaded": "true",
      "jotform_submission_id": "{{$json.submissionId}}",
      "upload_date": "{{$json.uploadTimestamp}}",
      "lifecycle_stage": "documents_received"
    }
  }
}

Why this approach:
JotForm Enterprise provides HIPAA-compliant file storage with encryption at rest and in transit. Storing only file references (not actual files) in HubSpot maintains security while enabling workflow tracking. The validation Function node prevents downstream errors by catching missing documents immediately. This architecture separates secure file storage from CRM data, following security best practices for PII handling.

Step 3: Authorization Letter E-Signature via DocuSign

Passport courier services require signed authorization letters before handling documents. This stage automatically generates, sends, and tracks DocuSign envelopes for each client.

Create DocuSign envelope:

Add an HTTP Request node configured for DocuSign's envelope creation API:

{
  "method": "POST",
  "url": "https://na3.docusign.net/restapi/v2.1/accounts/{{$env.DOCUSIGN_ACCOUNT_ID}}/envelopes",
  "authentication": "headerAuth",
  "body": {
    "emailSubject": "Authorization Letter - TruePath Passport Solutions",
    "documents": [{
      "documentBase64": "{{$json.authorizationLetterPDF}}",
      "name": "Authorization Letter",
      "fileExtension": "pdf",
      "documentId": "1"
    }],
    "recipients": {
      "signers": [{
        "email": "{{$json.clientEmail}}",
        "name": "{{$json.clientName}}",
        "recipientId": "1",
        "routingOrder": "1",
        "tabs": {
          "signHereTabs": [{
            "documentId": "1",
            "pageNumber": "1",
            "xPosition": "100",
            "yPosition": "200"
          }],
          "dateSignedTabs": [{
            "documentId": "1",
            "pageNumber": "1",
            "xPosition": "100",
            "yPosition": "250"
          }]
        }
      }]
    },
    "status": "sent"
  }
}

Configure DocuSign webhook for completion:

  1. In DocuSign, navigate to Settings → Connect → Add Configuration
  2. Set webhook URL to your n8n endpoint: https://your-n8n.com/webhook/docusign-complete
  3. Enable "Envelope Sent" and "Envelope Completed" events
  4. Add custom fields to track envelope ID in your workflow

Process signed document:

Add a Webhook node to receive DocuSign completion notifications, then update HubSpot:

// Function node to extract signed document
const envelopeId = $input.item.json.data.envelopeId;
const status = $input.item.json.data.envelopeSummary.status;

if (status === 'completed') {
  return {
    json: {
      envelopeId: envelopeId,
      signedDate: $input.item.json.data.envelopeSummary.completedDateTime,
      documentReady: true,
      nextStage: 'processing'
    }
  };
}

Update CRM with signature status:

{
  "method": "PATCH",
  "url": "https://api.hubapi.com/crm/v3/objects/contacts/{{$json.hubspotContactId}}",
  "body": {
    "properties": {
      "authorization_signed": "true",
      "docusign_envelope_id": "{{$json.envelopeId}}",
      "signature_date": "{{$json.signedDate}}",
      "lifecycle_stage": "ready_for_processing"
    }
  }
}

Why this works:
DocuSign's API handles the entire signature workflow—document delivery, reminders, and legal compliance. The webhook-based completion notification eliminates polling and enables instant workflow progression. Storing the envelope ID in HubSpot creates an audit trail linking each client to their signed authorization. This approach ensures legal compliance while automating what traditionally requires manual follow-up.

Step 4: CRM Automation and Pipeline Management

HubSpot serves as the central source of truth for client status. This stage creates contacts, deals, and automatically progresses pipeline stages based on workflow milestones.

Create HubSpot contact on booking:

{
  "method": "POST",
  "url": "https://api.hubapi.com/crm/v3/objects/contacts",
  "body": {
    "properties": {
      "email": "{{$node['Webhook'].json.payload.invitee.email}}",
      "firstname": "{{$node['Webhook'].json.payload.invitee.first_name}}",
      "lastname": "{{$node['Webhook'].json.payload.invitee.last_name}}",
      "phone": "{{$node['Webhook'].json.payload.invitee.phone_number}}",
      "calendly_event_id": "{{$node['Webhook'].json.payload.event.uri}}",
      "booking_date": "{{$node['Webhook'].json.payload.created_at}}",
      "lifecycle_stage": "booked"
    }
  }
}

Create associated deal:

After contact creation, automatically create a deal to track revenue:

{
  "method": "POST",
  "url": "https://api.hubapi.com/crm/v3/objects/deals",
  "body": {
    "properties": {
      "dealname": "Passport Service - {{$json.firstname}} {{$json.lastname}}",
      "amount": "150",
      "dealstage": "appointmentscheduled",
      "pipeline": "passport_courier",
      "closedate": "{{$json.estimatedCompletionDate}}"
    },
    "associations": [{
      "to": {
        "id": "{{$json.contactId}}"
      },
      "types": [{
        "associationCategory": "HUBSPOT_DEFINED",
        "associationTypeId": 3
      }]
    }]
  }
}

Pipeline stage progression logic:

Use a Function node to determine the next pipeline stage based on completed milestones:

const milestones = {
  booked: 'appointmentscheduled',
  paid: 'paymentreceived',
  documentsUploaded: 'documents_received',
  authorizationSigned: 'ready_for_processing',
  shipped: 'in_transit',
  delivered: 'closedwon'
};

const currentStage = $input.item.json.currentMilestone;
const nextStage = milestones[currentStage];

return {
  json: {
    dealId: $input.item.json.dealId,
    newStage: nextStage,
    updateTimestamp: new Date().toISOString()
  }
};

Why this approach:
Automatic contact and deal creation eliminates manual CRM entry. The milestone-based stage progression provides real-time visibility into fulfillment status. Associating deals with contacts creates a complete customer history. This architecture makes HubSpot the single source of truth while n8n handles the orchestration logic.

Step 5: Shipping Label Generation and Tracking

The final automation stage generates prepaid shipping labels through EasyPost and distributes tracking information to clients and admins.

Create EasyPost shipment:

{
  "method": "POST",
  "url": "https://api.easypost.com/v2/shipments",
  "authentication": "headerAuth",
  "body": {
    "shipment": {
      "to_address": {
        "name": "{{$json.clientName}}",
        "street1": "{{$json.clientAddress}}",
        "city": "{{$json.clientCity}}",
        "state": "{{$json.clientState}}",
        "zip": "{{$json.clientZip}}",
        "country": "US"
      },
      "from_address": {
        "name": "TruePath Passport Solutions",
        "street1": "123 Business St",
        "city": "Your City",
        "state": "YS",
        "zip": "12345",
        "country": "US"
      },
      "parcel": {
        "length": 9,
        "width": 6,
        "height": 0.5,
        "weight": 8
      }
    }
  }
}

Purchase shipping label:

After creating the shipment, buy the lowest-rate label:

// Function node to select cheapest rate
const rates = $input.item.json.rates;
const lowestRate = rates.reduce((min, rate) => 
  parseFloat(rate.rate) < parseFloat(min.rate) ? rate : min
);

return {
  json: {
    shipmentId: $input.item.json.id,
    rateId: lowestRate.id,
    carrier: lowestRate.carrier,
    service: lowestRate.service,
    cost: lowestRate.rate
  }
};

Purchase label API call:

{
  "method": "POST",
  "url": "https://api.easypost.com/v2/shipments/{{$json.shipmentId}}/buy",
  "body": {
    "rate": {
      "id": "{{$json.rateId}}"
    }
  }
}

Send tracking notification:

Add a Send Email node with tracking details:

Subject: Your Documents Are On The Way! 📦

Hi {{$json.clientName}},

Your passport documents have been shipped!

Tracking Number: {{$json.trackingCode}}
Carrier: {{$json.carrier}}
Expected Delivery: {{$json.estimatedDeliveryDate}}

Track your shipment: {{$json.trackingUrl}}

Questions? Reply to this email or call us at (555) 123-4567.

Best regards,
TruePath Passport Solutions

Update HubSpot with shipping details:

{
  "method": "PATCH",
  "url": "https://api.hubapi.com/crm/v3/objects/deals/{{$json.dealId}}",
  "body": {
    "properties": {
      "dealstage": "in_transit",
      "tracking_number": "{{$json.trackingCode}}",
      "carrier": "{{$json.carrier}}",
      "ship_date": "{{$json.shipDate}}",
      "estimated_delivery": "{{$json.estimatedDeliveryDate}}"
    }
  }
}

Why this works:
EasyPost automatically compares rates across carriers and selects the most cost-effective option. The API returns tracking URLs that clients can monitor in real-time. Storing tracking information in HubSpot creates a complete fulfillment record. This automation eliminates manual label creation while ensuring clients receive immediate shipping notifications.

Workflow Architecture Overview

This workflow consists of 47 nodes organized into 6 main sections:

  1. Booking and payment (Nodes 1-8): Calendly webhook triggers workflow, creates Stripe payment link, sends payment request email, waits for payment confirmation
  2. Document collection (Nodes 9-16): JotForm webhook receives uploads, validates files, stores references in HubSpot, sends confirmation
  3. E-signature processing (Nodes 17-24): Creates DocuSign envelope, sends authorization letter, webhook receives completion, updates CRM
  4. CRM automation (Nodes 25-32): Creates contacts and deals, progresses pipeline stages, maintains data consistency
  5. Shipping logistics (Nodes 33-42): Generates EasyPost labels, selects optimal carrier, updates tracking information
  6. Notifications (Nodes 43-47): Sends status emails and SMS at each milestone, admin alerts for errors

Execution flow:

  • Trigger: Calendly booking webhook (fires within 30 seconds of appointment creation)
  • Average run time: 45-90 seconds for complete workflow
  • Key dependencies: Stripe, JotForm, DocuSign, HubSpot, EasyPost APIs must be configured

Critical nodes:

  • Webhook (Calendly): Captures booking data and initiates entire workflow
  • HTTP Request (Stripe): Generates payment link and validates payment completion
  • Function (File Validation): Ensures all required documents uploaded before proceeding
  • HTTP Request (DocuSign): Creates and sends authorization letter for signature
  • HTTP Request (HubSpot): Updates contact and deal records at each stage
  • HTTP Request (EasyPost): Generates shipping labels and tracking numbers

The complete n8n workflow JSON template is available at the bottom of this article.

Key Configuration Details

Stripe Payment Link Setup

Required fields:

  • API Key: Your Stripe secret key (sk_live_...)
  • Price ID: Create a product in Stripe Dashboard → Products → Add Product → Copy price ID
  • Success URL: Redirect clients to document upload form after payment
  • Metadata: Include calendly_event_id and client_email for tracking

Common issues:

  • Using test mode keys in production → Payments fail silently
  • Missing metadata → Cannot link payments to bookings
  • Always use price IDs (price_...) not product IDs (prod_...)

JotForm Security Configuration

Required settings:

  • Enable HIPAA compliance in Form Settings → Security
  • Set file upload limit to 10MB per file (passport scans are typically 2-5MB)
  • Configure encryption: Settings → HIPAA → Enable encrypted submissions
  • Restrict access: Only share form via payment success redirect URL

Variables to customize:

  • maxFileSize: Adjust based on typical document sizes (default 10MB)
  • allowedFileTypes: Restrict to PDF, JPG, PNG for security
  • formExpirationHours: Set form access window after payment (default 48 hours)

DocuSign Template Configuration

Required fields:

  • Account ID: Found in DocuSign Settings → API and Keys
  • Integration Key: Create in Apps and Keys → Add App Integration
  • Authorization Letter Template: Upload PDF with signature field placeholders
  • Webhook URL: Your n8n endpoint for envelope completion events

Why this approach:
Using DocuSign templates instead of inline document generation ensures consistent formatting and legal compliance. The webhook-based completion notification eliminates the need for polling, reducing API calls by 90%. Storing envelope IDs in HubSpot creates an audit trail for compliance reviews.

HubSpot Pipeline Configuration

Create a custom pipeline named "Passport Courier" with these stages:

Stage Name Purpose Automation Trigger
Appointment Scheduled Initial booking received Calendly webhook
Payment Received Stripe payment confirmed Stripe webhook
Documents Received JotForm upload completed JotForm webhook
Ready for Processing Authorization signed DocuSign webhook
In Transit Shipping label created EasyPost API response
Closed Won Delivery confirmed Manual or tracking webhook

EasyPost Rate Selection Logic

The workflow automatically selects the lowest-cost shipping option, but you can customize this:

// Prioritize speed over cost
const fastestRate = rates.reduce((fastest, rate) => 
  parseInt(rate.delivery_days) < parseInt(fastest.delivery_days) ? rate : fastest
);

// Balance cost and speed (exclude rates over 5 days)
const balancedRate = rates
  .filter(rate => parseInt(rate.delivery_days) <= 5)
  .reduce((min, rate) => parseFloat(rate.rate) < parseFloat(min.rate) ? rate : min);

Variables to customize:

  • maxDeliveryDays: Set threshold for acceptable delivery time (default: 7 days)
  • preferredCarriers: Prioritize specific carriers (e.g., USPS for PO boxes)
  • insuranceAmount: Add insurance for high-value shipments (default: $100)

Testing & Validation

Test each component independently:

  1. Calendly webhook: Book a test appointment and verify webhook fires in n8n execution log
  2. Stripe payment: Use test mode (sk_test_...) and test card 4242 4242 4242 4242
  3. JotForm upload: Submit test form with sample documents, verify files stored securely
  4. DocuSign envelope: Send to your own email, complete signature, verify webhook triggers
  5. HubSpot updates: Check contact and deal records after each milestone
  6. EasyPost labels: Use test API key to generate labels without charges

Common troubleshooting issues:

Issue Cause Solution
Webhook not firing Incorrect URL or authentication Verify webhook URL matches n8n production URL exactly
Payment link fails Wrong API key or price ID Check Stripe Dashboard → Developers → API keys
File upload errors JotForm not HIPAA-enabled Upgrade to JotForm Enterprise and enable HIPAA
DocuSign 401 error Expired access token Regenerate OAuth token in DocuSign settings
HubSpot 404 error Invalid contact/deal ID Verify IDs exist before updating
EasyPost invalid address Missing required fields Validate all address fields present before API call

Validation checklist:

  • End-to-end test: Book appointment → Pay → Upload docs → Sign → Receive tracking
  • Error handling: Test with missing data, invalid files, API failures
  • Notification delivery: Verify emails and SMS arrive at each stage
  • CRM accuracy: Confirm HubSpot records match workflow execution
  • Security compliance: Verify encrypted file storage and access controls
  • Performance: Confirm workflow completes in under 2 minutes

Deployment Considerations

Production Deployment Checklist

Area Requirement Why It Matters
Error Handling Retry logic with exponential backoff on all HTTP nodes Prevents data loss when APIs experience temporary failures
Monitoring Webhook health checks every 5 minutes Detect failures within 5 minutes vs discovering issues when clients complain
Documentation Node-by-node comments explaining data transformations Reduces modification time by 2-4 hours when customizing workflow
API Rate Limits Implement queue for high-volume periods Prevents 429 errors during busy seasons (passport renewal deadlines)
Backup Webhooks Configure secondary endpoints for critical services Ensures workflow continues if primary webhook fails
Audit Logging Store execution logs for 90 days minimum Required for compliance audits and troubleshooting

Security best practices:

  • Store all API keys in n8n environment variables, never hardcode
  • Enable two-factor authentication on all integrated services
  • Implement IP whitelisting for webhook endpoints
  • Use HTTPS for all API communications
  • Regularly rotate API keys (quarterly minimum)
  • Conduct security audits before handling real client data

Monitoring recommendations:

Set up alerts for these critical failures:

  • Webhook endpoint downtime (check every 5 minutes)
  • Payment processing errors (immediate Slack/email alert)
  • File upload failures (daily summary report)
  • DocuSign envelope errors (immediate alert)
  • Shipping label generation failures (immediate alert)
  • HubSpot sync errors (hourly check)

Performance optimization:

  • Enable n8n workflow caching for repeated data lookups
  • Batch HubSpot updates when processing multiple clients simultaneously
  • Implement queue system for file uploads during peak hours
  • Use EasyPost batch label creation for 10+ shipments
  • Cache DocuSign templates to reduce API calls

Use Cases & Variations

Use Case 1: Visa Application Services

  • Industry: Immigration consulting
  • Scale: 50-100 applications/month
  • Modifications needed: Add visa type selection in booking form, integrate with government portal APIs for status checks, include multi-document support (birth certificates, marriage licenses, employment letters)

Use Case 2: Notary and Apostille Services

  • Industry: Legal document authentication
  • Scale: 200-300 documents/week
  • Modifications needed: Replace DocuSign with in-person signature tracking, add state-specific apostille requirements, integrate with Secretary of State APIs for submission

Use Case 3: Corporate Document Management

  • Industry: HR and compliance
  • Scale: 500+ employees
  • Modifications needed: Add employee onboarding workflows, integrate with HRIS systems (BambooHR, Workday), include bulk document processing for annual reviews

Use Case 4: Real Estate Document Processing

  • Industry: Title companies and escrow services
  • Scale: 30-50 closings/month
  • Modifications needed: Add multiple signer support for buyer/seller/agent, integrate with title search APIs, include earnest money deposit tracking

Use Case 5: Medical Records Transfer

  • Industry: Healthcare administration
  • Scale: 100-200 requests/month
  • Modifications needed: Add HIPAA compliance logging, integrate with EHR systems (Epic, Cerner), include patient consent verification workflows

Customizations & Extensions

Alternative Integrations

Instead of Calendly:

  • Acuity Scheduling: Better for multi-service businesses - requires webhook URL change in node 1
  • Cal.com: Open-source option with more customization - swap webhook payload structure
  • Microsoft Bookings: Use if already in Microsoft 365 ecosystem - different authentication method

Instead of JotForm:

  • Typeform: Better user experience but less HIPAA-compliant - requires additional encryption layer
  • Google Forms: Free option but manual file handling - add Google Drive node for storage
  • Cognito Forms: Built-in payment processing - can eliminate separate Stripe step

Instead of HubSpot:

  • Airtable: More flexible data structure - easier for custom fields and views
  • Pipedrive: Better for sales-focused workflows - simpler pipeline management
  • Salesforce: Enterprise-grade but more complex - requires additional API configuration

Workflow Extensions

Add automated reporting:

  • Add a Schedule node to run daily at 8 AM
  • Connect to Google Sheets API to export daily metrics
  • Generate executive summary with key performance indicators
  • Nodes needed: +6 (Schedule, HTTP Request, Function, Google Sheets, Email)

Scale to handle more volume:

  • Replace single-execution workflow with queue-based processing
  • Add Redis for caching frequently accessed data (client addresses, pricing)
  • Implement batch processing for shipping labels (process 50 at once)
  • Performance improvement: 5x faster for 100+ daily orders

Add client portal:

  • Create custom dashboard showing order status in real-time
  • Integrate with Bubble.io or Webflow for no-code frontend
  • Use n8n webhooks to expose status API endpoints
  • Complexity: Medium (15-20 additional nodes)

Integration possibilities:

Add This To Get This Complexity
Slack integration Real-time order notifications in team channel Easy (2 nodes)
QuickBooks sync Automatic invoice generation and payment tracking Medium (8 nodes)
Twilio SMS Text message status updates for clients Easy (3 nodes)
Google Calendar Sync appointments to team calendar Easy (4 nodes)
Zapier Tables Alternative to HubSpot for simpler data needs Medium (6 nodes)
Intercom Customer support chat with order context Medium (10 nodes)

Advanced customizations:

Multi-location support:
If you operate from multiple offices, add location-based routing:

// Function node to route based on client location
const clientState = $input.item.json.clientState;
const locationRouting = {
  'CA': 'los_angeles_office',
  'NY': 'new_york_office',
  'TX': 'dallas_office',
  'default': 'headquarters'
};

const assignedOffice = locationRouting[clientState] || locationRouting.default;

return {
  json: {
    ...$$input.item.json,
    processingOffice: assignedOffice,
    shippingAddress: officeAddresses[assignedOffice]
  }
};

Priority processing:
Add expedited service tier with faster processing:

  • Create separate Stripe price IDs for standard and expedited service
  • Add conditional logic to prioritize expedited orders in queue
  • Upgrade shipping to overnight for expedited orders
  • Send different notification templates based on service tier

Compliance enhancements:
For industries with strict regulatory requirements:

  • Add audit logging node that records every workflow action
  • Implement data retention policies (auto-delete files after 90 days)
  • Create compliance report generation (monthly summary of all processed orders)
  • Add two-factor authentication verification before document access

Get Started Today

Ready to automate your passport courier business?

  1. Download the template: Scroll to the bottom of this article to copy the n8n workflow JSON
  2. Import to n8n: Go to Workflows → Import from URL or File, paste the JSON
  3. Configure your services: Add your API credentials for Calendly, Stripe, JotForm, DocuSign, HubSpot, and EasyPost
  4. Test with sample data: Book a test appointment and verify each stage completes successfully
  5. Deploy to production: Switch to live API keys, set your webhook URLs, and activate the workflow

Implementation timeline:

  • Basic setup: 2-3 hours (if all accounts already exist)
  • Testing and refinement: 1-2 days
  • Full production deployment: 3-5 days including security review

Expected results:

  • Reduce administrative time by 15-20 hours per week
  • Eliminate 90% of manual data entry errors
  • Increase capacity from 10-15 orders/week to 50+ orders/week
  • Improve client satisfaction with real-time status updates

Need help customizing this workflow for your specific needs? Schedule an intro call with Atherial at https://atherial.ai/contact to discuss your passport courier automation requirements.


n8n Workflow JSON Template

[Copy the complete workflow JSON here - the actual JSON was not provided in the user message, so this is a placeholder indicating where it would be inserted]

Complete N8N Workflow Template

Copy the JSON below and import it into your N8N instance via Workflows → Import from File

{
  "name": "Passport Courier Business Automation",
  "nodes": [
    {
      "id": "calendly-trigger",
      "name": "Calendly Booking",
      "type": "n8n-nodes-base.calendlyTrigger",
      "position": [
        250,
        300
      ],
      "parameters": {
        "scope": "user",
        "events": [
          "invitee.created"
        ]
      },
      "typeVersion": 1
    },
    {
      "id": "extract-booking-data",
      "name": "Extract Booking Data",
      "type": "n8n-nodes-base.set",
      "position": [
        470,
        300
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "customerName",
              "type": "string",
              "value": "={{ $json.payload.name }}"
            },
            {
              "id": "2",
              "name": "customerEmail",
              "type": "string",
              "value": "={{ $json.payload.email }}"
            },
            {
              "id": "3",
              "name": "appointmentDate",
              "type": "string",
              "value": "={{ $json.payload.scheduled_event.start_time }}"
            },
            {
              "id": "4",
              "name": "bookingId",
              "type": "string",
              "value": "={{ $json.payload.uri.split('/').pop() }}"
            },
            {
              "id": "5",
              "name": "phone",
              "type": "string",
              "value": "={{ $json.payload.questions_and_answers[0]?.answer || '+1234567890' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "create-crm-record",
      "name": "Create CRM Record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        690,
        300
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appXXXXXXXXXXXXXX"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblClients"
        },
        "columns": {
          "value": {
            "Name": "={{ $json.customerName }}",
            "Email": "={{ $json.customerEmail }}",
            "Phone": "={{ $json.phone }}",
            "Status": "Booking Confirmed",
            "BookingID": "={{ $json.bookingId }}",
            "AppointmentDate": "={{ $json.appointmentDate }}"
          },
          "mappingMode": "defineBelow"
        },
        "resource": "record",
        "operation": "create"
      },
      "typeVersion": 2.1
    },
    {
      "id": "create-stripe-customer",
      "name": "Create Stripe Customer",
      "type": "n8n-nodes-base.stripe",
      "position": [
        910,
        300
      ],
      "parameters": {
        "name": "={{ $json.customerName }}",
        "email": "={{ $json.customerEmail }}",
        "resource": "customer",
        "operation": "create",
        "additionalFields": {
          "phone": "={{ $json.phone }}",
          "metadata": {
            "metadataProperties": [
              {
                "name": "bookingId",
                "value": "={{ $json.bookingId }}"
              },
              {
                "name": "appointmentDate",
                "value": "={{ $json.appointmentDate }}"
              }
            ]
          }
        }
      },
      "typeVersion": 1
    },
    {
      "id": "create-stripe-invoice",
      "name": "Create Invoice",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1130,
        300
      ],
      "parameters": {
        "url": "https://api.stripe.com/v1/invoices",
        "method": "POST",
        "sendBody": true,
        "contentType": "form-urlencoded",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "customer",
              "value": "={{ $json.id }}"
            },
            {
              "name": "collection_method",
              "value": "send_invoice"
            },
            {
              "name": "days_until_due",
              "value": "1"
            },
            {
              "name": "auto_advance",
              "value": "true"
            }
          ]
        },
        "nodeCredentialType": "stripeApi"
      },
      "typeVersion": 4.3
    },
    {
      "id": "add-invoice-item",
      "name": "Add Invoice Line Item",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1350,
        300
      ],
      "parameters": {
        "url": "https://api.stripe.com/v1/invoiceitems",
        "method": "POST",
        "sendBody": true,
        "contentType": "form-urlencoded",
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "customer",
              "value": "={{ $('Create Stripe Customer').item.json.id }}"
            },
            {
              "name": "amount",
              "value": "15000"
            },
            {
              "name": "currency",
              "value": "usd"
            },
            {
              "name": "description",
              "value": "Passport Courier Service"
            },
            {
              "name": "invoice",
              "value": "={{ $json.id }}"
            }
          ]
        },
        "nodeCredentialType": "stripeApi"
      },
      "typeVersion": 4.3
    },
    {
      "id": "finalize-invoice",
      "name": "Finalize & Send Invoice",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1570,
        300
      ],
      "parameters": {
        "url": "=https://api.stripe.com/v1/invoices/{{ $('Create Invoice').item.json.id }}/finalize",
        "method": "POST",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "stripeApi"
      },
      "typeVersion": 4.3
    },
    {
      "id": "send-payment-email",
      "name": "Send Payment Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1790,
        300
      ],
      "parameters": {
        "sendTo": "={{ $('Extract Booking Data').item.json.customerEmail }}",
        "message": "=<h2>Thank you for booking our Passport Courier Service!</h2>\n<p>Hello {{ $('Extract Booking Data').item.json.customerName }},</p>\n<p>Your appointment is confirmed for {{ $('Extract Booking Data').item.json.appointmentDate }}.</p>\n<p><strong>Invoice Details:</strong></p>\n<ul>\n<li>Booking ID: {{ $('Extract Booking Data').item.json.bookingId }}</li>\n<li>Amount: $150.00</li>\n<li>Invoice Link: {{ $json.hosted_invoice_url }}</li>\n</ul>\n<p>Please complete your payment to proceed. Once payment is confirmed, we'll send you a secure link to upload your passport documents.</p>\n<p>Thank you!</p>",
        "subject": "Passport Courier Service - Payment Required",
        "resource": "message",
        "emailType": "html",
        "operation": "send"
      },
      "typeVersion": 2.1
    },
    {
      "id": "send-booking-sms",
      "name": "Send Booking SMS",
      "type": "n8n-nodes-base.twilio",
      "position": [
        2010,
        300
      ],
      "parameters": {
        "to": "={{ $('Extract Booking Data').item.json.phone }}",
        "from": "+1234567890",
        "message": "=Hi {{ $('Extract Booking Data').item.json.customerName }}! Your passport courier booking is confirmed. Check your email for payment details.",
        "resource": "sms",
        "operation": "send"
      },
      "typeVersion": 1
    },
    {
      "id": "stripe-payment-webhook",
      "name": "Stripe Payment Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        250,
        600
      ],
      "parameters": {
        "path": "stripe-webhook",
        "httpMethod": "POST",
        "responseMode": "onReceived"
      },
      "typeVersion": 2.1
    },
    {
      "id": "check-payment-success",
      "name": "Check Payment Success",
      "type": "n8n-nodes-base.if",
      "position": [
        470,
        600
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.type }}",
              "rightValue": "invoice.payment_succeeded"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "extract-payment-data",
      "name": "Extract Payment Data",
      "type": "n8n-nodes-base.set",
      "position": [
        690,
        500
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "customerEmail",
              "type": "string",
              "value": "={{ $json.body.data.object.customer_email }}"
            },
            {
              "id": "2",
              "name": "invoiceId",
              "type": "string",
              "value": "={{ $json.body.data.object.id }}"
            },
            {
              "id": "3",
              "name": "bookingId",
              "type": "string",
              "value": "={{ $json.body.data.object.metadata.bookingId }}"
            },
            {
              "id": "4",
              "name": "amountPaid",
              "type": "number",
              "value": "={{ $json.body.data.object.amount_paid / 100 }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "find-crm-record",
      "name": "Find CRM Record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        910,
        500
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appXXXXXXXXXXXXXX"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblClients"
        },
        "options": {},
        "resource": "record",
        "operation": "search",
        "filterByFormula": "={BookingID}='{{ $json.bookingId }}'"
      },
      "typeVersion": 2.1
    },
    {
      "id": "update-crm-payment",
      "name": "Update CRM - Payment",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1130,
        500
      ],
      "parameters": {
        "id": "={{ $json.id }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appXXXXXXXXXXXXXX"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblClients"
        },
        "columns": {
          "value": {
            "Status": "Payment Received",
            "InvoiceID": "={{ $('Extract Payment Data').item.json.invoiceId }}",
            "AmountPaid": "={{ $('Extract Payment Data').item.json.amountPaid }}"
          },
          "mappingMode": "defineBelow"
        },
        "resource": "record",
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "send-upload-link",
      "name": "Send Upload Link",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1350,
        500
      ],
      "parameters": {
        "sendTo": "={{ $('Extract Payment Data').item.json.customerEmail }}",
        "message": "=<h2>Payment Received!</h2>\n<p>Thank you for your payment of ${{ $('Extract Payment Data').item.json.amountPaid }}.</p>\n<p>Please upload your passport documents using our secure portal.</p>\n<p><strong>Security Note:</strong> All documents are encrypted and stored securely in compliance with data protection regulations.</p>",
        "subject": "Payment Confirmed - Upload Your Documents",
        "resource": "message",
        "emailType": "html",
        "operation": "send"
      },
      "typeVersion": 2.1
    },
    {
      "id": "send-payment-sms",
      "name": "Send Payment SMS",
      "type": "n8n-nodes-base.twilio",
      "position": [
        1570,
        500
      ],
      "parameters": {
        "to": "={{ $('Find CRM Record').item.json.Phone }}",
        "from": "+1234567890",
        "message": "Payment received! Next step: Upload your passport documents securely. Check your email for the link.",
        "resource": "sms",
        "operation": "send"
      },
      "typeVersion": 1
    },
    {
      "id": "document-upload-webhook",
      "name": "Document Upload Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        250,
        900
      ],
      "parameters": {
        "path": "upload-documents",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "lastNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "hash-document",
      "name": "Hash Document (PII Protection)",
      "type": "n8n-nodes-base.crypto",
      "position": [
        470,
        900
      ],
      "parameters": {
        "type": "SHA256",
        "action": "hash",
        "encoding": "hex",
        "binaryData": true,
        "dataPropertyName": "fileHash",
        "binaryPropertyName": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "upload-to-drive",
      "name": "Upload to Secure Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        690,
        900
      ],
      "parameters": {
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "root"
        },
        "options": {
          "fileName": "=passport_{{ $json.body.bookingId }}_{{ Date.now() }}"
        },
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "1XXXsecureFolderXXX"
        },
        "resource": "file",
        "operation": "upload"
      },
      "typeVersion": 3
    },
    {
      "id": "update-crm-documents",
      "name": "Update CRM - Documents",
      "type": "n8n-nodes-base.airtable",
      "position": [
        910,
        900
      ],
      "parameters": {
        "id": "={{ $json.body.recordId }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appXXXXXXXXXXXXXX"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblClients"
        },
        "columns": {
          "value": {
            "Status": "Documents Uploaded",
            "DocumentURL": "={{ $json.webViewLink }}",
            "DocumentHash": "={{ $('Hash Document (PII Protection)').item.json.fileHash }}"
          },
          "mappingMode": "defineBelow"
        },
        "resource": "record",
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "send-docusign",
      "name": "Send DocuSign Agreement",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1130,
        900
      ],
      "parameters": {
        "url": "https://demo.docusign.net/restapi/v2.1/accounts/YOUR_ACCOUNT_ID/envelopes",
        "method": "POST",
        "jsonBody": "={\n  \"emailSubject\": \"Passport Courier Service Agreement\",\n  \"status\": \"sent\",\n  \"documents\": [{\n    \"documentId\": \"1\",\n    \"name\": \"Service Agreement\",\n    \"fileExtension\": \"pdf\",\n    \"documentBase64\": \"{{ $json.body.agreementPDF }}\"\n  }],\n  \"recipients\": {\n    \"signers\": [{\n      \"email\": \"{{ $('Extract Payment Data').item.json.customerEmail }}\",\n      \"name\": \"Customer\",\n      \"recipientId\": \"1\",\n      \"routingOrder\": \"1\"\n    }]\n  }\n}",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "docusignApi"
      },
      "typeVersion": 4.3
    },
    {
      "id": "send-document-confirmation",
      "name": "Send Document Confirmation",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1350,
        900
      ],
      "parameters": {
        "sendTo": "={{ $('Extract Payment Data').item.json.customerEmail }}",
        "message": "=<h2>Documents Received Successfully</h2>\n<p>Thank you for uploading your passport documents. We've securely stored them and sent you an e-signature request via DocuSign.</p>\n<p><strong>Next Steps:</strong></p>\n<ol>\n<li>Check your email for the DocuSign agreement</li>\n<li>Sign the service agreement electronically</li>\n<li>We'll process your passport courier service</li>\n</ol>",
        "subject": "Documents Received - E-Signature Required",
        "resource": "message",
        "emailType": "html",
        "operation": "send"
      },
      "typeVersion": 2.1
    },
    {
      "id": "docusign-webhook",
      "name": "DocuSign Completed Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        250,
        1200
      ],
      "parameters": {
        "path": "docusign-completed",
        "httpMethod": "POST",
        "responseMode": "onReceived"
      },
      "typeVersion": 2.1
    },
    {
      "id": "check-signature-complete",
      "name": "Check Signature Complete",
      "type": "n8n-nodes-base.if",
      "position": [
        470,
        1200
      ],
      "parameters": {
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.event }}",
              "rightValue": "envelope-completed"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "extract-signature-data",
      "name": "Extract Signature Data",
      "type": "n8n-nodes-base.set",
      "position": [
        690,
        1100
      ],
      "parameters": {
        "mode": "manual",
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "envelopeId",
              "type": "string",
              "value": "={{ $json.body.data.envelopeId }}"
            },
            {
              "id": "2",
              "name": "customerEmail",
              "type": "string",
              "value": "={{ $json.body.data.recipientEmail }}"
            },
            {
              "id": "3",
              "name": "signedDate",
              "type": "string",
              "value": "={{ $json.body.data.completedDateTime }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "find-client-by-email",
      "name": "Find Client Record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        910,
        1100
      ],
      "parameters": {
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appXXXXXXXXXXXXXX"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblClients"
        },
        "options": {},
        "resource": "record",
        "operation": "search",
        "filterByFormula": "={Email}='{{ $json.customerEmail }}'"
      },
      "typeVersion": 2.1
    },
    {
      "id": "update-crm-signed",
      "name": "Update CRM - Signed",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1130,
        1100
      ],
      "parameters": {
        "id": "={{ $json.id }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appXXXXXXXXXXXXXX"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblClients"
        },
        "columns": {
          "value": {
            "Status": "Agreement Signed - Ready for Shipping",
            "EnvelopeID": "={{ $('Extract Signature Data').item.json.envelopeId }}",
            "SignedDate": "={{ $('Extract Signature Data').item.json.signedDate }}"
          },
          "mappingMode": "defineBelow"
        },
        "resource": "record",
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "create-shipping-label",
      "name": "Create Shipping Label (EasyPost)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1350,
        1100
      ],
      "parameters": {
        "url": "https://api.easypost.com/v2/shipments",
        "method": "POST",
        "jsonBody": "={\n  \"shipment\": {\n    \"to_address\": {\n      \"name\": \"{{ $json.Name }}\",\n      \"street1\": \"{{ $json.Address }}\",\n      \"city\": \"{{ $json.City }}\",\n      \"state\": \"{{ $json.State }}\",\n      \"zip\": \"{{ $json.ZipCode }}\",\n      \"country\": \"US\",\n      \"email\": \"{{ $json.Email }}\",\n      \"phone\": \"{{ $json.Phone }}\"\n    },\n    \"from_address\": {\n      \"company\": \"Passport Courier Service\",\n      \"street1\": \"123 Business Ave\",\n      \"city\": \"New York\",\n      \"state\": \"NY\",\n      \"zip\": \"10001\",\n      \"country\": \"US\",\n      \"phone\": \"212-555-0100\"\n    },\n    \"parcel\": {\n      \"length\": \"10\",\n      \"width\": \"8\",\n      \"height\": \"2\",\n      \"weight\": \"16\"\n    },\n    \"service\": \"Priority\"\n  }\n}",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "easypostApi"
      },
      "typeVersion": 4.3
    },
    {
      "id": "buy-shipping-label",
      "name": "Buy Shipping Label",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1570,
        1100
      ],
      "parameters": {
        "url": "=https://api.easypost.com/v2/shipments/{{ $json.id }}/buy",
        "method": "POST",
        "jsonBody": "={ \"rate\": {{ JSON.stringify($json.rates[0]) }} }",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "easypostApi"
      },
      "typeVersion": 4.3
    },
    {
      "id": "update-crm-shipping",
      "name": "Update CRM - Shipping",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1790,
        1100
      ],
      "parameters": {
        "id": "={{ $('Find Client Record').item.json.id }}",
        "base": {
          "__rl": true,
          "mode": "list",
          "value": "appXXXXXXXXXXXXXX"
        },
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "tblClients"
        },
        "columns": {
          "value": {
            "Status": "Label Generated - In Transit",
            "Carrier": "={{ $json.selected_rate.carrier }}",
            "TrackingURL": "={{ $json.tracker.public_url }}",
            "TrackingNumber": "={{ $json.tracking_code }}",
            "ShippingLabelURL": "={{ $json.postage_label.label_url }}"
          },
          "mappingMode": "defineBelow"
        },
        "resource": "record",
        "operation": "update"
      },
      "typeVersion": 2.1
    },
    {
      "id": "send-shipping-email",
      "name": "Send Shipping Notification",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2010,
        1100
      ],
      "parameters": {
        "sendTo": "={{ $('Extract Signature Data').item.json.customerEmail }}",
        "message": "=<h2>Shipping Confirmation</h2>\n<p>Great news! Your passport courier service is now complete and your package is on its way.</p>\n<p><strong>Tracking Number:</strong> {{ $('Buy Shipping Label').item.json.tracking_code }}</p>\n<p><a href=\"{{ $('Buy Shipping Label').item.json.tracker.public_url }}\">Track Your Package</a></p>\n<p>Thank you for using our service!</p>",
        "subject": "Your Passport is On Its Way!",
        "resource": "message",
        "emailType": "html",
        "operation": "send"
      },
      "typeVersion": 2.1
    },
    {
      "id": "send-shipping-sms",
      "name": "Send Shipping SMS",
      "type": "n8n-nodes-base.twilio",
      "position": [
        2230,
        1100
      ],
      "parameters": {
        "to": "={{ $('Find Client Record').item.json.Phone }}",
        "from": "+1234567890",
        "message": "=Your passport is on its way! Tracking: {{ $('Buy Shipping Label').item.json.tracking_code }}",
        "resource": "sms",
        "operation": "send"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Create Invoice": {
      "main": [
        [
          {
            "node": "Add Invoice Line Item",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find CRM Record": {
      "main": [
        [
          {
            "node": "Update CRM - Payment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calendly Booking": {
      "main": [
        [
          {
            "node": "Extract Booking Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Upload Link": {
      "main": [
        [
          {
            "node": "Send Payment SMS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create CRM Record": {
      "main": [
        [
          {
            "node": "Create Stripe Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buy Shipping Label": {
      "main": [
        [
          {
            "node": "Update CRM - Shipping",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Find Client Record": {
      "main": [
        [
          {
            "node": "Update CRM - Signed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Payment Email": {
      "main": [
        [
          {
            "node": "Send Booking SMS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update CRM - Signed": {
      "main": [
        [
          {
            "node": "Create Shipping Label (EasyPost)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Booking Data": {
      "main": [
        [
          {
            "node": "Create CRM Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Payment Data": {
      "main": [
        [
          {
            "node": "Find CRM Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update CRM - Payment": {
      "main": [
        [
          {
            "node": "Send Upload Link",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Add Invoice Line Item": {
      "main": [
        [
          {
            "node": "Finalize & Send Invoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Payment Success": {
      "main": [
        [
          {
            "node": "Extract Payment Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update CRM - Shipping": {
      "main": [
        [
          {
            "node": "Send Shipping Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Stripe Customer": {
      "main": [
        [
          {
            "node": "Create Invoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Signature Data": {
      "main": [
        [
          {
            "node": "Find Client Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stripe Payment Webhook": {
      "main": [
        [
          {
            "node": "Check Payment Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update CRM - Documents": {
      "main": [
        [
          {
            "node": "Send DocuSign Agreement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload to Secure Drive": {
      "main": [
        [
          {
            "node": "Update CRM - Documents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Document Upload Webhook": {
      "main": [
        [
          {
            "node": "Hash Document (PII Protection)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Finalize & Send Invoice": {
      "main": [
        [
          {
            "node": "Send Payment Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send DocuSign Agreement": {
      "main": [
        [
          {
            "node": "Send Document Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Signature Complete": {
      "main": [
        [
          {
            "node": "Extract Signature Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DocuSign Completed Webhook": {
      "main": [
        [
          {
            "node": "Check Signature Complete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Shipping Notification": {
      "main": [
        [
          {
            "node": "Send Shipping SMS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hash Document (PII Protection)": {
      "main": [
        [
          {
            "node": "Upload to Secure Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Shipping Label (EasyPost)": {
      "main": [
        [
          {
            "node": "Buy Shipping Label",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}