AutomationFlowsAI & RAG › Coffee & Peppers - Contact Form AI

Coffee & Peppers - Contact Form AI

Coffee & Peppers - Contact Form AI. Uses httpRequest, openAi, gmail. Scheduled trigger; 12 nodes.

Cron / scheduled trigger★★★★☆ complexityAI-powered12 nodesHTTP RequestOpenAIGmail
AI & RAG Trigger: Cron / scheduled Nodes: 12 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow follows the Gmail → HTTP Request recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "name": "Coffee & Peppers - Contact Form AI",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 1
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -600,
        0
      ],
      "id": "schedule-trigger",
      "name": "Every Minute"
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://coffeeandpeppers.com/wp-json/fluentform/v1/submissions?form_id=3&per_page=10&sort_column=id&sort_by=DESC&status=unread",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        -380,
        0
      ],
      "id": "fetch-submissions",
      "name": "Fetch Unread Submissions",
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Parse the Fluent Forms API response\n// It returns {total, data: [...]} structure\nconst response = $input.first().json;\n\nlet submissions = [];\ntry {\n  // Response may be a string (JSON-encoded)\n  const parsed = typeof response === 'string' ? JSON.parse(response) : response;\n  submissions = parsed.data || parsed || [];\n} catch(e) {\n  return [];\n}\n\nif (!submissions.length) return [];\n\n// Parse each submission's response field\nconst items = submissions.map(sub => {\n  let formData = {};\n  try {\n    formData = JSON.parse(sub.response);\n  } catch(e) {}\n  \n  const names = formData.names || {};\n  const firstName = names.first_name || '';\n  const lastName = names.last_name || '';\n  \n  return {\n    json: {\n      submissionId: sub.id,\n      customerName: `${firstName} ${lastName}`.trim() || 'there',\n      customerEmail: formData.email || '',\n      subject: formData.subject || '',\n      message: formData.message || '',\n      createdAt: sub.created_at,\n      source: 'fluent_forms'\n    }\n  };\n});\n\nreturn items;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -160,
        0
      ],
      "id": "parse-submissions",
      "name": "Parse Submissions"
    },
    {
      "parameters": {
        "jsCode": "// Extract order number from subject and message\nconst data = $input.first().json;\nconst subject = data.subject || '';\nconst message = data.message || '';\nconst searchText = subject + ' ' + message;\n\nconst orderMatch = searchText.match(/(?:order\\s*#?\\s*|#)(\\d{4,6})\\b/i)\n  || searchText.match(/\\b(\\d{5,6})\\b/);\nconst orderNumber = orderMatch ? orderMatch[1] : null;\n\n// Check for system emails / skip non-customer messages\nconst isSystemEmail = !data.customerEmail || data.customerEmail.includes('mailer-daemon');\nif (isSystemEmail) return [];\n\nreturn [{ json: { ...data, orderNumber } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        60,
        0
      ],
      "id": "extract-order",
      "name": "Extract Order Number"
    },
    {
      "parameters": {
        "conditions": {
          "conditions": [
            {
              "leftValue": "={{ $json.orderNumber }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "isNotEmpty"
              }
            }
          ]
        }
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        280,
        0
      ],
      "id": "has-order",
      "name": "Has Order Number?"
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://coffeeandpeppers.com/wp-json/wc/v3/orders/{{ $json.orderNumber }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        500,
        -120
      ],
      "id": "get-order-by-number",
      "name": "Get Order by Number",
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "method": "GET",
        "url": "=https://coffeeandpeppers.com/wp-json/wc/v3/orders?email={{ $json.customerEmail }}&per_page=3&orderby=date&order=desc",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        500,
        120
      ],
      "id": "get-orders-by-email",
      "name": "Get Orders by Email",
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "jsCode": "const formData = $('Extract Order Number').first().json;\nconst orderData = $input.first().json;\n\nlet orderSummary = 'No order data available.';\ntry {\n  if (Array.isArray(orderData) && orderData.length > 0) {\n    orderSummary = orderData.slice(0, 3).map(o => {\n      const items = (o.line_items || []).map(i => `${i.quantity}x ${i.name}`).join(', ');\n      const tracking = o.meta_data?.find(m => m.key === '_wc_shipment_tracking_items')?.value?.[0]?.tracking_number;\n      return `Order #${o.id} | ${o.status} | ${items} | $${o.total}` + (tracking ? ` | Tracking: ${tracking}` : '');\n    }).join('\\n');\n  } else if (orderData && orderData.id) {\n    const items = (orderData.line_items || []).map(i => `${i.quantity}x ${i.name}`).join(', ');\n    const tracking = orderData.meta_data?.find(m => m.key === '_wc_shipment_tracking_items')?.value?.[0]?.tracking_number;\n    orderSummary = `Order #${orderData.id} | ${orderData.status} | ${items} | $${orderData.total}` + (tracking ? ` | Tracking: ${tracking}` : '');\n  }\n} catch(e) {\n  orderSummary = 'Could not retrieve order data.';\n}\n\nreturn [{ json: { ...formData, orderSummary } }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        0
      ],
      "id": "format-order",
      "name": "Format Order Data"
    },
    {
      "parameters": {
        "model": "gpt-5",
        "messages": {
          "values": [
            {
              "role": "system",
              "content": "You are a friendly, casual customer service AI for Coffee & Peppers (coffeeandpeppers.com), a peptide and supplement company. Your job is to:\n\n1. CLASSIFY the email into one of these categories:\n   - order_status (asking where their order is)\n   - missing_items (received incomplete kit or wrong items)\n   - wrong_address (address error on order)\n   - dosing_medical (ANY dosing, medical, or health advice questions)\n   - product_question (general product info, availability, batch tests)\n   - refund_return (requesting refund or return)\n   - other (anything that doesn't fit above)\n\n2. Determine a CONFIDENCE score (0.0 to 1.0):\n   - High confidence (0.8+): Simple factual replies, dosing deflections, order status with full data\n   - Low confidence (below 0.8): Missing items, refunds, complaints, anything requiring a business decision\n\n3. Draft a RESPONSE that is casual and friendly. Sign off as 'The C&P Team'.\n\nSpecial rules:\n- For dosing_medical: Respond with: \"Hey [name]!\\n\\nWe totally get the curiosity, but we're not able to give medical or dosing advice - that's something to chat with your healthcare provider about! Is there anything else we can help you with?\\n\\n- The C&P Team\"\n- For missing_items or wrong_address: Keep confidence LOW (0.4)\n- For refund_return: Keep confidence LOW (0.3)\n- Never promise specific outcomes without human approval\n- Format: greeting on its own line, blank line, then body. Use \\n\\n between greeting and body.\n\nReturn ONLY valid JSON:\n{\n  \"category\": \"<category>\",\n  \"confidence\": <number>,\n  \"response\": \"<full email response>\",\n  \"summary\": \"<one sentence summary>\"\n}"
            },
            {
              "role": "user",
              "content": "=Customer: {{ $json.customerName }}\nEmail: {{ $json.customerEmail }}\nSubject: {{ $json.subject }}\nMessage: {{ $json.message }}\n\nOrder Data: {{ $json.orderSummary }}\nSource: Contact Form (structured data, no thread contamination)\n\nClassify and draft a response."
            }
          ]
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 1.7,
      "position": [
        940,
        0
      ],
      "id": "ai-node",
      "name": "AI - Classify & Draft",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const raw = $input.first().json.message?.content || $input.first().json.choices?.[0]?.message?.content || '{}';\nlet parsed;\ntry {\n  const cleaned = raw.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n  parsed = JSON.parse(cleaned);\n} catch(e) {\n  parsed = { category: 'other', confidence: 0.1, response: raw, summary: 'Parse error' };\n}\n\nconst formData = $('Format Order Data').first().json;\n\nreturn [{ json: {\n  ...formData,\n  category: parsed.category,\n  confidence: parsed.confidence,\n  aiResponse: parsed.response,\n  summary: parsed.summary,\n  draftSubject: `[AI] Re: ${formData.subject || 'Your inquiry'}`,\n  submissionId: formData.submissionId\n} }];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1160,
        0
      ],
      "id": "parse-ai",
      "name": "Parse AI Response"
    },
    {
      "parameters": {
        "resource": "draft",
        "operation": "create",
        "subject": "={{ $json.draftSubject }}",
        "emailType": "text",
        "message": "={{ $json.aiResponse }}",
        "options": {
          "sendTo": "={{ $json.customerEmail }}"
        }
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1380,
        0
      ],
      "id": "create-draft",
      "name": "Create Gmail Draft",
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "=https://coffeeandpeppers.com/wp-json/fluentform/v1/submission/{{ $json.submissionId }}/status",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "read"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1600,
        0
      ],
      "id": "mark-read",
      "name": "Mark Submission Read",
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      },
      "onError": "continueRegularOutput"
    }
  ],
  "connections": {
    "Every Minute": {
      "main": [
        [
          {
            "node": "Fetch Unread Submissions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Unread Submissions": {
      "main": [
        [
          {
            "node": "Parse Submissions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Submissions": {
      "main": [
        [
          {
            "node": "Extract Order Number",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Order Number": {
      "main": [
        [
          {
            "node": "Has Order Number?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has Order Number?": {
      "main": [
        [
          {
            "node": "Get Order by Number",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Get Orders by Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Order by Number": {
      "main": [
        [
          {
            "node": "Format Order Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Orders by Email": {
      "main": [
        [
          {
            "node": "Format Order Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Order Data": {
      "main": [
        [
          {
            "node": "AI - Classify & Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI - Classify & Draft": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Create Gmail Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Gmail Draft": {
      "main": [
        [
          {
            "node": "Mark Submission Read",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

Coffee & Peppers - Contact Form AI. Uses httpRequest, openAi, gmail. Scheduled trigger; 12 nodes.

Source: https://gist.github.com/aidanvalero/f7e92c26896311042967bdf8c80475ff — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

A scheduled process aggregates content from eight distinct data sources and standardizes all inputs into a unified format. AI models perform sentiment scoring, detect conspiracy or misinformation sign

HTTP Request, OpenAI, Postgres +2
AI & RAG

This workflow monitors filesystem sync and backup jobs by validating their execution logs, not by running or inspecting the jobs themselves.

Google Cloud Storage, Gmail, GitHub +2
AI & RAG

Stop wasting billable hours on manual time-tracking. AutoTimesheet Pro uses AI to collect emails, meetings, and GitHub work, then writes a clean timesheet straight into Google Sheets. Perfect for deve

Google Calendar, Gmail, GitHub +3
AI & RAG

Imagine a dedicated financial expert tirelessly working behind the scenes, sifting through every transaction, every investment move, and every accounting entry. That's exactly what this automated syst

HTTP Request, Google Sheets, OpenAI +3
AI & RAG

Who is this for? AI creators, marketers, agencies, and researchers tracking YouTube trends who need weekly high-signal insights without 4+ hours manual research.

HTTP Request, OpenAI, Google Sheets +2