RapidfolioRapidfolio
API Reference

Manage Runs

Poll run status, retrieve results, cancel runs, and implement reliable polling patterns with the Rapidfolio Runner API.

Get Run Status

GET https://run.rapidfolio.com/runs/:runId
Authorization: Bearer <api_key>

Returns the current state of a run, including its inputs, outputs, and timing.

Response

{
  "id": "run_clxyz123",
  "status": "completed",
  "type": "api",
  "environment": "sandbox",
  "input": { "customerId": "cust_123" },
  "output": { "approved": true },
  "error": null,
  "startedAt": "2026-02-27T10:00:00.000Z",
  "completedAt": "2026-02-27T10:00:05.000Z",
  "createdAt": "2026-02-27T10:00:00.000Z",
  "procedureVersionId": "ver_abc"
}

Response Fields

FieldTypeDescription
idstringThe run ID
statusstringCurrent status — see Status Values
typestringHow the run was triggered: api, trigger, or manual
environmentstringsandbox or live
inputobjectThe input data the run was started with
outputobject | nullThe procedure's final output, once completed
errorstring | nullError message if the run failed or was rejected
startedAtstring | nullISO 8601 timestamp when execution began
completedAtstring | nullISO 8601 timestamp when the run reached a terminal state
createdAtstringISO 8601 timestamp when the run record was created
procedureVersionIdstringThe specific procedure version that was executed

Status Values

StatusDescription
pendingQueued but not yet started
runningActively executing
awaiting_reviewPaused at a Human Review node — waiting for a reviewer decision
completedFinished successfully — output is populated
failedFinished with an error — error describes what went wrong
cancelledManually cancelled before reaching a terminal state

The terminal statuses are completed, failed, and cancelled. Once a run reaches one of these statuses it will not change again.


Cancel a Run

POST https://run.rapidfolio.com/runs/:runId/cancel
Authorization: Bearer <api_key>

Cancels a run that is in pending or running status. Runs that are awaiting_review can also be cancelled. Runs that have already reached a terminal state (completed, failed, cancelled) cannot be cancelled.

Success Response — 200

{ "success": true }

Error Response — 409

{ "error": "Run is already in a terminal state" }

Polling Pattern

When you start a run in async mode, you receive a runId and a statusUrl. Poll statusUrl until the run reaches a terminal status.

Use exponential backoff to avoid hammering the API — start with a short interval and increase it on each poll.

async function pollUntilDone(
  runId: string,
  apiKey: string,
  options: { initialIntervalMs?: number; maxIntervalMs?: number; timeoutMs?: number } = {}
): Promise<RunResult> {
  const {
    initialIntervalMs = 1000,
    maxIntervalMs = 15000,
    timeoutMs = 300000,
  } = options

  const terminalStatuses = new Set(['completed', 'failed', 'cancelled'])
  const startTime = Date.now()
  let intervalMs = initialIntervalMs

  while (true) {
    if (Date.now() - startTime > timeoutMs) {
      throw new Error(`Polling timed out after ${timeoutMs}ms for run ${runId}`)
    }

    await sleep(intervalMs)

    const response = await fetch(`https://run.rapidfolio.com/runs/${runId}`, {
      headers: { Authorization: `Bearer ${apiKey}` },
    })

    if (!response.ok) {
      throw new Error(`Failed to fetch run status: ${response.status}`)
    }

    const run = await response.json() as RunResult

    if (terminalStatuses.has(run.status)) {
      return run
    }

    // Exponential backoff with jitter
    intervalMs = Math.min(intervalMs * 1.5 + Math.random() * 500, maxIntervalMs)
  }
}

function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms))
}

Tip: If you are polling frequently or have many concurrent runs, consider using webhooks instead. Webhooks push completion events to your server the moment they occur, eliminating polling entirely.


Handling Each Terminal Status

Once polling returns a terminal status, branch on run.status:

const run = await pollUntilDone(runId, apiKey)

switch (run.status) {
  case 'completed':
    // Use run.output
    console.log('Procedure completed:', run.output)
    break
  case 'failed':
    // run.error contains the failure reason
    console.error('Procedure failed:', run.error)
    break
  case 'cancelled':
    console.warn('Run was cancelled')
    break
}

On this page