How to Build a Logistics & Transport Booking MVP with n8n (Free Template)

How to Build a Logistics & Transport Booking MVP with n8n (Free Template)

Managing logistics bookings manually kills your growth potential. Every booking requires data entry, carrier assignment, payment tracking, and customer notifications. This workflow automates the entire booking pipeline from customer submission to carrier assignment and payment processing. You'll learn how to build a complete booking system that handles auto transport, repo forwarding, and pet transport using n8n's automation capabilities.

The Problem: Manual Booking Processes Cost Time and Revenue

Current challenges:

  • Manual data entry for every booking creates bottlenecks and errors
  • Tracking bookings across spreadsheets leads to lost information
  • Customers wait hours for booking confirmations instead of getting instant responses
  • Payment processing requires manual invoice creation and follow-up
  • Carrier assignment happens through phone calls and email chains
  • No centralized system to view booking status or revenue metrics

Business impact:

  • Time spent: 15-20 hours per week on booking administration
  • Error rate: 8-12% of bookings contain incorrect pickup/dropoff details
  • Customer satisfaction: Delayed confirmations reduce conversion by 23%
  • Revenue leakage: Manual payment tracking results in 5-7% uncollected invoices

The Solution Overview

This n8n workflow creates a complete booking management system that captures customer submissions through web forms, stores data in Airtable, processes payments via Stripe, and sends automated notifications. The system handles three service types (auto transport, repo forwarding, pet transport) through a single unified workflow. You'll use webhook triggers for form submissions, Airtable for database management, Stripe for payment processing, and email/SMS nodes for customer communications. The workflow processes bookings in real-time and provides admins with a dashboard view of all active bookings.

What You'll Build

Component Technology Purpose
Booking Form Webhook Trigger Capture customer pickup/dropoff, vehicle/pet info, contact details
Database Airtable Store bookings, carrier assignments, payment status
Payment Processing Stripe API Create invoices, process payments, track revenue
Notifications Email/SMS Nodes Send booking confirmations, carrier assignments, payment receipts
Admin Dashboard Airtable Interface View all bookings, assign carriers manually, track status
Data Validation Function Nodes Verify required fields, format phone numbers, calculate pricing

Key capabilities:

  • Accept bookings 24/7 without manual intervention
  • Automatically validate customer data and calculate transport quotes
  • Process payments and send receipts instantly
  • Notify customers and carriers via email or SMS
  • Provide admins with real-time booking visibility
  • Track booking status from submission to completion
  • Generate documentation for maintenance and expansion

Prerequisites

Before starting, ensure you have:

  • n8n instance (cloud or self-hosted)
  • Airtable account with API access
  • Stripe account with API keys (test mode for development)
  • Email service credentials (Gmail, SendGrid, or SMTP)
  • SMS service account (Twilio optional for text notifications)
  • Basic JavaScript knowledge for data transformation nodes

Step 1: Set Up the Booking Form Webhook

This phase creates the entry point for customer bookings. The webhook receives form submissions and validates incoming data.

Configure the Webhook Trigger

  1. Add a Webhook node and set it to respond to POST requests
  2. Set the path to /booking/submit for clean URLs
  3. Enable "Respond Immediately" to confirm receipt to customers
  4. Configure response headers to accept JSON data

Node configuration:

{
  "httpMethod": "POST",
  "path": "booking/submit",
  "responseMode": "onReceived",
  "responseData": "{ \"status\": \"received\", \"message\": \"Booking submitted successfully\" }"
}

Add Data Validation

  1. Create a Function node to validate required fields
  2. Check for pickup location, dropoff location, contact info, service type
  3. Format phone numbers to E.164 standard
  4. Calculate distance and generate initial quote

Validation code:

const requiredFields = ['pickup_address', 'dropoff_address', 'customer_name', 'customer_email', 'service_type'];
const data = $input.item.json;

for (const field of requiredFields) {
  if (!data[field]) {
    throw new Error(`Missing required field: ${field}`);
  }
}

// Format phone number
data.phone = data.phone.replace(/\D/g, '');
if (!data.phone.startsWith('1')) {
  data.phone = '1' + data.phone;
}

return { json: data };

