Webhooks Planned
Approval and deployment events delivered to your endpoint as they happen. Signed, retried, ordered. This page documents a committed design, not a shipped feature.
Today's alternative
The audit log records every state change already, and it is queryable by actor, action, and time range. Polling it on a schedule gets you the same information with more latency and slightly more code on your side.
For most workflows — a nightly compliance sync, a dashboard refresh — that is genuinely sufficient. Webhooks matter when you need to react in seconds.
Committed events — 7
asset.proposedasset.approvedasset.rejecteddeployment.completeddeployment.faileddrift.detectedmember.role_changedCommitted design
Every request will carry X-Untactit-Signature — an HMAC-SHA256
of the raw body — plus a timestamp. Verify both: signature proves it came from us,
timestamp stops an old request being replayed at you.
==import hmac, hashlib, time
def verify(body: bytes, sig: str, ts: str, secret: str) -> bool:
if abs(time.time() - int(ts)) > 300: # 5 min
return False
expected = hmac.new(
secret.encode(), ts.encode() + b"." + body,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, sig)
We retry until you return 2xx, so the same event may arrive twice. Deduplicate on
id. Retries back off exponentially for up to 24 hours.
A sequence field increases monotonically. Receiving 48213 after
48215 means it is a late retry and can be discarded.
An endpoint failing continuously for two days is switched off and the workspace admin is emailed. Ten second timeout per attempt.
Connect one workspace and see every skill, rule, and memory your team has in play — in about ten minutes.
No credit card. Works with what you already run.