n8n daily workflow: schedule → API → Slack digest

n8n builders — here’s a workflow outline for **daily contract monitoring by industry + state**. Would love feedback on pagination and rate limits.

**Flow:**

1. **Schedule Trigger** — weekdays 7am

2. **HTTP Request** — GET opps (store API key in n8n credentials):

```bash

GET https://moltawards.com/api/v1/opps?with_adjacency=true&type=federal&state=TX&limit=25

Authorization: Bearer {{$env.MOLTAWARDS_API_KEY}}

```

3. **IF** — count > 0

4. **Code** — map each row: `title`, `adjacency_narrative`, `money.place_of_performance`, `moltawards_url`

5. **Slack** — post to `#contracts`

**Gotcha:** Right after register, `/opps` may return zero rows for ~30–60 s. Poll `/agents/status` first.

Test kit: MoltAwards/TEST_KIT.md at main · matchawards/MoltAwards · GitHub

Hi, this workflow structure looks good.

For pagination, I would first check how the API returns the next page. If it returns a next URL, you can use the HTTP Request node pagination option with “Response Contains Next URL”. If it uses page, offset, or cursor, use “Update a Parameter in Each Request”.

For rate limits, I would avoid posting one Slack message per opportunity. A better pattern is:

Schedule Trigger → /agents/status → HTTP Request /opps with pagination → Code node to build one digest message → Slack

In the Code node, build one text summary, for example:

const rows = $input.all().map(item => item.json);

const message = rows.length
  ? rows.map(row =>
      `• ${row.title}\n${row.adjacency_narrative || ""}\n${row.moltawards_url}`
    ).join("\n\n")
  : "No matching opportunities found today.";

return [{ json: { message } }];

Then in the Slack node, send {{ $json.message }} to #contracts.

Practical tip: add a max page limit, for example 5 or 10 pages, so the workflow cannot loop forever if the API response changes. For rate limits, you can also add a Wait node or batch requests with Loop Over Items.

Useful docs: