{
  "name": "Fetch reliable FX exchange rates with Frankfurter and open.er-api",
  "nodes": [
    {
      "id": "9b76fbe7-d643-4f54-b334-bfca4491f887",
      "name": "Set Currencies",
      "type": "n8n-nodes-base.set",
      "position": [
        176,
        -304
      ]
    },
    {
      "id": "b070066b-cf98-4e19-88e3-11028547d74e",
      "name": "If Valid Data",
      "type": "n8n-nodes-base.if",
      "position": [
        624,
        -208
      ]
    },
    {
      "id": "cc9c9a7f-41d2-4825-9138-4bebf7d45a6a",
      "name": "Stop and Error",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        848,
        -112
      ]
    },
    {
      "id": "77db9040-880b-4a9c-aa92-8cbb2eae8cc9",
      "name": "Frankfurter",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1296,
        -304
      ]
    },
    {
      "id": "f2e4e674-d014-41df-9b14-7520e7dd40e5",
      "name": "Normalize Frankfurter",
      "type": "n8n-nodes-base.code",
      "position": [
        1744,
        -400
      ]
    },
    {
      "id": "bdb88e3b-d12a-46eb-ae4b-5a308173d12c",
      "name": "open.er-api.com",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2416,
        -224
      ]
    },
    {
      "id": "c327f7b4-1547-4c89-a2e6-98895601048d",
      "name": "If base correct 1",
      "type": "n8n-nodes-base.if",
      "position": [
        1520,
        -304
      ]
    },
    {
      "id": "585cb49c-716d-41bc-8f30-eae30b2e50b4",
      "name": "If base correct  2",
      "type": "n8n-nodes-base.if",
      "position": [
        2640,
        -224
      ]
    },
    {
      "id": "930d6e7c-1d0b-457a-a396-cf6b83c467d7",
      "name": "Fetch FX Rates",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        176,
        -112
      ]
    },
    {
      "id": "4a5f1c28-820c-49b6-be4b-7cee3f68b897",
      "name": "Stop and Error3",
      "type": "n8n-nodes-base.stopAndError",
      "position": [
        3536,
        -176
      ]
    },
    {
      "id": "ef99aeb2-f5a0-472d-8a67-2575454e27fd",
      "name": "Normalize open.er-api.com",
      "type": "n8n-nodes-base.code",
      "position": [
        2864,
        -320
      ]
    },
    {
      "id": "e170996f-5970-46ce-8bf1-8de7596e3cc5",
      "name": "Handle Wrong Base 1",
      "type": "n8n-nodes-base.code",
      "position": [
        1744,
        -208
      ]
    },
    {
      "id": "e2e8d53f-a585-4a1c-b1f6-fae93fbe1f92",
      "name": "Handle Wrong Base 2",
      "type": "n8n-nodes-base.code",
      "position": [
        2864,
        -128
      ]
    },
    {
      "id": "9f4e28ec-480c-4581-8d86-b6a4b6d47502",
      "name": "Trim",
      "type": "n8n-nodes-base.code",
      "position": [
        3760,
        -464
      ]
    },
    {
      "id": "f22fcecd-6344-44af-a487-b82dc34e1498",
      "name": "If Trim",
      "type": "n8n-nodes-base.if",
      "position": [
        3536,
        -400
      ]
    },
    {
      "id": "ec7a2f04-a6c8-47b0-bf16-2ceb0fd7eb62",
      "name": "Manual Trigger (Example)",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -48,
        -304
      ]
    },
    {
      "id": "bf019fea-6cc2-4076-b16b-a6cf4c051d6c",
      "name": "Validate & Normalize Inputs",
      "type": "n8n-nodes-base.code",
      "position": [
        400,
        -208
      ]
    },
    {
      "id": "528a4062-c9a8-4924-b859-3b5aa377ebc1",
      "name": "Initialize FX State + Static Rates",
      "type": "n8n-nodes-base.code",
      "position": [
        848,
        -304
      ]
    },
    {
      "id": "030de89f-2d67-425f-819b-5f7daf12a696",
      "name": "Initialize Coverage Tracking",
      "type": "n8n-nodes-base.code",
      "position": [
        1072,
        -304
      ]
    },
    {
      "id": "c8922d5e-2baf-4e5e-b29e-02a9596f4608",
      "name": "Merge Rates & Check Coverage (1)",
      "type": "n8n-nodes-base.code",
      "position": [
        1968,
        -304
      ]
    },
    {
      "id": "4cd57cab-a81c-4a2a-8594-bc5bf062b91c",
      "name": "Merge Rates & Check Coverage (2)",
      "type": "n8n-nodes-base.code",
      "position": [
        3088,
        -224
      ]
    },
    {
      "id": "c357635b-f4e8-4c6b-819c-f79442792da3",
      "name": "Coverage Complete 1?",
      "type": "n8n-nodes-base.if",
      "position": [
        2192,
        -304
      ]
    },
    {
      "id": "77e273fc-fc8d-4716-8192-366f855c7a26",
      "name": "Coverage Complete 2?",
      "type": "n8n-nodes-base.if",
      "position": [
        3312,
        -224
      ]
    },
    {
      "id": "9072a67f-0e25-4d4a-9d06-04e2d0027ec7",
      "name": "Final Output",
      "type": "n8n-nodes-base.noOp",
      "position": [
        3984,
        -400
      ]
    },
    {
      "id": "5a14b24b-277d-40b5-b1be-f117d56c6330",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -1424
      ],
      "parameters": {
        "width": 580,
        "height": 894,
        "content": "# Multi-provider FX Rates Fetcher\nThis workflow fetches foreign exchange (FX) rates for a configurable base currency using multiple public APIs.\n\nIt is designed to guarantee complete coverage for the "
      }
    },
    {
      "id": "b97fd36c-9e86-4bfa-8f1d-5a15ce47c232",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -464
      ],
      "parameters": {
        "width": 576,
        "height": 496,
        "content": "## Inputs\n* `trim` (boolean)\n* `baseCurrency` (string, e.g. \"EUR\")\n* `currencies` (array of string ISO currency codes, e.g [\"USD\",\"EUR\",\"IDR\",\"AED\"])\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n### Use Manual Trigger or\n##"
      }
    },
    {
      "id": "624b0a2b-ff5b-4e49-83cc-2ce2b9b000a5",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        752,
        -560
      ],
      "parameters": {
        "width": 288,
        "height": 416,
        "content": "## Optional static rates\n* You can define fixed FX rates here. Static rates always override provider results.\n\ne.g. \nif (base === 'USD') {\n   staticRates.AED = 3.6725;\n   staticMeta.AED = 'static_usd_"
      }
    },
    {
      "id": "f848ff8c-83d2-4622-aeee-64a4f1cd3e82",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2352,
        -464
      ],
      "parameters": {
        "width": 1120,
        "height": 512,
        "content": "## Optional expand providers\n* Clone this nodes to expand your fetcher with another provider and connect the clones to Stop and Error3 node."
      }
    }
  ],
  "connections": {
    "Trim": {
      "main": [
        [
          {
            "node": "Final Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Trim": {
      "main": [
        [
          {
            "node": "Trim",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Final Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Frankfurter": {
      "main": [
        [
          {
            "node": "If base correct 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Valid Data": {
      "main": [
        [
          {
            "node": "Initialize FX State + Static Rates",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop and Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch FX Rates": {
      "main": [
        [
          {
            "node": "Validate & Normalize Inputs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Currencies": {
      "main": [
        [
          {
            "node": "Validate & Normalize Inputs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "open.er-api.com": {
      "main": [
        [
          {
            "node": "If base correct  2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If base correct 1": {
      "main": [
        [
          {
            "node": "Normalize Frankfurter",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Wrong Base 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If base correct  2": {
      "main": [
        [
          {
            "node": "Normalize open.er-api.com",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Wrong Base 2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Wrong Base 1": {
      "main": [
        [
          {
            "node": "Merge Rates & Check Coverage (1)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Wrong Base 2": {
      "main": [
        [
          {
            "node": "Merge Rates & Check Coverage (2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Coverage Complete 1?": {
      "main": [
        [
          {
            "node": "If Trim",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "open.er-api.com",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Coverage Complete 2?": {
      "main": [
        [
          {
            "node": "If Trim",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Stop and Error3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Frankfurter": {
      "main": [
        [
          {
            "node": "Merge Rates & Check Coverage (1)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Manual Trigger (Example)": {
      "main": [
        [
          {
            "node": "Set Currencies",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize open.er-api.com": {
      "main": [
        [
          {
            "node": "Merge Rates & Check Coverage (2)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate & Normalize Inputs": {
      "main": [
        [
          {
            "node": "If Valid Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initialize Coverage Tracking": {
      "main": [
        [
          {
            "node": "Frankfurter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Rates & Check Coverage (1)": {
      "main": [
        [
          {
            "node": "Coverage Complete 1?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Rates & Check Coverage (2)": {
      "main": [
        [
          {
            "node": "Coverage Complete 2?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Initialize FX State + Static Rates": {
      "main": [
        [
          {
            "node": "Initialize Coverage Tracking",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}