When your Task Runs emit events via webhooks, you need to be sure the payload actually came from Coasty. A malicious actor could craft a request that claims a run succeeded or failed when it did not. The Coasty computer use API signs every webhook request with an HMAC. You must verify this signature before processing the event. This guide shows you how to validate incoming webhooks using the Coasty-Signature header and your API key.
How webhook signatures work
Coasty sends webhooks from POST /v1/runs/{id}/events. The response is a stream of server-sent events. Each event is an HTTP request with a header named Coasty-Signature. This header contains a timestamp and an HMAC value. The header format is Coasty-Signature: t=unix,v1=hex. The timestamp is seconds since the Unix epoch. The hex string is an HMAC-SHA256 computed over the raw request body using your Coasty API key. To verify, you decode the header, recompute the HMAC on the received body, and compare the hex values. If they match, the request is authentic.
import os
import hmac
import hashlib
import json
import time
from flask import Flask, request, Response
app = Flask(__name__)
API_KEY = os.getenv("COASTY_API_KEY")
@app.route("/webhook", methods=["POST"])
def handle_webhook():
# 1. Get raw body (Flask reads into request.data)
body = request.data
# 2. Extract signature header
sig_header = request.headers.get("Coasty-Signature")
if not sig_header:
return "Missing signature", 401
# 3. Parse header (t=unix,v1=hex)
parts = sig_header.split(",")
timestamp = None
hex_signature = None
for part in parts:
if part.startswith("t="):
timestamp = int(part[2:])
elif part.startswith("v1="):
hex_signature = part[3:]
if timestamp is None or hex_signature is None:
return "Invalid signature format", 401
# 4. Reject replayed or old requests (e.g., >5 minutes old)
if abs(time.time() - timestamp) > 300:
return "Timestamp too old", 401
# 5. Compute HMAC-SHA256 of the body using your API key
computed = hmac.new(
API_KEY.encode("utf-8"),
body,
hashlib.sha256
).hexdigest()
# 6. Compare hex strings in constant-time to avoid timing attacks
if not hmac.compare_digest(computed, hex_signature):
return "Signature mismatch", 401
# 7. Payload is verified; parse and handle the event
try:
event = json.loads(body)
run_id = event.get("run_id")
status = event.get("status")
print(f"Verified event: run_id={run_id}, status={status}")
# Process your business logic here, for example:
# - Update your database record for the run
# - Trigger downstream workflows
# - Notify your team
return "OK", 200
except json.JSONDecodeError:
return "Invalid JSON body", 400
if __name__ == "__main__":
app.run(port=8080)Key webhook fields and states
- POST /v1/runs/{id}/events streams Server-Sent Events. Each event is a separate HTTP request with Coasty-Signature header.
- Each event payload is JSON. It contains run_id, status, and optional fields like error_code, message, and timestamp.
- Status values include queued, running, awaiting_human, succeeded, failed, cancelled, and timed_out.
- The Coasty-Signature header format is Coasty-Signature: t=unix,v1=hex. Extract both parts for validation.
- Use hmac.compare_digest to safely compare computed and received signatures and avoid timing side channels.
Always verify the Coasty-Signature header before processing any webhook payload.
Where this beats brittle automation
Traditional automation often relies on fragile selectors or fixed endpoints. If a UI element moves or an API contract changes, your scripts break. The Coasty computer use API lets you drive real desktops, browsers, and terminals through Task Runs. You configure a task and a webhook URL for events. The agent executes the task in a browser or desktop environment. When the run reaches a final state, Coasty sends a webhook with the status. By verifying the HMAC, you know the run state is authentic and not tampered with. This pattern works for any workflow you orchestrate with POST /v1/runs or POST /v1/workflows.
You now have a production-ready webhook verification flow for the Coasty computer use API. Use the HMAC signature to ensure that every event you receive is genuine and untampered. From here, you can build robust monitoring dashboards, trigger downstream automation, or notify your team when a Task Run succeeds or fails. Get your API key at https://coasty.ai/developers and start building resilient computer use agents today.
Want to see this in action?
View Case Studies