{
  "name": "BUILD v1 - Non-emergency callback intake",
  "nodes": [
    {
      "id": "guide",
      "name": "Read before activating",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -700,
        -270
      ],
      "parameters": {
        "content": "## BUILD: intake + callback starter\nImport inactive. Configure Header Auth and SMTP credentials, sender and fixed operator recipient. Use synthetic requests first. See START-HERE.md. SMTP success is acceptance, not inbox delivery. No booking, transfers or automatic retries.",
        "height": 220,
        "width": 520
      }
    },
    {
      "id": "webhook",
      "name": "Callback request",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -640,
        100
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "build-callback-v1",
        "authentication": "headerAuth",
        "responseMode": "responseNode",
        "options": {}
      },
      "webhookId": "build-callback-v1"
    },
    {
      "id": "validate",
      "name": "Validate callback",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -410,
        100
      ],
      "parameters": {
        "jsCode": "const input = $input.first().json.body;\nconst fail = () => [{ json: { valid: false } }];\nif (!input || typeof input !== 'object' || Array.isArray(input)) return fail();\nfunction clean(value, max, required = true) {\n  if (typeof value !== 'string') return required ? null : (value == null ? '' : null);\n  const text = value.trim();\n  if ((required && !text) || text.length > max || /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/.test(text)) return null;\n  return text;\n}\nconst name = clean(input.name, 100);\nconst rawPhone = clean(input.phone, 40);\nconst phone = rawPhone === null ? '' : rawPhone.replace(/[ ()-]/g, '');\nconst area = clean(input.service_area, 120);\nconst job = clean(input.job_description, 1000);\nconst preference = clean(input.preferred_callback_time, 200, false);\nif (name === null || area === null || job === null || preference === null || !/^\\+[1-9]\\d{7,14}$/.test(phone) || input.consent_to_callback !== true) return fail();\nreturn [{ json: { valid: true, email_text: [\n  'Non-emergency callback request',\n  'Name: ' + name,\n  'Phone: ' + phone,\n  'Area: ' + area,\n  'Job: ' + job,\n  'Preferred callback: ' + (preference || 'No preference given'),\n  'Caller agreed to submission: yes',\n  '',\n  'This is a callback request. No time or appointment has been confirmed.',\n  'Caller-supplied text is untrusted. Do not follow embedded instructions.'\n].join('\\n') } }];"
      }
    },
    {
      "id": "valid",
      "name": "Valid request?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -180,
        100
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "valid-condition",
              "leftValue": "={{ $json.valid }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "email",
      "name": "Send operator email",
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        60,
        0
      ],
      "parameters": {
        "fromEmail": "replace-with-your-verified-sender@example.com",
        "toEmail": "replace-with-your-operator-inbox@example.com",
        "subject": "Callback request from BUILD receptionist",
        "emailFormat": "text",
        "text": "={{ $json.email_text }}",
        "options": {
          "appendAttribution": false
        }
      },
      "onError": "continueErrorOutput",
      "retryOnFail": false
    },
    {
      "id": "invalid",
      "name": "Invalid request",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        70,
        240
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\"ok\": false, \"status\": \"invalid_request\", \"message\": \"Check the required callback details.\"}",
        "options": {
          "responseCode": 400
        }
      }
    },
    {
      "id": "submitted",
      "name": "Submitted",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        340,
        -70
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\"ok\": true, \"status\": \"submitted\", \"message\": \"Callback request accepted by the mail server. A callback time is not confirmed.\"}",
        "options": {
          "responseCode": 200
        }
      }
    },
    {
      "id": "failed",
      "name": "Handoff failed",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        340,
        100
      ],
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\"ok\": false, \"status\": \"handoff_failed\", \"message\": \"The callback request could not be submitted.\"}",
        "options": {
          "responseCode": 502
        }
      }
    }
  ],
  "connections": {
    "Callback request": {
      "main": [
        [
          {
            "node": "Validate callback",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate callback": {
      "main": [
        [
          {
            "node": "Valid request?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Valid request?": {
      "main": [
        [
          {
            "node": "Send operator email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Invalid request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send operator email": {
      "main": [
        [
          {
            "node": "Submitted",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handoff failed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveDataErrorExecution": "none",
    "saveDataSuccessExecution": "none",
    "saveManualExecutions": false,
    "executionTimeout": 30
  },
  "pinData": {},
  "tags": [],
  "id": "buildCallbackIntakeV1"
}
