Engineering

Verify HMAC Signatures on the Computer Use API Webhooks

Alex Thompson||5 min
Cmd+V

Webhooks from the Coasty Computer Use API let you consume live task events as Server-Sent Events (SSE). Without verification, any caller can spoof events and corrupt your state. You must validate each incoming request with an HMAC signature to guarantee it originates from Coasty and matches your secret. This guide shows how to decode and verify the signature header, so you can safely consume events and keep your automated workflows correct.

How Coasty signs webhook payloads

Coasty sends webhooks as SSE streams from GET /v1/runs/{id}/events. Each event includes a Coasty-Signature header in the form t=unix,v1=hex. The header contains a timestamp and an HMAC-SHA256 digest of the event payload. You must reconstruct that digest on your side, then compare it against the provided value. If they match, the event is authentic. Failure means discard the event and optionally retry from the last stored Last-Event-ID.

python
import os
import hmac
import hashlib
from base64 import b64decode
from datetime import datetime, timedelta

# Example event body from GET /v1/runs/{id}/events
event_body = '''{
  "id": "evt_1",
  "run_id": "run_abc123",
  "state": "running",
  "step": 42
}'''

# Signature we receive on each event, e.g. Coasty-Signature: t=1729876543,v1=abc123...
raw_signature_header = os.environ.get("COASTY_SIGNATURE_HEADER")

secret = os.environ.get("COASTY_WEBHOOK_SECRET")
assert secret, "Missing COASTY_WEBHOOK_SECRET"

# Parse the header: t=unix,v1=hex
parts = raw_signature_header.split(",")
timestamp_str, hmac_digest_str = parts[0].split("=")
unix_ts = int(timestamp_str)
provided_hmac = b64decode(hmac_digest_str)

# Reject if stale (within last 5 minutes)
if datetime.utcnow().timestamp() - unix_ts > 300:
    raise ValueError("Signature timestamp too old")

# Reconstruct HMAC-SHA256 of the event body
computed_hmac = hmac.new(
    secret.encode("utf-8"),
    event_body.encode("utf-8"),
    hashlib.sha256
).digest()

if not hmac.compare_digest(computed_hmac, provided_hmac):
    raise ValueError("HMAC mismatch")

print("Signature verified")

Replay protection with timestamps

Coasty includes a timestamp in the signature header. You must reject events older than a window (e.g., 300 seconds). This prevents replay attacks where an attacker re-sends an old event. Always use hmac.compare_digest to avoid timing leaks when comparing digests. The timestamp is part of the header format Coasty-Signature: t=unix,v1=hex.

Event flow and state recovery

When you start consuming events from GET /v1/runs/{id}/events, you may miss messages if your connection fails. Coasty supports the Last-Event-ID HTTP header to resume streaming. Store the last verified event ID in your database. On reconnect, supply Last-Event-ID to fetch missed events, then replay them in order while validating signatures. This guarantees exactly-once delivery of state updates.

Where this beats brittle automation

API-only automation often relies on brittle selectors that break when a UI changes. The Coasty Computer Use API lets you verify events that the agent actually saw and acted on. By validating webhooks, you know the server truly completed steps, so you can safely commit state without manual reconciliation. This reduces false positives and lets you build robust workflows that survive UI evolution.

Decode Coasty-Signature: t=unix,v1=hex, recalc HMAC-SHA256 of the event body, and compare with hmac.compare_digest to verify authenticity.

Now you can safely consume Coasty Computer Use API webhooks with verified HMAC signatures. Use the code above as a building block for production webhook handlers. Get your API key and start building secure automation at https://coasty.ai/developers.

Want to see this in action?

View Case Studies
Try Coasty Free