{
  "id": "fiwano-universal-auto-responder",
  "name": "Fiwano \u2014 Universal Auto-Responder (WhatsApp + Instagram + Facebook)",
  "nodes": [
    {
      "parameters": {
        "content": "## Universal Auto-Responder\n### WhatsApp \u00b7 Instagram \u00b7 Facebook\n\n**One trigger, three channels.** A user messages any connected channel \u2192 instant reply. No per-channel code.\n\n- **Text** \u2192 echoed back.\n- **Anything else** (image, audio, video, document\u2026) \u2192 a reply describing the attachment.\n\n### Before you start\n**Connect at least one channel first** \u2014 use the *Connect a Channel* workflow, or the [Fiwano portal](https://fiwano.com). The responder wires itself to channels you've already connected; with none connected, there's nothing to reply on.\n\n### Setup\n1. Add your **Fiwano API** credential to the Trigger and both reply nodes.\n2. *(Recommended)* Set a **Webhook Secret** on that **credential** \u2014 the Trigger uses it to verify incoming signatures. (The node's own Webhook Secret field is just an override; leave it empty to use the credential's.)\n3. **Save & Activate.**\n\n### What activation does\nThe Trigger is set to **Auto-Setup \u2192 All Active Channels**: on activation it points **every active channel** at this workflow at once \u2014 registering its webhook URL, the selected **Event Types**, and the credential's secret. Connect a channel later? Re-activate to wire it. Deactivating clears the webhook again.\n\nKeep **Event Types** on *Message Received*. n8n must be publicly reachable.\n\n[Docs](https://fiwano.com/documentation/n8n) \u00b7 [Get an API key](https://fiwano.com)",
        "height": 954,
        "width": 504,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -496,
        192
      ],
      "id": "bb2c0002-0002-4000-8000-000000000001",
      "name": "About this workflow"
    },
    {
      "parameters": {
        "autoSetup": "all"
      },
      "type": "n8n-nodes-fiwano.fiwanoTrigger",
      "typeVersion": 1,
      "position": [
        128,
        432
      ],
      "id": "bb2c0002-0002-4000-8000-000000000002",
      "name": "Fiwano Trigger"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "is-text",
              "leftValue": "={{ $json.data.type }}",
              "rightValue": "text",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        400,
        432
      ],
      "id": "bb2c0002-0002-4000-8000-000000000003",
      "name": "Is it a text message?"
    },
    {
      "parameters": {
        "channelId": "={{ $json.channel_id }}",
        "recipient": "={{ $json.data.from }}",
        "text": "=You said: \"{{ $json.data.text }}\" \ud83d\udc4b"
      },
      "type": "n8n-nodes-fiwano.fiwano",
      "typeVersion": 1,
      "position": [
        688,
        304
      ],
      "id": "bb2c0002-0002-4000-8000-000000000004",
      "name": "Reply \u2014 text echo"
    },
    {
      "parameters": {
        "channelId": "={{ $json.channel_id }}",
        "recipient": "={{ $json.data.from }}",
        "text": "=Got your {{ $json.data.type }} \ud83d\udcce \u2014 {{ ($json.data.media || {}).mime_type || 'attachment' }}. Thanks!"
      },
      "type": "n8n-nodes-fiwano.fiwano",
      "typeVersion": 1,
      "position": [
        688,
        544
      ],
      "id": "bb2c0002-0002-4000-8000-000000000005",
      "name": "Reply \u2014 attachment info"
    },
    {
      "parameters": {
        "content": "### \ud83d\udce5 What's in each message\n\nSame shape for all 3 channels (`$json` on the trigger):\n\n- `channel_id` \u2014 which channel\n- `data.from` \u2014 sender \u2192 use as reply recipient\n- `data.from_name` \u2014 name (WhatsApp only; `null` on IG/FB)\n- `data.type` \u2014 a **closed set**, safe to switch on: `text`, `image`, `audio`, `video`, `document`, `sticker` (WhatsApp only, inbound only), `unsupported`\n- `data.text` \u2014 the text (when `type = text`)\n- `data.caption` \u2014 text sent *with* a file (all channels)\n- `data.media` \u2014 `media_id`, `mime_type`, `file_size`, `filename`\u2026 (for media)\n\n`unsupported` means no file is coming: `data.unsupported_type` says what Meta sent, and `data.upgrade_required` marks the cases a **Pro** licence would have delivered.\n\nEach attachment of an album arrives as its **own** execution.\n\n### \u26a0\ufe0f Sends answer HTTP 200 even when they fail\nThe reply node stays green either way \u2014 the outcome is in `success` and `status` (`sent` / `queued` / `failed`). Branch on `{{ $json.success }}` if a failed reply must be noticed.",
        "height": 626,
        "width": 668,
        "color": 4
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1232,
        496
      ],
      "id": "bb2c0002-0002-4000-8000-000000000006",
      "name": "Payload cheat-sheet"
    },
    {
      "parameters": {
        "content": "## \ud83d\udce4 Sending media\n\n**Meta fetches outbound media by URL.** `Send Media` takes a `media_url` and Meta downloads it itself \u2014 so the file has to sit at an HTTPS address Meta can reach anonymously. Use a signed URL (S3/GCS/R2 presigned, Azure SAS) for anything non-public, with an expiry of \u2265 20 min so background retries still work. **Pro** licence required.\n\nThat is all you need for normal sending \u2014 pointing at your own images, invoices, reports.\n\n### Echoing a received file back\n\nExtra step, because the inbound `download_url` requires your `X-API-Key` and Meta will not send it. Fetch the bytes with **Media \u2192 Download**, then republish them somewhere Meta can fetch \u2014 your object storage, or any small HTTPS endpoint of your own. Files expire ~60 min after arrival.\n\n`sticker` is inbound-only (WhatsApp): re-send it as `image`.",
        "height": 629,
        "width": 420,
        "color": 7
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1952,
        496
      ],
      "id": "bb2c0002-0002-4000-8000-000000000007",
      "name": "Sending media"
    }
  ],
  "connections": {
    "Fiwano Trigger": {
      "main": [
        [
          {
            "node": "Is it a text message?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is it a text message?": {
      "main": [
        [
          {
            "node": "Reply \u2014 text echo",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Reply \u2014 attachment info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate"
  },
  "tags": []
}