Skip to content

Polling for Results

After executing a workflow, use the status endpoint to check progress and retrieve results.

Endpoint

GET /api/v1/runs/{run_id}/status

Request

Headers

Authorization: Bearer gm_live_...

No request body is needed.

Response

Running

{
  "run_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "running",
  "progress": {
    "current_step": 2,
    "total_steps": 5,
    "current_step_name": "Generate content",
    "percentage": 40
  },
  "started_at": "2026-03-10T15:30:00Z",
  "completed_at": null,
  "result": null,
  "cost_cents": null,
  "error": null
}

Completed

{
  "run_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "progress": {
    "current_step": 5,
    "total_steps": 5,
    "current_step_name": "Post to Slack",
    "percentage": 100
  },
  "started_at": "2026-03-10T15:30:00Z",
  "completed_at": "2026-03-10T15:31:45Z",
  "result": {
    "generated_content": "Daily digest: 3 emails from team...",
    "summary": "Posted summary to #daily-digest"
  },
  "cost_cents": 15,
  "error": null
}

Failed

{
  "run_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "failed",
  "progress": {
    "current_step": 3,
    "total_steps": 5,
    "current_step_name": "Send email",
    "percentage": 60
  },
  "started_at": "2026-03-10T15:30:00Z",
  "completed_at": "2026-03-10T15:30:58Z",
  "result": null,
  "cost_cents": 8,
  "error": "Gmail connection expired. Please reconnect."
}

Status Values

Status Meaning
queued Workflow is queued and will start shortly
running Workflow is actively executing
completed Workflow finished successfully
failed Workflow encountered an error

Polling Strategy

Workflows typically complete within seconds to a few minutes, depending on the number of steps and external API latency.

Recommended polling approach:

import time
import requests

def wait_for_completion(run_id, api_key, max_wait=300, request_timeout=10):
    """Poll until workflow completes or times out."""
    url = f"https://app.gloriamundo.com/api/v1/runs/{run_id}/status"
    headers = {"Authorization": f"Bearer {api_key}"}

    start = time.monotonic()
    while time.monotonic() - start < max_wait:
        try:
            response = requests.get(url, headers=headers, timeout=request_timeout)
        except requests.exceptions.Timeout:
            # Transient timeout — continue polling until max_wait expires
            time.sleep(2)
            continue
        except requests.exceptions.RequestException as exc:
            raise RuntimeError(f"Request failed for run {run_id}: {exc}") from exc

        if response.status_code == 401:
            raise PermissionError("Invalid or expired API key (401 Unauthorized)")
        if response.status_code == 404:
            raise LookupError(f"Run {run_id} not found (404)")
        response.raise_for_status()

        data = response.json()

        if data["status"] in ("completed", "failed"):
            return data

        # Back off between polls
        time.sleep(2)

    raise TimeoutError(f"Workflow {run_id} did not complete within {max_wait}s")

Tip

Start with a 2-second polling interval. For longer-running workflows, you can increase the interval after the first few checks.

Error Responses

Status Meaning
401 Unauthorized Missing or invalid API key
404 Not Found Run not found or you don't own the workflow

Next Steps