DEV Community

Alex Kane
Alex Kane

Posted on

n8n for Marketplace & Platform Companies: 5 Automations That Scale Both Sides of the Market (Free Workflow JSON)

Running a two-sided marketplace means managing two completely different groups simultaneously: sellers (providers, hosts, gig workers) and buyers (consumers, guests, riders). Every transaction, dispute, and onboarding event happens at scale — manual ops don't survive hypergrowth.

Here are 5 n8n automations built for marketplace and platform companies — with import-ready JSON for each.


Why Self-Hosted n8n for Marketplaces?

Marketplace ops involve transaction records (PCI DSS), seller/buyer PII (GDPR/CCPA), platform pricing algorithms (trade secrets), and fraud signals. Routing any of this through Zapier or Make's cloud means sensitive marketplace data transits a third-party server.

Self-hosted n8n keeps all automation logic inside your own infrastructure — git-versionable JSON, full audit trail, zero data egress.

Feature n8n (self-hosted) Zapier Make
Data stays on your infra Yes No No
High-volume webhook events Yes Limited Limited
Git-versionable workflows Yes No No
Cost at scale ~$0/month $$$+ $$+

Workflow 1: New Seller Onboarding Drip

Goal: Guide new sellers from signup to first sale with automated touchpoints — no CSM needed for every new account.

