{
  "name": "FlowPantry - AI drafts replies to new Google reviews for approval",
  "nodes": [
    {
      "id": "8c031c81-6056-496e-94c6-54f25ca9db0e",
      "name": "Schedule",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        0,
        300
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "days",
              "daysInterval": 1,
              "triggerAtHour": 8
            }
          ]
        }
      }
    },
    {
      "id": "3227d01e-2acf-4491-bf8b-9e17a3275299",
      "name": "Get recent reviews",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        240,
        300
      ],
      "parameters": {
        "url": "={{$env.REVIEWS_URL}}",
        "options": {}
      }
    },
    {
      "id": "96ef772d-bbe8-4db7-a760-c744cb6de494",
      "name": "Unreplied new reviews",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const s=$getWorkflowStaticData('global');s.seen=s.seen||[];const out=[];for(const i of $input.all()){const rs=Array.isArray(i.json)?i.json:(i.json.reviews||[i.json]);for(const r of rs){if(r.id&&!s.seen.includes(r.id)&&!r.reviewReply){s.seen.push(r.id);out.push({json:r});}}}s.seen=s.seen.slice(-500);return out;"
      }
    },
    {
      "id": "1fb8debc-7ad4-4ad4-bccb-0b8e1c974c56",
      "name": "Draft reply",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        300
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.openai.com/v1/chat/completions",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({model:'gpt-4o-mini', messages:[{role:'user', content: 'Write a 2-3 sentence public reply to this Google review. Voice: '+$env.BRAND_VOICE+'. Do not confirm they were a patient/client, no promises of compensation. Review ('+($json.rating||$json.starRating)+' stars) by '+($json.author||'a customer')+': '+($json.text||$json.comment||'')}]}) }}",
        "options": {}
      }
    },
    {
      "id": "2ba3093a-eb49-4af8-b323-ad4936a916bf",
      "name": "Build digest",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        960,
        300
      ],
      "parameters": {
        "mode": "runOnceForAllItems",
        "language": "javaScript",
        "jsCode": "const reviews=$('Unreplied new reviews').all();const html=$input.all().map((d,i)=>'<p><b>'+(reviews[i].json.author||'Customer')+'</b>: '+(reviews[i].json.text||reviews[i].json.comment||'')+'<br><i>Draft:</i> '+d.json.choices[0].message.content+'</p>').join('<hr>');return [{json:{html,count:reviews.length}}];"
      }
    },
    {
      "id": "205dea69-c536-40e2-88bc-c6d8ff13c8d6",
      "name": "Email drafts to owner",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1200,
        300
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.resend.com/emails",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({from: $env.FROM_EMAIL, to: $env.OWNER_EMAIL, subject: $json.count+' review reply drafts', html: $json.html}) }}",
        "options": {}
      }
    }
  ],
  "connections": {
    "Schedule": {
      "main": [
        [
          {
            "node": "Get recent reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get recent reviews": {
      "main": [
        [
          {
            "node": "Unreplied new reviews",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Unreplied new reviews": {
      "main": [
        [
          {
            "node": "Draft reply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Draft reply": {
      "main": [
        [
          {
            "node": "Build digest",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build digest": {
      "main": [
        [
          {
            "node": "Email drafts to owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {}
}