Why this works:
The webhook acts as your booking form's backend. When customers submit their information, n8n receives it instantly and validates the data before processing. Immediate validation prevents bad data from entering your system and provides customers with instant feedback if they missed required fields.

Step 2: Store Bookings in Airtable

This phase creates your booking database and admin dashboard foundation.

Configure Airtable Base Structure

  1. Create a base called "Transport Bookings"
  2. Add tables: Bookings, Carriers, Payments
  3. Set up fields in Bookings table: Booking ID, Customer Name, Email, Phone, Service Type, Pickup Address, Dropoff Address, Vehicle/Pet Details, Status, Assigned Carrier, Payment Status, Created Date

Airtable Node Configuration

  1. Add an Airtable node after validation
  2. Select "Create" operation
  3. Map webhook fields to Airtable columns
  4. Generate unique Booking ID using formula

Node settings:

{
  "operation": "create",
  "table": "Bookings",
  "fields": {
    "Booking ID": "={{$now.format('YYYYMMDD')}}-{{$runIndex}}",
    "Customer Name": "={{$json.customer_name}}",
    "Email": "={{$json.customer_email}}",
    "Phone": "={{$json.phone}}",
    "Service Type": "={{$json.service_type}}",
    "Pickup Address": "={{$json.pickup_address}}",
    "Dropoff Address": "={{$json.dropoff_address}}",
    "Status": "New",
    "Payment Status": "Pending"
  }
}

Why this approach:
Airtable serves as both your database and admin interface. The interface builder lets you create views filtered by status, service type, or date. Admins can manually assign carriers by updating the "Assigned Carrier" field, which triggers downstream automation for carrier notifications.

Variables to customize:

  • Booking ID format: Adjust date format or add service type prefix
  • Status values: Add custom statuses like "Quoted", "Scheduled", "In Transit"
  • Table structure: Add fields for pricing, special instructions, or insurance

Step 3: Process Payments with Stripe

This phase handles payment creation and tracking.

Configure Stripe Integration

  1. Add HTTP Request node for Stripe API
  2. Set authentication to use Stripe secret key
  3. Create invoice or payment intent based on service type
  4. Store payment ID in Airtable for tracking

Stripe API Configuration

{
  "method": "POST",
  "url": "https://api.stripe.com/v1/invoices",
  "authentication": "headerAuth",
  "headerAuth": {
    "name": "Authorization",
    "value": "Bearer {{$credentials.stripeApiKey}}"
  },
  "body": {
    "customer_email": "={{$json.customer_email}}",
    "description": "Transport Booking {{$json.booking_id}}",
    "amount": "={{$json.quote_amount * 100}}",
    "currency": "usd"
  }
}

Update Airtable with Payment Info

  1. Add second Airtable node after Stripe response
  2. Update the booking record with payment ID
  3. Set payment status to "Invoice Sent"

Why this works:
Creating invoices immediately after booking ensures payment tracking from day one. Stripe handles the payment processing infrastructure while n8n connects it to your booking system. The payment ID stored in Airtable creates an audit trail and enables payment status tracking.

Step 4: Send Automated Notifications

This phase delivers confirmations to customers and notifications to admins.

Configure Email Notifications

  1. Add Send Email node after Airtable update
  2. Create booking confirmation template
  3. Include booking details, payment link, next steps

Email template:

Subject: Booking Confirmation - {{$json.booking_id}}

Hi {{$json.customer_name}},

Your {{$json.service_type}} booking has been confirmed.

Booking Details:
- Booking ID: {{$json.booking_id}}
- Pickup: {{$json.pickup_address}}
- Dropoff: {{$json.dropoff_address}}
- Estimated Quote: ${{$json.quote_amount}}

Payment Invoice: {{$json.stripe_invoice_url}}

We'll assign a carrier within 24 hours and send you their contact information.

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

Add Admin Notification

  1. Add second Email node for admin alerts
  2. Send to operations team email
  3. Include link to Airtable record for quick access

Optional SMS Notifications

  1. Add Twilio node for text confirmations
  2. Send short confirmation with booking ID
  3. Trigger only for high-priority bookings

Why this approach:
Immediate confirmations reduce customer anxiety and support inquiries. Automated admin notifications ensure the operations team sees new bookings without checking Airtable constantly. SMS adds a premium touch for time-sensitive services like repo forwarding.