{
  "name": "Marketplace — Seller Onboarding Drip",
  "nodes": [
    { "name": "New Seller Row", "type": "n8n-nodes-base.googleSheetsTrigger",
      "parameters": { "sheetId": "YOUR_SHEET_ID", "triggerOn": "rowAdded" } },
    { "name": "Day 0 Welcome Email", "type": "n8n-nodes-base.gmail",
      "parameters": { "operation": "send", "toEmail": "={{ $json.email }}",
        "subject": "Welcome to [Platform] — set up your first listing",
        "message": "Hi {{ $json.seller_name }}, welcome! Here are your first steps..." } },
    { "name": "CSM Slack Alert", "type": "n8n-nodes-base.slack",
      "parameters": { "channel": "#seller-success",
        "text": "New seller: {{ $json.seller_name }} — check in by Day 3" } },
    { "name": "Wait 3 Days", "type": "n8n-nodes-base.wait",
      "parameters": { "amount": 3, "unit": "days" } },
    { "name": "Day 3 Listing Tips", "type": "n8n-nodes-base.gmail",
      "parameters": { "operation": "send", "toEmail": "={{ $json.email }}",
        "subject": "Listings with 5+ photos get 3x more orders",
        "message": "Hi {{ $json.seller_name }}, here is what top sellers do in week 1..." } },
    { "name": "Wait 4 Days", "type": "n8n-nodes-base.wait",
      "parameters": { "amount": 4, "unit": "days" } },
    { "name": "Day 7 First-Sale Push", "type": "n8n-nodes-base.gmail",
      "parameters": { "operation": "send", "toEmail": "={{ $json.email }}",
        "subject": "You are 1 step from your first sale",
        "message": "Hi {{ $json.seller_name }}, sellers who do these 3 things make their first sale 4x faster..." } },
    { "name": "Mark Complete", "type": "n8n-nodes-base.googleSheets",
      "parameters": { "operation": "update", "columns": { "onboarding_complete": true } } }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Why it matters: Most marketplace seller churn happens in the first 14 days — before the seller makes their first sale. Automated touchpoints at the right moment keep sellers engaged without growing CS headcount.


Workflow 2: Transaction Dispute Auto-Triage

Goal: Route dispute tickets to the right team instantly, with an immediate buyer acknowledgement.

{
  "name": "Marketplace — Dispute Auto-Triage",
  "nodes": [
    { "name": "Dispute Webhook", "type": "n8n-nodes-base.webhook",
      "parameters": { "path": "dispute-created", "responseMode": "responseNode" } },
    { "name": "ACK Immediately", "type": "n8n-nodes-base.respondToWebhook",
      "parameters": { "responseCode": 200 } },
    { "name": "Classify Dispute", "type": "n8n-nodes-base.code",
      "parameters": { "jsCode": "const body = $json.body || $json; const text = (body.reason + ' ' + body.buyer_message).toLowerCase(); let type = 'OTHER'; if (text.includes('fraud') || text.includes('unauthorized')) type = 'FRAUD_REPORT'; else if (text.includes('not received') || text.includes('never arrived')) type = 'ITEM_NOT_RECEIVED'; else if (text.includes('refund') || text.includes('return')) type = 'REFUND_REQUEST'; else if (text.includes('cancel')) type = 'SELLER_CANCELLATION'; const priority = type === 'FRAUD_REPORT' ? 'CRITICAL' : body.order_value > 500 ? 'HIGH' : 'MEDIUM'; return [{ ...body, dispute_type: type, priority }];" } },
    { "name": "Route by Type", "type": "n8n-nodes-base.switch",
      "parameters": { "rules": [
        { "value1": "={{ $json.dispute_type }}", "value2": "FRAUD_REPORT", "output": 0 },
        { "value1": "={{ $json.dispute_type }}", "value2": "ITEM_NOT_RECEIVED", "output": 1 },
        { "value1": "={{ $json.dispute_type }}", "value2": "REFUND_REQUEST", "output": 2 }
      ] } },
    { "name": "Alert Fraud Team", "type": "n8n-nodes-base.slack",
      "parameters": { "channel": "#fraud-ops",
        "text": "FRAUD REPORT: Order {{ $json.order_id }} — ${{ $json.order_value }} — {{ $json.buyer_message }}" } },
    { "name": "ACK Buyer by Email", "type": "n8n-nodes-base.gmail",
      "parameters": { "operation": "send", "toEmail": "={{ $json.buyer_email }}",
        "subject": "Your dispute #{{ $json.dispute_id }} received — we will follow up within 24h",
        "message": "Hi {{ $json.buyer_name }}, your case is being reviewed. Reference: {{ $json.dispute_id }}" } },
    { "name": "Log to Postgres", "type": "n8n-nodes-base.postgres",
      "parameters": { "operation": "insert", "table": "disputes" } }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Why it matters: Dispute SLAs are often contractual in marketplace agreements. Manual triage at scale means tickets fall through the cracks — fraud reports especially need immediate human eyes.


Workflow 3: Seller Quality Score Monitor

Goal: Detect seller quality degradation before sellers reach policy-action thresholds.

{
  "name": "Marketplace — Seller Quality Monitor",
  "nodes": [
    { "name": "Daily 8AM", "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": { "rule": { "hour": 8 } } },
    { "name": "Query Seller Metrics", "type": "n8n-nodes-base.postgres",
      "parameters": { "operation": "select",
        "query": "SELECT seller_id, seller_name, email, avg_rating, cancellation_rate, response_time_hrs, fulfilment_rate, (avg_rating*30 + (1-cancellation_rate)*30 + LEAST(fulfilment_rate*20,20) + GREATEST(20-(response_time_hrs*2),0)) AS quality_score FROM seller_metrics WHERE active = true ORDER BY quality_score ASC" } },
    { "name": "Flag Risk Tier", "type": "n8n-nodes-base.code",
      "parameters": { "jsCode": "return $input.all().map(item => { const s = item.json; const tier = s.quality_score < 40 ? 'CRITICAL' : s.quality_score < 60 ? 'AT_RISK' : s.quality_score < 70 ? 'WATCH' : 'GOOD'; return { ...s, risk_tier: tier }; }).filter(s => s.risk_tier !== 'GOOD');" } },
    { "name": "Email Improvement Guide", "type": "n8n-nodes-base.gmail",
      "parameters": { "operation": "send", "toEmail": "={{ $json.email }}",
        "subject": "Your seller score needs attention — here is how to improve it",
        "message": "Hi {{ $json.seller_name }}, your quality score is {{ $json.quality_score }}/100. Here are the top 3 improvements: response time, cancellation rate, fulfilment rate." } },
    { "name": "CRITICAL Sellers to Trust Safety", "type": "n8n-nodes-base.if",
      "parameters": { "conditions": [{ "value1": "={{ $json.risk_tier }}", "value2": "CRITICAL" }] } },
    { "name": "Slack Trust Safety Alert", "type": "n8n-nodes-base.slack",
      "parameters": { "channel": "#trust-safety",
        "text": "CRITICAL SELLER: {{ $json.seller_name }} — score {{ $json.quality_score }}/100. Policy review required before suspension." } }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Why it matters: Catching a seller at 65/100 (before the 60 threshold that triggers suspension) is cheaper than enforcement. Proactive outreach converts ~30% of at-risk sellers back to healthy status.


Workflow 4: Platform Fraud & Anomaly Alert

Goal: Surface suspicious transaction patterns every 15 minutes — before they scale into a fraud event.

{
  "name": "Marketplace — Fraud Anomaly Monitor",
  "nodes": [
    { "name": "Every 15 Min", "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": { "rule": { "interval": 15, "unit": "minutes" } } },
    { "name": "Multi-Account Same IP", "type": "n8n-nodes-base.postgres",
      "parameters": { "operation": "select",
        "query": "SELECT ip_address, COUNT(DISTINCT buyer_id) as accounts, SUM(order_value) as total_spend FROM orders WHERE created_at > NOW() - INTERVAL '1 hour' GROUP BY ip_address HAVING COUNT(DISTINCT buyer_id) > 3 ORDER BY accounts DESC LIMIT 20" } },
    { "name": "Burst Orders New Accounts", "type": "n8n-nodes-base.postgres",
      "parameters": { "operation": "select",
        "query": "SELECT buyer_id, buyer_email, COUNT(*) as orders_1h, SUM(order_value) as spend_1h FROM orders o JOIN buyers b ON o.buyer_id = b.id WHERE o.created_at > NOW() - INTERVAL '1 hour' AND b.created_at > NOW() - INTERVAL '24 hours' GROUP BY buyer_id, buyer_email HAVING COUNT(*) > 5 OR SUM(order_value) > 500" } },
    { "name": "Merge Signals", "type": "n8n-nodes-base.merge",
      "parameters": { "mode": "append" } },
    { "name": "Score & Filter", "type": "n8n-nodes-base.code",
      "parameters": { "jsCode": "return $input.all().map(item => { const r = item.json; const severity = (r.accounts > 10 || r.spend_1h > 2000) ? 'CRITICAL' : (r.accounts > 5 || r.orders_1h > 10) ? 'HIGH' : 'MEDIUM'; return { ...r, severity }; })" } },
    { "name": "Alert Fraud Ops", "type": "n8n-nodes-base.slack",
      "parameters": { "channel": "#fraud-ops",
        "text": "{{ $json.severity }} fraud signal: {{ $json.ip_address ? 'IP ' + $json.ip_address + ' used by ' + $json.accounts + ' accounts' : 'Buyer ' + $json.buyer_email + ' placed ' + $json.orders_1h + ' orders/hour' }}. Value: ${{ $json.total_spend || $json.spend_1h }}" } },
    { "name": "Log Signal", "type": "n8n-nodes-base.postgres",
      "parameters": { "operation": "insert", "table": "fraud_signals" } }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Why it matters: Fraud on marketplaces is a slow boil — small signals that compound. 15-minute polling catches patterns while they are still actionable, before a chargeback wave hits.


Workflow 5: Weekly Marketplace Health Report

Goal: Give leadership a single weekly view of both sides of the market — GMV, take rate, dispute rate, seller activation.

{
  "name": "Marketplace — Weekly Health Report",
  "nodes": [
    { "name": "Monday 8AM", "type": "n8n-nodes-base.scheduleTrigger",
      "parameters": { "rule": { "dayOfWeek": 1, "hour": 8 } } },
    { "name": "Query GMV Metrics", "type": "n8n-nodes-base.postgres",
      "parameters": { "operation": "select",
        "query": "SELECT SUM(order_value) as gmv, COUNT(*) as transactions, AVG(order_value) as avg_order_value, SUM(platform_fee) as revenue, SUM(platform_fee)/NULLIF(SUM(order_value),0)*100 as take_rate_pct, SUM(CASE WHEN status='disputed' THEN 1 ELSE 0 END)*100.0/COUNT(*) as dispute_rate_pct, COUNT(DISTINCT seller_id) as active_sellers, COUNT(DISTINCT buyer_id) as active_buyers FROM orders WHERE created_at >= DATE_TRUNC('week', NOW()) - INTERVAL '7 days' AND created_at < DATE_TRUNC('week', NOW())" } },
    { "name": "Query New Sellers", "type": "n8n-nodes-base.postgres",
      "parameters": { "operation": "select",
        "query": "SELECT COUNT(*) as new_sellers, COUNT(CASE WHEN first_sale_at IS NOT NULL THEN 1 END) as activated_sellers FROM sellers WHERE created_at >= DATE_TRUNC('week', NOW()) - INTERVAL '7 days'" } },
    { "name": "Merge Metrics", "type": "n8n-nodes-base.merge",
      "parameters": { "mode": "mergeByPosition" } },
    { "name": "Build HTML Report", "type": "n8n-nodes-base.code",
      "parameters": { "jsCode": "const m = Object.assign({}, $input.all()[0].json, $input.all()[1] ? $input.all()[1].json : {}); const prev = $getWorkflowStaticData('global').prev_gmv || m.gmv; const wow = prev ? ((m.gmv - prev) / prev * 100).toFixed(1) + '%' : 'N/A'; $getWorkflowStaticData('global').prev_gmv = m.gmv; const rows = [['GMV', '$' + Number(m.gmv||0).toLocaleString(), wow + ' WoW'], ['Transactions', m.transactions, ''], ['Avg Order', '$' + Number(m.avg_order_value||0).toFixed(2), ''], ['Platform Revenue', '$' + Number(m.revenue||0).toLocaleString(), ''], ['Take Rate', Number(m.take_rate_pct||0).toFixed(1) + '%', ''], ['Dispute Rate', Number(m.dispute_rate_pct||0).toFixed(2) + '%', ''], ['Active Sellers', m.active_sellers, ''], ['Active Buyers', m.active_buyers, ''], ['New Sellers', m.new_sellers, ''], ['Activated (First Sale)', m.activated_sellers, '']]; const trs = rows.map(r => '<tr><td>' + r[0] + '</td><td>' + r[1] + '</td><td>' + r[2] + '</td></tr>').join(''); const html = '<h2>Weekly Marketplace Report</h2><table border=1 style=border-collapse:collapse><tr><th>Metric</th><th>This Week</th><th>Delta</th></tr>' + trs + '</table>'; return [{ html, summary: 'GMV $' + Number(m.gmv||0).toLocaleString() + ' (' + wow + ') | Take rate ' + Number(m.take_rate_pct||0).toFixed(1) + '% | Dispute rate ' + Number(m.dispute_rate_pct||0).toFixed(2) + '%' }];" } },
    { "name": "Email Leadership", "type": "n8n-nodes-base.gmail",
      "parameters": { "operation": "send", "toEmail": "leadership@yourcompany.com",
        "subject": "Weekly Marketplace Report",
        "message": "={{ $json.html }}", "emailType": "html" } },
    { "name": "Slack Summary", "type": "n8n-nodes-base.slack",
      "parameters": { "channel": "#marketplace",
        "text": "Weekly marketplace: {{ $json.summary }}" } }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Why it matters: Marketplace businesses live by cohort math. Seeing GMV grow without also tracking take rate, dispute rate, and seller activation in the same view causes bad decisions.


Get All 5 Workflows (Import-Ready)

All 5 marketplace automation workflows — fully configured, import-ready JSON — are available at FlowKit on Gumroad.

Each template includes import-ready JSON, a setup guide, and tested node configurations.

What marketplace problems are you automating? Drop a comment — happy to share workflow patterns for your use case.

Top comments (0)