Loop over items until found in API

Hey everyone :waving_hand:

I’m building an automation in n8n that processes track & trace numbers. The system needs to look up tracking info over a rolling date range — specifically from today up to three weeks earlier (21 days total).

However, I don’t want to make 21 API requests every time if I can avoid it. Ideally, I’d like a workflow that:

  • Checks today’s data first.
  • If a given track & trace number isn’t found, it then checks the previous day.
  • Continues doing that until it’s found or until it reaches the 21-day cutoff.

Some track & trace numbers might show up in different days — for example, one might appear today, another might only be found 2 days ago, etc.

So it’s not a single dataset per day — I might need to “merge” or accumulate results across multiple days until all items are found.


I could brute-force this with 21 requests (one per day), but that feels inefficient.

What I’d prefer is some kind of loop that:

  1. Tries a date,
  2. Filters out any track numbers that were found,
  3. Moves to the next (previous) date only for the ones that are still missing,
  4. Stops after 21 iterations or once all are found.

:toolbox: Additional Details

  • The API I’m calling accepts a date parameter and returns a list of tracking results.
  • I’m using an HTTP Request node to get the data.
  • I can handle merging or filtering with Code or IF nodes, but I’m not sure about the best workflow for this search-until-found behavior.

Hey @OpenSourceSimon,

This looks interesting!

To help us get started, do you have any mock data or an initial draft of the workflow?

Also, are databases allowed or is that off the table?

Hey @mohamed3nan,

Thanks for your reply. Attached is a screenshot of the current workflow. I tried mimicking the workflow to publish it here, but that didn’t succeed.

The merge8 node brings together the items that need to be searched in the API. The code in JavaScript searches the earliest ShipmentDate and returns 21 items (including that date)

[
  {
    "ShipmentDate": "2025-10-22"
  },
  {
    "ShipmentDate": "2025-10-23"
  },
  {
    "ShipmentDate": "2025-10-24"
  },
  {
    "ShipmentDate": "2025-10-25"
  },
  {
    "ShipmentDate": "2025-10-26"
  },
  {
    "ShipmentDate": "2025-10-27"
  },
  {
    "ShipmentDate": "2025-10-28"
  },
  {
    "ShipmentDate": "2025-10-29"
  },
  {
    "ShipmentDate": "2025-10-30"
  },
  {
    "ShipmentDate": "2025-10-31"
  }
]

The HTTP request fetches all the results on those dates (including pagination) and then the array’s of the API are split up so all the items from the API are ready for merging. The merge node then matches items of the input compared to what the API gave back with a corresponding Track and Trace number.

Databases are definitely allowed, but only if that’s the right solution. If this could be solved natively in n8n which would be more efficient, I’d prefer that. Otherwise, a database solution would sound good.

Let me know if I can provide any additional context. This proces is part of a complicated workflow, so I tried simplifying the question on this forum.

If you cannot improve the API you are calling, then the best approach is probably to do something like this:

  1. Pre-create a table (n8n now supports tables) or a database with a table containing all the records you have processed in the past. The sample JSON output you shared does not include a unique identifier, but I assume you will obtain one in the production environment. If not, you will need to devise a method for creating one.
  2. Using n8n nodes to calculate dates and run backfilter API calls sounds a bit messy to implement, so I suggest you start by adding a code node that calculates the `currentDate`, the current date - 21. Then, have the code node execute the API calls as many times as necessary. The output should be JSON, with each item as its own separate entity. This means that if you have, say, eight records to process from the last 21 days, then eight records are output from the code node.
  3. Let’s say you are using n8n Tables, insert that node with if row does not exist, filling out the matching field criteria (like a unique identifier), and then processing each row.
  4. Once the processing is complete, you add the row to the table so it will not be processed again.

Since your code node outputs each record as its own JSON element, you will not have to do any looping (eight records = eight runs in n8n).

I did not test this code and had ChatGPT create it, but here is an example of how you might get started with looping through the past 21 days using a code (JavaScript) node:

// n8n Code Node: Run Once for All Items

// Wrap everything in an immediately invoked async function
return (async () => {
  // Helper: format date as YYYY-MM-DD
  function formatDate(date) {
    return date.toISOString().split('T')[0];
  }

  const today = new Date();
  const cutoff = new Date(today);
  cutoff.setDate(today.getDate() - 21);

  let currentDate = new Date(today);

  /** @type {{ [key: string]: any }[]} */
  let allShipments = [];

  // Loop backward in time, calling the API until reaching cutoff
  while (currentDate >= cutoff) {
    const dateStr = formatDate(currentDate);

    // Example API call (replace URL with your endpoint)
    const response = await $httpRequest({
      method: 'GET',
      url: `https://api.example.com/shipments?date=${dateStr}`,
      headers: { Authorization: 'Bearer your_token_here' },
    });

    // Combine all results
    if (response && Array.isArray(response)) {
      allShipments = allShipments.concat(response);
    }

    // Move to previous day
    currentDate.setDate(currentDate.getDate() - 1);
  }

  // Return all shipments
  return allShipments.map(item => ({ json: item }));
})();

I hope this helps. -Bill

Bill is correct with using datatables or a database whenever possible as native or local tables are waaaay faster than holding data outside of N8N or on some external sheet or db you call over the internet.

From the looping perspective (and only looping and possibly processing) this might give you a direction to go in.