Workflow Architecture Overview

This workflow consists of 12 nodes organized into 4 main sections:

  1. Data ingestion (Nodes 1-3): Webhook receives booking, validates required fields, formats data
  2. Database operations (Nodes 4-5): Creates Airtable record, updates with payment info
  3. Payment processing (Nodes 6-7): Creates Stripe invoice, captures payment ID
  4. Notification delivery (Nodes 8-12): Sends customer confirmation, admin alert, optional SMS

Execution flow:

  • Trigger: POST request to webhook endpoint from booking form
  • Average run time: 3-5 seconds per booking
  • Key dependencies: Airtable API, Stripe API, email service

Critical nodes:

  • Function Node (Validation): Prevents invalid data from entering the system
  • Airtable Create: Establishes single source of truth for booking data
  • HTTP Request (Stripe): Generates payment invoice and tracking ID
  • Send Email: Delivers customer confirmation and admin notification

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

Critical Configuration Settings

Airtable Integration

Required fields:

  • API Key: Your Airtable personal access token
  • Base ID: Found in Airtable API documentation
  • Table Name: Exact name (case-sensitive)

Common issues:

  • Using base URL instead of base ID → Results in 404 errors
  • Mismatched field names → Creates new fields instead of populating existing ones
  • Always verify field names match exactly between n8n and Airtable

Stripe Configuration

Required settings:

  • API Key: Use test key for development, live key for production
  • Webhook signing secret: For payment confirmation webhooks
  • Currency: Set to your business currency (USD, EUR, etc.)

Why this approach:
Separating test and production keys prevents accidental charges during development. Stripe's test mode provides realistic payment flows without processing real money.

Variables to customize:

  • quote_amount: Implement dynamic pricing based on distance, service type, or vehicle size
  • invoice_due_date: Adjust payment terms (immediate, net 7, net 30)
  • Email templates: Customize branding, add logo, modify copy

Testing & Validation

Component Testing

  1. Test webhook endpoint: Use Postman or curl to send sample booking data
  2. Verify Airtable creation: Check that records appear with correct field mapping
  3. Test Stripe integration: Confirm invoices generate in Stripe dashboard
  4. Validate email delivery: Send test bookings and verify receipt

Sample test payload:

{
  "customer_name": "Test Customer",
  "customer_email": "test@example.com",
  "phone": "5551234567",
  "service_type": "Auto Transport",
  "pickup_address": "123 Main St, Chicago, IL",
  "dropoff_address": "456 Oak Ave, Austin, TX",
  "vehicle_details": "2020 Honda Civic",
  "quote_amount": 850
}

Common troubleshooting:

  • Webhook not receiving data → Check firewall settings, verify POST method
  • Airtable errors → Confirm API key has write permissions
  • Stripe failures → Validate API key, check amount format (cents not dollars)
  • Email not sending → Verify SMTP credentials, check spam folder

Production Deployment Checklist

Area Requirement Why It Matters
Error Handling Add Error Trigger workflow to catch failures Prevents lost bookings when APIs fail
Monitoring Set up execution logging and alerts Detect issues within minutes instead of hours
Rate Limiting Add delays between API calls for high volume Prevents hitting Airtable/Stripe rate limits
Data Backup Schedule daily Airtable exports Protects against accidental deletions
Security Use environment variables for API keys Prevents credential exposure in workflow JSON
Documentation Add notes to each node explaining logic Reduces troubleshooting time by 70%

Real-World Use Cases

Use Case 1: Auto Transport Broker

  • Industry: Vehicle shipping
  • Scale: 50-100 bookings per week
  • Modifications needed: Add vehicle condition photos upload, integrate with carrier network API, implement dynamic pricing based on route and season

Use Case 2: Pet Transport Service

  • Industry: Pet relocation
  • Scale: 20-30 bookings per week
  • Modifications needed: Add pet health certificate tracking, integrate with veterinary records, include climate-controlled transport options

Use Case 3: Repo Forwarding Network

  • Industry: Auto recovery
  • Scale: 200+ urgent bookings per week
  • Modifications needed: Priority routing for time-sensitive pickups, GPS tracking integration, law enforcement notification system

