HTTP request consulting in loop

Hi there,
I was wondering how I can do looping and consulting a range inside an array.
The looping must get the length of the array and do an HTTP request for each position in the array.

{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        290,
        380
      ]
    },
    {
      "parameters": {
        "functionCode": "number = items[0].json.COUNTER += 1\nreturn [\n  {\n    json: {\n      COUNTER: number\n    }\n  }\n]\n"
      },
      "name": "increment",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        670,
        200
      ]
    },
    {
      "parameters": {
        "functionCode": "//return [{json:{postCode: 'LA96RA'}}]\nconst postCodeList = ['LA96RA','DA145DL','PH263AE','BH118QX','IG80SU','BD108LZ','TA116LA','GL538AN','TS69DQ','GU342DS']\nconst counter = items[0].json.COUNTER\n\nif(postCodeList.length <= counter){\n  return arr\n}\n\npostCodeList.forEach((elem, index) => {\n  if(index == counter){\n     return {json: {\n          postCode: [{json:{postCode: elem}}], \n    }}\n  }\n})\n"
      },
      "name": "loop",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        870,
        380
      ]
    },
    {
      "parameters": {
        "values": {
          "number": [
            {
              "name": "COUNTER",
              "value": -1
            }
          ],
          "string": [
            {
              "name": "URI",
              "value": "https://api.postcodes.io/postcodes/"
            }
          ]
        },
        "options": {}
      },
      "name": "startCounter",
      "type": "n8n-nodes-base.set",
      "typeVersion": 1,
      "position": [
        540,
        380
      ]
    },
    {
      "parameters": {
        "url": "={{$node[\"startCounter\"].json[\"URI\"]}}{{$json[\"postCode\"]}}",
        "options": {}
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1270,
        360
      ]
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json[\"status\"]}}",
              "operation": "equal",
              "value2": 200
            }
          ]
        }
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1460,
        360
      ]
    },
    {
      "parameters": {},
      "name": "OKAY",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        540,
        50
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$node[\"loop\"].parameter[\"functionCode\"]}}",
              "value2": "// IF ARR == NULL then finish the process"
            }
          ]
        }
      },
      "name": "IF1",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1060,
        380
      ]
    },
    {
      "parameters": {},
      "name": "END",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1240,
        580
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "startCounter",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "increment": {
      "main": [
        [
          {
            "node": "loop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "loop": {
      "main": [
        [
          {
            "node": "IF1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "startCounter": {
      "main": [
        [
          {
            "node": "loop",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "OKAY",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "increment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OKAY": {
      "main": [
        [
          {
            "node": "increment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF1": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "END",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Hi @tuliovargas, from looking at your workflow it’s unfortunately not totally clear to me what you want to achieve here. Are you trying to make HTTP Requests for each of the postal codes from your list ['LA96RA','DA145DL','PH263AE','BH118QX','IG80SU','BD108LZ','TA116LA','GL538AN','TS69DQ','GU342DS']? This would not require building a loop manually as the HTTP Request node would run once for each incoming item by default. This is the default behaviour for most nodes, exceptions are listed here in the docs.

So a simple way of making an API request for each of these postal codes would be to spread them into single items and then just follow up with the HTTP Request node.

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "url": "=https://api.postcodes.io/postcodes/{{$json[\"postal_codes\"]}}",
        "options": {}
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [{\n  json: {\n    postal_codes: ['LA96RA','DA145DL','PH263AE','BH118QX','IG80SU','BD108LZ','TA116LA','GL538AN','TS69DQ','GU342DS']\n  }\n}];"
      },
      "name": "Set Postal Codes",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "fieldToSplitOut": "postal_codes",
        "options": {}
      },
      "name": "Split Out Postal Codes",
      "type": "n8n-nodes-base.itemLists",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Set Postal Codes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Postal Codes": {
      "main": [
        [
          {
            "node": "Split Out Postal Codes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Postal Codes": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

This would then return individual items for each postal code you pass on:

Hi @MutedJam,
my intention is do loop for each position into the array, for instance, initially, it must collect the array size and then use the COUNTER variable to walk through the array, for each array’s position, it must perform an HTTP request and after it, COUNTER variable will receive an increment (+1) and so the loop continues to the next positions in the array.

Hi @tuliovargas, that’s pretty much what my example workflow does - it goes through each element in your postal code array and runs an HTTP request for it.

@MutedJam ,
I am using the version 0.137.0, and this ItemList is available from the 0-138-0.

I will update it, thank you

1 Like

Ah I see - great to see you can update to a later version. If that would be a problem for any reason, you could also replace it with a Function node so you can free yourself from the loop :slight_smile:

@MutedJam ,
Is it possible to create something like a result per page?

If you really need one result per execution you could just avail of the simplicity first and then split everything in batches of 1 at the end like so:

Example Workflow
{
  "nodes": [
    {
      "parameters": {
        "url": "=https://api.postcodes.io/postcodes/{{$json[\"postal_codes\"]}}",
        "options": {}
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [{\n  json: {\n    postal_codes: ['LA96RA','DA145DL','PH263AE','BH118QX','IG80SU','BD108LZ','TA116LA','GL538AN','TS69DQ','GU342DS']\n  }\n}];"
      },
      "name": "Set Postal Codes",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "fieldToSplitOut": "postal_codes",
        "options": {}
      },
      "name": "Split Out Postal Codes",
      "type": "n8n-nodes-base.itemLists",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "name": "SplitInBatches",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        1050,
        300
      ]
    },
    {
      "parameters": {},
      "name": "NoOp",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1250,
        450
      ]
    }
  ],
  "connections": {
    "HTTP Request": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Postal Codes": {
      "main": [
        [
          {
            "node": "Split Out Postal Codes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Postal Codes": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SplitInBatches": {
      "main": [
        [
          {
            "node": "NoOp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "NoOp": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

But in this case, the “HTTP Request” has still been called once, and I was wondering if I can do like it:

The 1 would only indicate the number of workflow executions, not the number of times it has made a request. It would still make 10 individual requests, one for each postal code. There is no functional difference, Split In Batches would just add complexity here but not change the functionality.

That said, you can still place the HTTP Request node after the Split In Batches node if you prefer that approach for any reason:

Workflow Example
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "url": "=https://api.postcodes.io/postcodes/{{$json[\"postal_codes\"]}}",
        "options": {}
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1050,
        450
      ]
    },
    {
      "parameters": {
        "functionCode": "return [{\n  json: {\n    postal_codes: ['LA96RA','DA145DL','PH263AE','BH118QX','IG80SU','BD108LZ','TA116LA','GL538AN','TS69DQ','GU342DS']\n  }\n}];"
      },
      "name": "Set Postal Codes",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "fieldToSplitOut": "postal_codes",
        "options": {}
      },
      "name": "Split Out Postal Codes",
      "type": "n8n-nodes-base.itemLists",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "name": "SplitInBatches",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Set Postal Codes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Postal Codes": {
      "main": [
        [
          {
            "node": "Split Out Postal Codes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Postal Codes": {
      "main": [
        [
          {
            "node": "SplitInBatches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SplitInBatches": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

@MutedJam , let me explain the reason I want to break the HTTP request in many called, for example, insert inside the array an invalid postcode, like ERROR:

postal_codes: [‘LA96RA’,‘DA145DL’,‘PH263AE’,‘ERROR’,‘BH118QX’,‘IG80SU’,‘BD108LZ’,‘TA116LA’,‘GL538AN’,‘TS69DQ’,‘GU342DS’]

Thus, it will invalidate the whole process, instead of only not doing one call.

If you want to handle errors in the workflow you could enable the Ignore Response Code option of the HTTP request node:

image

You could then use an IF node to identify the error, for example like so:

Example Workflow
{
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        250,
        300
      ]
    },
    {
      "parameters": {
        "url": "=https://api.postcodes.io/postcodes/{{$json[\"postal_codes\"]}}",
        "options": {
          "ignoreResponseCode": true
        }
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        850,
        300
      ]
    },
    {
      "parameters": {
        "functionCode": "return [{\n  json: {\n    postal_codes: ['LA96RA','ERROR','DA145DL','PH263AE','BH118QX','IG80SU','BD108LZ','TA116LA','GL538AN','TS69DQ','GU342DS']\n  }\n}];"
      },
      "name": "Set Postal Codes",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "fieldToSplitOut": "postal_codes",
        "options": {}
      },
      "name": "Split Out Postal Codes",
      "type": "n8n-nodes-base.itemLists",
      "typeVersion": 1,
      "position": [
        650,
        300
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json[\"error\"]}}",
              "value2": "Invalid postcode"
            }
          ]
        }
      },
      "name": "Invalid postcode error?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1050,
        300
      ]
    },
    {
      "parameters": {},
      "name": "Error Handling",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1250,
        200
      ]
    },
    {
      "parameters": {},
      "name": "Success Path",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1250,
        400
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Set Postal Codes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Invalid postcode error?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Postal Codes": {
      "main": [
        [
          {
            "node": "Split Out Postal Codes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out Postal Codes": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Invalid postcode error?": {
      "main": [
        [
          {
            "node": "Error Handling",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Success Path",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Great tip !!! It will be very helpful.
Thanks so much

1 Like

You are most welcome!

Also, just to clarify, I am not trying to stop you from using the Split in Batches node - I just wanted to make it clear that in most instances it’s not required :smiley: