Use this file to discover all available pages before exploring further.
You can register webhooks for each workflow to receive events. Below are the most common events.For the full list of subscribable events you can set in event_types_subscribed, see the webhook schema in the Run API reference. Some recovery events are emitted only in specific maintenance flows.
execution.start
This event is sent once when the execution of the workflow starts. It returns a live view URL of the running browser agent embeddable as iframe.
The llm_error_category field contains an AI-generated categorization of the error type. This field may be null if AI analysis was not performed.The original_error field contains the raw technical runtime error message before any AI analysis. This is useful for debugging and differs from message field that contains the Maintenance Agent’s analysis.
execution.stopped
This event is sent when one or several workflow runs were cancelled. It respectively either contains session_id of the cancelled run or session_ids that contains all of the cancelled runs.Response for single run cancelled:
{ "payload": { "message": "Execution was interrupted because another workflow was executed with the same credentials, but failed its login attempt. This is to prevent repeated incorrect login attempts.", "error_code": "INTERRUPTED-E0002", "session_causing_error": "60673dc6-92a1-428a-ba51-8c3f324daea8", "session_ids": ["60673dc6-92a1-428a-ba51-8c3f324daea8", "50673dc6-92a1-428a-ba51-8c3f324daea8"] }, "metadata": { "key1": "value1" }, "timestamp": 1724002463, "expires_at": 1724002763, "event": "execution.stopped"}
agent.tfa_setup_recovery
This event is sent when the Maintenance Agent successfully completes an automated TFA setup recovery flow during a run.
This event is sent when a run pauses because incorrect input data was detected and the workflow is waiting for corrected values. Submit corrected fields using the Submit New Input Variables endpoint to resume execution.
This event is sent when a file has been uploaded during workflow execution. The signed_file_url expiration is configurable per workspace (default: 7 days, range: 1 hour to 7 days). Configure this in your workspace settings.
We sign webhook events with the secret you get when you register a webhook. We also add an expiry time. You can change the expiry time in the setting of the registered webhook.Here’s how we recommend to verify the message you receive from us:
Python
Javascript
import timeimport hashlibimport hmacimport jsonclass VerificationError(Exception): """Custom exception to handle verification errors.""" def __init__(self, message="Verification failed", status_code=400): super().__init__(message) self.status_code = status_codedef verify_hmac(received_data, received_signature, secret_key): # Ensure the received data is in bytes, necessary for HMAC if isinstance(received_data, str): received_data = received_data.encode() # Generate the HMAC new object with the secret key and SHA-256 calculated_signature = hmac.new(secret_key.encode(), received_data, hashlib.sha256).hexdigest() # Safely compare the computed HMAC with the received HMAC return hmac.compare_digest(calculated_signature, received_signature)# Extract signature from X-HMAC-Signature header, removing the 'Sha256=' prefix# receivedData = await request.body()# receivedSignature = request.headers.get('X-HMAC-Signature').split('=')[1]# secretKey = your_secret_keydef verify_message(received_data, received_signature, secret_key): if not received_data: raise VerificationError("Received request without body", 400) try: data_json = json.loads(received_data.decode('utf-8')) except json.JSONDecodeError as e: raise VerificationError("Failed to decode json: " + str(e), 400) # Check if the expiration is sent expires_at = data_json.get("expires_at") if not expires_at: raise VerificationError("No expiration date sent", 400) # Verify HMAC first if not verify_hmac(received_data, received_signature, secret_key): raise VerificationError("Invalid HMAC signature.", 401) # Check if the message is not expired if time.time() > expires_at: raise VerificationError("Webhook message expired.", 400) return data_json
All webhook requests from CloudCruise originate from the following static IP addresses. If your infrastructure requires IP-based filtering, add these to your allowlist:
CloudCruise automatically retries failed webhook deliveries up to 3 times (4 total attempts including the initial request) with exponential backoff delays between attempts.Each delivery attempt has a 5-second request timeout. Total delivery time depends on failure mode, so retries may complete quickly for immediate network errors or take longer for repeated timeouts.