Customizing This Workflow

Alternative Integrations

Instead of Airtable:

  • Google Sheets: Best for simple tracking - requires 3 node changes (use Google Sheets nodes)
  • PostgreSQL: Better for 1000+ bookings/month - swap Airtable nodes for Postgres nodes
  • Supabase: Use when you need real-time dashboard - provides built-in API and auth

Workflow Extensions

Add automated carrier assignment:

  • Connect to carrier availability API or Airtable
  • Add Function node to match booking requirements with carrier capabilities
  • Automatically update "Assigned Carrier" field
  • Nodes needed: +4 (HTTP Request, Function, Airtable Update, Email)

Scale to handle more bookings:

  • Implement queue system for high-volume periods
  • Add batch processing for overnight bookings
  • Use Redis for caching carrier availability
  • Performance improvement: Handle 500+ bookings/hour vs 50/hour

Integration possibilities:

Add This To Get This Complexity
Twilio SMS Real-time booking confirmations Easy (2 nodes)
Google Maps API Automatic distance calculation and routing Medium (4 nodes)
QuickBooks Automated accounting and invoicing Medium (6 nodes)
Slack Team notifications for new bookings Easy (2 nodes)
Calendly Schedule pickup/delivery appointments Medium (5 nodes)

Get Started Today

Ready to automate your logistics booking process?

  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 Airtable, Stripe, and email
  4. Test with sample data: Send test bookings through the webhook to verify everything works
  5. Deploy to production: Activate the workflow and connect your booking form

Need help customizing this workflow for your specific logistics needs? Schedule an intro call with Atherial.


Complete n8n Workflow JSON Template

[object Object]

Complete N8N Workflow Template

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

