Skip to main content

Stream Run

Stream real-time ActionFlows run updates over the REST API using Server-Sent Events (SSE). Includes connection details and event payload formats.

Stream Run

Stream real-time updates for a running flow execution using Server-Sent Events (SSE).

Endpoint

GET /api/runs/{runId}/stream

Try it

Live requests run from your browser. Open the API Explorer to try every operation from one screen.

get/api/runs/{runId}/stream

Stream run updates

Requests go to the live API from your browser. The docs server never sees this key.

curl -X GET 'https://api.actionflows.ai/api/runs/{runId}/stream' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json'

Response

Send a request to see the response.

Authentication

Required. See API Reference for authentication details.

Path Parameters

ParameterTypeRequiredDescription
runIdstringYesThe unique identifier of the run (must start with run_)

Response

This endpoint returns a Server-Sent Events (SSE) stream. The response is a continuous stream of events.

Event Types

Connected Event

Sent immediately when the connection is established:

data: {"type":"connected","runId":"run_123"}

Update Event

Sent whenever the run status or data changes:

data: {"type":"update","data":{"id":"run_123","status":"EXECUTING",...}}

Completed Event

Sent when the run finishes (completed, failed, canceled, or similar):

data: {"type":"completed","status":"COMPLETED"}

Error Event

Sent if an error occurs while streaming:

data: {"type":"error","error":"Error message"}

Example Requests

JavaScript (EventSource)

const runId = 'run_123';

// Create EventSource for SSE
const eventSource = new EventSource(
  `https://api.actionflows.ai/api/runs/${runId}/stream`,
  {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
    },
  }
);

// Handle connection
eventSource.addEventListener('message', (event) => {
  const data = JSON.parse(event.data);
  
  if (data.type === 'connected') {
    console.log('Connected to stream for run:', data.runId);
  } else if (data.type === 'update') {
    console.log('Run update:', data.data);
    console.log('Status:', data.data.status);
  } else if (data.type === 'completed') {
    console.log('Run completed with status:', data.status);
    eventSource.close();
  } else if (data.type === 'error') {
    console.error('Stream error:', data.error);
    eventSource.close();
  }
});

// Handle errors
eventSource.onerror = (error) => {
  console.error('EventSource error:', error);
  eventSource.close();
};

JavaScript (Fetch with ReadableStream)

const runId = 'run_123';

async function streamRun(runId) {
  const response = await fetch(
    `https://api.actionflows.ai/api/runs/${runId}/stream`,
    {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY',
      },
    }
  );

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error || 'Stream failed');
  }

  const reader = response.body.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader.read();
    
    if (done) {
      break;
    }

    const chunk = decoder.decode(value);
    const lines = chunk.split('\n');

    for (const line of lines) {
      if (line.startsWith('data: ')) {
        const data = JSON.parse(line.slice(6));
        
        if (data.type === 'connected') {
          console.log('Connected to stream');
        } else if (data.type === 'update') {
          console.log('Update:', data.data);
        } else if (data.type === 'completed') {
          console.log('Completed:', data.status);
          return;
        } else if (data.type === 'error') {
          console.error('Error:', data.error);
          return;
        }
      }
    }
  }
}

// Use it
streamRun(runId).catch(console.error);

Python

import requests
import json

headers = {
    'Authorization': 'Bearer YOUR_API_KEY',
}

run_id = 'run_123'

response = requests.get(
    f'https://api.actionflows.ai/api/runs/{run_id}/stream',
    headers=headers,
    stream=True
)

if response.status_code != 200:
    error = response.json()
    raise Exception(error.get('error', 'Stream failed'))

for line in response.iter_lines():
    if line:
        decoded_line = line.decode('utf-8')
        if decoded_line.startswith('data: '):
            data = json.loads(decoded_line[6:])
            
            if data['type'] == 'connected':
                print(f"Connected to stream for run: {data['runId']}")
            elif data['type'] == 'update':
                print(f"Update: {data['data']}")
                print(f"Status: {data['data']['status']}")
            elif data['type'] == 'completed':
                print(f"Completed with status: {data['status']}")
                break
            elif data['type'] == 'error':
                print(f"Error: {data['error']}")
                break

cURL

curl -N -H "Authorization: Bearer YOUR_API_KEY" \
  https://api.actionflows.ai/api/runs/run_123/stream

The -N flag disables buffering for real-time streaming.

Event Data Structure

Connected Event

{
  "type": "connected",
  "runId": "run_123"
}

Update Event

{
  "type": "update",
  "data": {
    "id": "run_123",
    "status": "EXECUTING",
    "taskIdentifier": "run-flow",
    "payload": {
      "organizationId": "org_123",
      "actionFlowId": "flow_123"
    },
    "updatedAt": "2024-01-01T00:01:00.000Z"
  }
}

Completed Event

{
  "type": "completed",
  "status": "COMPLETED"
}

Possible status values: COMPLETED, FAILED, CANCELED, CRASHED, TIMED_OUT

Error Event

{
  "type": "error",
  "error": "Error message"
}

Error Responses

If the stream fails to start, you'll receive a JSON error response:

400 Bad Request

{
  "success": false,
  "error": "Invalid run ID"
}

401 Unauthorized

{
  "success": false,
  "error": "Unauthorized",
  "message": "Authentication required"
}

429 Too Many Requests

{
  "success": false,
  "error": "Too many requests"
}

Notes

  • The stream polls for updates every second
  • The stream automatically closes when the run completes, fails, or is canceled
  • You can manually close the connection by closing the EventSource or canceling the fetch request
  • The stream will send updates whenever the run status or data changes
  • Use this endpoint for real-time monitoring of long-running flows
  • This endpoint is rate-limited per user
  • The connection may timeout after extended periods of inactivity

Use Cases

  • Real-time progress monitoring
  • Live dashboards showing flow execution
  • Immediate notification when flows complete
  • Debugging long-running flows
  • Building interactive UIs that show flow progress

Browser Compatibility

For browser usage, EventSource is the recommended approach as it handles reconnection automatically. For Node.js or more control, use fetch with ReadableStream.

On this page