Monitoring Torii Workflow Failures with Workato

This guide walks you through building a Workato Ruby code step that fetches workflow action execution logs from Torii, detects failed steps, and prepares the data for routing to platforms like ServiceNow or email notifications.

🔍 Use Case

Many organizations automate SaaS lifecycle actions via Torii workflows — but some steps may fail, especially when user identity mismatches occur (e.g., due to multiple email domains).

This solution enables IT teams to periodically check for failures using Torii’s public API and route them into downstream systems using Workato.


✅ Requirements

  • Torii API Key stored in a Workato HTTP connection
  • Workato Recipe with:
    • Scheduled trigger (e.g., every hour)
    • Ruby code step
    • Optional: downstream steps (e.g., create ServiceNow ticket, send email)
  • Input fields:
    • start_time (ISO8601 string)
    • end_time (ISO8601 string)

🔧 API Used

Torii Endpoint:
GET /workflows/actionExecutions
API reference →

Supports:

  • Pagination via nextCursor
  • Filtering by idActionApp or idActionUser (optional)
  • Response includes status, errorMessage, timestamps, user and app IDs

🧠 Ruby Code Step (Workato)

# Inputs:
# - input['start_time'] => "2025-10-20T00:00:00Z"
# - input['end_time']   => "2025-10-21T00:00:00Z"

base_url = "https://api.toriihq.com/v1.0/workflows/actionExecutions"
headers = {
  'Authorization' => "Bearer #{connection['api_key']}",
  'Content-Type' => 'application/json'
}

params = {
  size: 100
}

failed_actions = []
next_cursor = nil

loop do
  query_params = params.dup
  query_params[:cursor] = next_cursor if next_cursor

  response = get(base_url, headers: headers, params: query_params)
  raise "Error fetching action executions: #{response['error']}" unless response['actionExecutions']

  response['actionExecutions'].each do |action|
    created_at = Time.parse(action['creationTime'])
    next unless created_at >= Time.parse(input['start_time']) && created_at <= Time.parse(input['end_time'])

    if action['status'] == 'failed'
      failed_actions << {
        id: action['id'],
        status: action['status'],
        creation_time: action['creationTime'],
        app_id: action['idActionApp'],
        user_id: action['idActionUser'],
        error_message: action['errorMessage'],
        raw_response: action['responseBody']
      }
    end
  end

  break unless response['nextCursor']
  next_cursor = response['nextCursor']
end

failed_actions

📘 Code Explanation
Section	Purpose
base_url, headers	Configures the HTTP request to the Torii API using the connection's API key
params[:size]	Limits results per page (adjustable)
loop + nextCursor	Handles pagination to fetch all action executions
Time.parse(...)	Filters only logs within the specified time window
status == 'failed'	Identifies failed workflow steps
failed_actions << {...}	Collects relevant failure details for reporting or notifications
🧪 Example Output
[
  {
    "id": 123456,
    "status": "failed",
    "creation_time": "2025-10-20T13:45:00Z",
    "app_id": 789,
    "user_id": 456,
    "error_message": "User not found for email [email protected]",
    "raw_response": "{...}"
  }
]
You can then pass this array to downstream Workato steps like:
* ServiceNow ticket creation
* Send email with failure report
* Logging in a database or Slack channel

🛠️ Enhancements (Optional)
* Add filters for specific workflow/action IDs (idActionApp)
* Extend output with app/user metadata via separate API calls
* Implement retry logic for transient errors
* Format output into human-readable HTML or Markdown

📎 Related Links
* Torii API Reference – Action Executions
* Torii Developer Docs
* Workato Code Steps