Loops

Loops

Reference article: Part of the API reference.

A loop is recurring work with an objective and triggers, such as a schedule, that decide when it runs. Each time a loop fires, Nimbus records an execution, which may start a run. These endpoints list loops and their executions, and let you fire a loop from your own systems, for example when a file lands or a deal closes.

Loops that their owner keeps private aren't visible to API keys. Loops shared with the organization are.

The Loop object

{
  "id": "6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58",
  "object": "loop",
  "name": "Weekly supplier price check",
  "objective": "Flag any supplier price change over 3% since last week.",
  "workstream": "3f6c2a1e-8b4d-4e2f-9a7c-5d1b0e6f2a94",
  "status": "active",
  "triggers": ["schedule"],
  "created": 1756201845,
  "updated": 1758190022
}
Field Type Description
id string The loop's ID.
object string Always loop.
name string Its display name.
objective string What the loop is for, in its owner's words.
workstream string or null The ID of the workstream it works in, if it has one.
status string draft, active, paused, or archived.
triggers string[] The kinds of trigger that fire it, such as schedule or webhook.
created integer or null When it was created, in Unix seconds.
updated integer or null When it last changed, in Unix seconds.

The LoopExecution object

{
  "id": "e3a8c5d2-9f1b-4e7a-b6c0-4d2f8a1e5b93",
  "object": "loop_execution",
  "loop": "6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58",
  "trigger": "manual",
  "status": "running",
  "run": "c1d7e4a9-3b8f-4c2e-9d6a-8f0b5e2c7a13",
  "reason": null,
  "created": 1758792310,
  "completed": null
}
Field Type Description
id string The execution's ID.
object string Always loop_execution.
loop string The ID of the loop.
trigger string What fired it. Executions started through the API show manual.
status string pending, skipped, running, completed, or failed.
run string or null The ID of the run it started, if any.
reason string or null Why it was skipped or failed.
created integer or null When it started, in Unix seconds.
completed integer or null When it finished, in Unix seconds.

skipped means the loop decided there was nothing to do, for example because nothing changed since its last execution. reason says why.

List loops

Returns the loops visible to API keys, newest first.

GET /v1/loops

Scope: loops:read

Parameter In Type Description
limit query integer, optional How many objects to return, 1–100. Default 20.
cursor query string, optional The next_cursor from the previous page. See Pagination.
status query string, optional Only loops with this status: draft, active, paused, or archived.

::: code-group

curl "https://api.gonimbus.ai/v1/loops?status=active" \
  -H "Authorization: Bearer $NIMBUS_API_KEY"
const response = await fetch('https://api.gonimbus.ai/v1/loops?status=active', {
  headers: { Authorization: `Bearer ${process.env.NIMBUS_API_KEY}` },
})
const { data: loops } = await response.json()
response = requests.get(
    "https://api.gonimbus.ai/v1/loops",
    params={"status": "active"},
    headers={"Authorization": f"Bearer {os.environ['NIMBUS_API_KEY']}"},
)
loops = response.json()["data"]

:::

Returns a list object of Loop objects.

Retrieve a loop

GET /v1/loops/{loop}

Scope: loops:read

Parameter In Type Description
loop path string The loop's ID.

::: code-group

curl https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58 \
  -H "Authorization: Bearer $NIMBUS_API_KEY"
const response = await fetch('https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58', {
  headers: { Authorization: `Bearer ${process.env.NIMBUS_API_KEY}` },
})
const loop = await response.json()
response = requests.get(
    "https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58",
    headers={"Authorization": f"Bearer {os.environ['NIMBUS_API_KEY']}"},
)
loop = response.json()

:::

Returns the Loop object.

List a loop's executions {#list-a-loops-executions}

Returns a loop's executions, newest first.

GET /v1/loops/{loop}/executions

Scope: loops:read

Parameter In Type Description
loop path string The loop's ID.
limit query integer, optional How many objects to return, 1–100. Default 20.
cursor query string, optional The next_cursor from the previous page.

::: code-group

curl https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58/executions \
  -H "Authorization: Bearer $NIMBUS_API_KEY"
const response = await fetch('https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58/executions', {
  headers: { Authorization: `Bearer ${process.env.NIMBUS_API_KEY}` },
})
const { data: executions } = await response.json()
response = requests.get(
    "https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58/executions",
    headers={"Authorization": f"Bearer {os.environ['NIMBUS_API_KEY']}"},
)
executions = response.json()["data"]

:::

Returns a list object of LoopExecution objects.

Run a loop now

Fires the loop as if its trigger had fired. Whatever you pass as input reaches the loop as its trigger payload, so the loop can act on it.

POST /v1/loops/{loop}/execute

Scope: loops:write · Accepts Idempotency-Key

Parameter In Type Description
loop path string The loop's ID.

The request body is optional and takes these fields:

Body field Type Description
input object, optional The trigger payload: any JSON object, up to 64 KB. If it has no source field, Nimbus adds "source": "public_api"; a source you send is kept.
force boolean, optional true to run even if nothing changed since the last execution.

::: code-group

curl https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58/execute \
  -H "Authorization: Bearer $NIMBUS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: price-file-2026-09-25" \
  -d '{"input": {"file": "prices/2026-09-25.csv", "supplier_count": 42}}'
const response = await fetch('https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58/execute', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.NIMBUS_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': 'price-file-2026-09-25',
  },
  body: JSON.stringify({ input: { file: 'prices/2026-09-25.csv', supplier_count: 42 } }),
})
const execution = await response.json()
response = requests.post(
    "https://api.gonimbus.ai/v1/loops/6b9e2f41-0c7d-4a5b-8e3f-2d1a9c4b7e58/execute",
    headers={
        "Authorization": f"Bearer {os.environ['NIMBUS_API_KEY']}",
        "Idempotency-Key": "price-file-2026-09-25",
    },
    json={"input": {"file": "prices/2026-09-25.csv", "supplier_count": 42}},
)
execution = response.json()

:::

Returns 201 with the new LoopExecution. Its status may already be skipped, with a reason, if the loop found nothing to do; send "force": true to run it anyway. An input over 64 KB fails with 400 parameter_invalid.

Example scenario

A finance team drops a supplier price file into cloud storage every Monday. Their storage system calls a small function that runs the loop now with the file's path as input, and an Idempotency-Key made from the file name, so a storage event delivered twice can't fire the loop twice. The loop compares prices and, when something changed, starts a run whose report lands in the workstream. The function stores the execution's run and reports back when the run completes.

FAQ

Why can't I see a loop that's in the app?

Its owner keeps it private. Loops shared with the organization are visible to API keys; private ones aren't. Ask the owner to share it if an integration needs it.

What does force do?

A loop can skip an execution when nothing has changed since the last one. force: true runs it regardless.

Does running a loop through the API use NTUs?

The work the loop does, such as the run it starts, uses NTUs the same way it would if the loop fired on its own schedule.

How do I know when an execution finishes?

List the loop's executions, or retrieve the run named in run and watch its status. Subscribing a webhook endpoint to run.completed and run.failed tells you without polling.

Can I create or edit loops through the API?

No. Create and change loops in the app; the API lists them and runs them.