When you use the Coasty Computer Use API to run task agents, you can have the server push events to your webhook URL. You need to verify each payload is authentic and not tampered with. The API signs webhooks using HMAC SHA256. This guide shows you how to verify those signatures on your server.
How webhook verification works
Coasty sends webhooks to the webhook_url you provide when you start a run. Each webhook request includes the header Coasty-Signature with a timestamp and HMAC value. The header format is t=unix_timestamp,v1=hex_signature. Your server must extract the timestamp and signature, then recompute the HMAC from the raw request body using the same secret key that you configured in the prepaid wallet. If the computed HMAC matches the v1 value, the payload is authentic. The signature also includes a timestamp to protect against replay attacks.
import os
import hmac
import hashlib
import json
from datetime import datetime, timezone
COASTY_API_KEY = os.getenv("COASTY_API_KEY")
HMAC_KEY = COASTY_API_KEY # the same key you use for signing
def verify_webhook(request_body, signature_header):
# Expected signature format: t=unix_timestamp,v1=hex_signature
parts = signature_header.split(",")
ts_part, sig_part = parts[0], parts[1]
timestamp_str = ts_part.split("=")[1]
received_sig = sig_part.split("=")[1]
# Verify timestamp (allow 5 minutes window)
timestamp = int(timestamp_str)
now = int(datetime.now(timezone.utc).timestamp())
if abs(now - timestamp) > 300:
raise ValueError("Signature timestamp too old or in the future")
# Recompute HMAC from raw body
computed_hmac = hmac.new(
HMAC_KEY.encode("utf-8"),
request_body,
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(computed_hmac, received_sig):
raise ValueError("HMAC verification failed")
# Parse payload if you need
payload = json.loads(request_body)
return payload
# Example usage (in a web framework like Flask or FastAPI):
# def webhook_handler(request):
# body = request.get_data(as_text=True)
# signature = request.headers.get("Coasty-Signature")
# if not signature:
# return "Missing signature", 401
# try:
# payload = verify_webhook(body, signature)
# # Handle payload (e.g., update DB, send notifications)
# except ValueError as e:
# return str(e), 401Webhook security best practices
- Always validate the Coasty-Signature header before acting on the payload.
- Check the timestamp to reject messages older than 5 minutes.
- Use the same API key that you configured for signing in your prepaid wallet.
- HMAC comparison should use constant-time comparison (hmac.compare_digest) to prevent timing attacks.
- Never hardcode the HMAC key in your source code; read COASTY_API_KEY from environment variables.
- If you use idempotency for reserve-and-replay operations, include Idempotency-Key in the original request.
The webhook signature header is Coasty-Signature: t=unix_timestamp,v1=hex_signature.
Where this beats brittle automation
Many automation tools rely on brittle selectors and fixed API endpoints. They break when UI changes or when an app adds a new modal. The Coasty Computer Use API lets the agent see the screen and act like a human. Webhook verification ensures you only trust events from an actual agent run, not from a malicious actor trying to spoof status updates. This combination gives you reliable endpoints for your integrations.
Now that you know how to verify webhook payloads, you can safely integrate Coasty Computer Use agents into your workflows. Start a run, provide a webhook URL, and validate each event with the HMAC signature. Get your API key at https://coasty.ai/developers and build secure, scalable automation with a real computer use agent.
Want to see this in action?
View Case Studies