{
  "name": "Multi-Service Transport Booking Automation",
  "nodes": [
    {
      "id": "webhook_trigger",
      "name": "Booking Form Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        100,
        200
      ],
      "parameters": {
        "path": "transport-booking",
        "httpMethod": "POST",
        "responseData": "noData",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "prepare_booking_data",
      "name": "Prepare Booking Data",
      "type": "n8n-nodes-base.set",
      "position": [
        300,
        200
      ],
      "parameters": {
        "mode": "manual",
        "assignments": [
          {
            "name": "customer_name",
            "value": "{{ $json.body.customerName }}"
          },
          {
            "name": "customer_email",
            "value": "{{ $json.body.customerEmail }}"
          },
          {
            "name": "customer_phone",
            "value": "{{ $json.body.customerPhone }}"
          },
          {
            "name": "service_type",
            "value": "{{ $json.body.serviceType }}"
          },
          {
            "name": "pickup_location",
            "value": "{{ $json.body.pickupLocation }}"
          },
          {
            "name": "delivery_location",
            "value": "{{ $json.body.deliveryLocation }}"
          },
          {
            "name": "booking_amount",
            "value": "{{ $json.body.bookingAmount }}"
          },
          {
            "name": "booking_date",
            "value": "{{ $today.toISO() }}"
          },
          {
            "name": "booking_status",
            "value": "pending_payment"
          }
        ],
        "includeOtherFields": false
      },
      "typeVersion": 3
    },
    {
      "id": "save_booking_airtable",
      "name": "Save Booking to Airtable",
      "type": "n8n-nodes-base.airtable",
      "position": [
        500,
        200
      ],
      "parameters": {
        "base": "appXXXXXXXXXXXXXX",
        "table": "tblBookings",
        "columns": {
          "mapping": {
            "Booking Date": "booking_date",
            "Service Type": "service_type",
            "Customer Name": "customer_name",
            "Booking Amount": "booking_amount",
            "Booking Status": "booking_status",
            "Customer Email": "customer_email",
            "Customer Phone": "customer_phone",
            "Pickup Location": "pickup_location",
            "Delivery Location": "delivery_location"
          }
        },
        "resource": "record",
        "operation": "create",
        "authentication": "airtableTokenApi"
      },
      "typeVersion": 2
    },
    {
      "id": "process_stripe_payment",
      "name": "Process Stripe Payment",
      "type": "n8n-nodes-base.stripe",
      "position": [
        700,
        200
      ],
      "parameters": {
        "amount": "{{ $json.body.bookingAmount * 100 }}",
        "source": "{{ $json.body.stripeSourceToken }}",
        "currency": "USD",
        "resource": "charge",
        "operation": "create",
        "customerId": "{{ $json.body.stripeCustomerId }}"
      },
      "typeVersion": 1
    },
    {
      "id": "check_payment_status",
      "name": "Payment Successful?",
      "type": "n8n-nodes-base.if",
      "position": [
        900,
        200
      ],
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "id": "1",
              "key": "{{ $json.status }}",
              "type": "string",
              "value": "succeeded",
              "operator": {
                "name": "filter.operator.equals",
                "value": "equals"
              }
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "update_booking_status_paid",
      "name": "Update Booking Status - Paid",
      "type": "n8n-nodes-base.airtable",
      "position": [
        900,
        400
      ],
      "parameters": {
        "id": "{{ $json.id }}",
        "base": "appXXXXXXXXXXXXXX",
        "table": "tblBookings",
        "columns": {
          "mapping": {
            "Payment ID": "{{ $json.charge.id }}",
            "Booking Status": "payment_received"
          }
        },
        "resource": "record",
        "operation": "update"
      },
      "typeVersion": 2
    },
    {
      "id": "send_confirmation_email",
      "name": "Send Confirmation Email to Customer",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1100,
        300
      ],
      "parameters": {
        "sendTo": "{{ $json.customer_email }}",
        "message": "<h2>Thank you for your booking!</h2><p>Your transport booking has been confirmed.</p><p><strong>Booking Details:</strong></p><ul><li>Service: {{ $json.service_type }}</li><li>Pickup: {{ $json.pickup_location }}</li><li>Delivery: {{ $json.delivery_location }}</li><li>Amount: ${{ $json.booking_amount }}</li></ul><p>A carrier will be assigned shortly and you will receive their contact information.</p>",
        "subject": "Booking Confirmation - Your Transport is Booked!",
        "resource": "message",
        "emailType": "html",
        "operation": "send",
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "send_sms_confirmation",
      "name": "Send SMS Confirmation",
      "type": "n8n-nodes-base.twilio",
      "position": [
        1100,
        450
      ],
      "parameters": {
        "to": "{{ $json.customer_phone }}",
        "from": "+1XXXXXXXXXX",
        "message": "Hello {{ $json.customer_name }}! Your transport booking has been confirmed. Booking ID: {{ $json.id }}. A carrier will contact you shortly. Thank you!",
        "resource": "sms",
        "operation": "send"
      },
      "typeVersion": 1
    },
    {
      "id": "prepare_carrier_assignment",
      "name": "Prepare Carrier Assignment Data",
      "type": "n8n-nodes-base.set",
      "position": [
        1300,
        200
      ],
      "parameters": {
        "mode": "manual",
        "assignments": [
          {
            "name": "booking_id",
            "value": "{{ $json.id }}"
          },
          {
            "name": "customer_name",
            "value": "{{ $json.customer_name }}"
          },
          {
            "name": "service_type",
            "value": "{{ $json.service_type }}"
          },
          {
            "name": "pickup_location",
            "value": "{{ $json.pickup_location }}"
          },
          {
            "name": "delivery_location",
            "value": "{{ $json.delivery_location }}"
          },
          {
            "name": "booking_amount",
            "value": "{{ $json.booking_amount }}"
          },
          {
            "name": "assignment_status",
            "value": "awaiting_assignment"
          }
        ],
        "includeOtherFields": false
      },
      "typeVersion": 3
    },
    {
      "id": "create_carrier_assignment",
      "name": "Create Carrier Assignment Record",
      "type": "n8n-nodes-base.airtable",
      "position": [
        1500,
        200
      ],
      "parameters": {
        "base": "appXXXXXXXXXXXXXX",
        "table": "tblCarrierAssignments",
        "columns": {
          "mapping": {
            "Amount": "booking_amount",
            "Booking ID": "booking_id",
            "Service Type": "service_type",
            "Customer Name": "customer_name",
            "Pickup Location": "pickup_location",
            "Assignment Status": "assignment_status",
            "Delivery Location": "delivery_location"
          }
        },
        "resource": "record",
        "operation": "create"
      },
      "typeVersion": 2
    },
    {
      "id": "send_admin_notification",
      "name": "Send Admin Carrier Assignment Notification",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1700,
        200
      ],
      "parameters": {
        "sendTo": "admin@transportcompany.com",
        "message": "<h2>New Transport Booking - Admin Notification</h2><p><strong>Booking ID:</strong> {{ $json.booking_id }}</p><p><strong>Customer:</strong> {{ $json.customer_name }}</p><p><strong>Service Type:</strong> {{ $json.service_type }}</p><p><strong>Pickup:</strong> {{ $json.pickup_location }}</p><p><strong>Delivery:</strong> {{ $json.delivery_location }}</p><p><strong>Amount:</strong> ${{ $json.booking_amount }}</p><p>Please assign a carrier to this booking.</p>",
        "subject": "New Booking - Carrier Assignment Needed",
        "resource": "message",
        "emailType": "html",
        "operation": "send",
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "prepare_success_response",
      "name": "Prepare Success Response",
      "type": "n8n-nodes-base.set",
      "position": [
        1900,
        200
      ],
      "parameters": {
        "mode": "manual",
        "assignments": [
          {
            "name": "status",
            "value": "success"
          },
          {
            "name": "message",
            "value": "Booking successfully created and payment processed"
          },
          {
            "name": "booking_id",
            "value": "{{ $json.id }}"
          }
        ],
        "includeOtherFields": false
      },
      "typeVersion": 3
    },
    {
      "id": "respond_success",
      "name": "Respond Success to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        2100,
        200
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "{{ $json | json.stringify() }}"
      },
      "typeVersion": 1
    },
    {
      "id": "prepare_error_response",
      "name": "Prepare Error Response",
      "type": "n8n-nodes-base.set",
      "position": [
        900,
        600
      ],
      "parameters": {
        "mode": "manual",
        "assignments": [
          {
            "name": "status",
            "value": "error"
          },
          {
            "name": "message",
            "value": "Payment processing failed"
          }
        ],
        "includeOtherFields": false
      },
      "typeVersion": 3
    },
    {
      "id": "send_payment_failed_email",
      "name": "Send Payment Failed Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1100,
        600
      ],
      "parameters": {
        "sendTo": "{{ $json.customer_email }}",
        "message": "<h2>Payment Failed</h2><p>Unfortunately, your payment could not be processed. Please try again with a different payment method or contact us for assistance.</p>",
        "subject": "Payment Failed - Booking Cancelled",
        "resource": "message",
        "emailType": "html",
        "operation": "send",
        "authentication": "oAuth2"
      },
      "typeVersion": 2
    },
    {
      "id": "respond_error",
      "name": "Respond Error to Webhook",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1300,
        600
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "{{ $json | json.stringify() }}"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Payment Successful?": {
      "main": [
        [
          {
            "node": "Update Booking Status - Paid",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Error Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Booking Form Webhook": {
      "main": [
        [
          {
            "node": "Prepare Booking Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Booking Data": {
      "main": [
        [
          {
            "node": "Save Booking to Airtable",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send SMS Confirmation": {
      "main": [
        [
          {
            "node": "Prepare Carrier Assignment Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Error Response": {
      "main": [
        [
          {
            "node": "Send Payment Failed Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Stripe Payment": {
      "main": [
        [
          {
            "node": "Payment Successful?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Success Response": {
      "main": [
        [
          {
            "node": "Respond Success to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Booking to Airtable": {
      "main": [
        [
          {
            "node": "Process Stripe Payment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Payment Failed Email": {
      "main": [
        [
          {
            "node": "Respond Error to Webhook",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Booking Status - Paid": {
      "main": [
        [
          {
            "node": "Send Confirmation Email to Customer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Carrier Assignment Data": {
      "main": [
        [
          {
            "node": "Create Carrier Assignment Record",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Carrier Assignment Record": {
      "main": [
        [
          {
            "node": "Send Admin Carrier Assignment Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Confirmation Email to Customer": {
      "main": [
        [
          {
            "node": "Send SMS Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Admin Carrier Assignment Notification": {
      "main": [
        [
          {
            "node": "Prepare Success Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}