Agent skill
Rutter Webhooks Skill
Receive and verify Rutter webhooks. Use when setting up Rutter (unified commerce and accounting API) webhook handlers, debugging X-Rutter-Signature verification, handling client secret rotation, or processing events like INITIAL_UPDATE, CONNECTION_NEEDS_UPDATE, ORDER_CREATED, or INVOICE_UPDATED.
Install this skill
npx skills add hookdeck/webhook-skills --skill rutter-webhooks
When to Use This Skill
- How do I receive Rutter webhooks?
- How do I verify the
X-Rutter-Signatureheader? - Why is my Rutter webhook signature verification failing?
- How do I accept webhooks during a Rutter client secret rotation (
X-Rutter-Signatures)? - How do I handle
INITIAL_UPDATE,CONNECTION_NEEDS_UPDATE,ORDER_CREATEDorINVOICE_UPDATEDevents?
Verification (core)
Rutter signs the raw request body with HMAC-SHA256, keyed with your organization's client secret (used as a raw string, not decoded). X-Rutter-Signature is sha256= + the base64 digest. X-Rutter-Signatures is a comma-separated list of every active signature: one entry normally, two during a client secret rotation (new secret first, expiring secret second). Accept the webhook if any signature you compute from any of your active secrets matches any entry in the list.
const crypto = require('crypto');
function verifyRutter(rawBody, signaturesHeader, secrets) {
if (!signaturesHeader) return false;
const received = signaturesHeader.split(',').map((s) => s.trim());
return secrets.some((secret) => {
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('base64');
return received.some((sig) => {
try {
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
} catch {
return false; // different lengths
}
});
});
}
Python equivalent:
import base64, hashlib, hmac
def verify_rutter(raw_body: bytes, signatures_header: str, secrets: list[str]) -> bool:
received = [s.strip() for s in (signatures_header or "").split(",") if s.strip()]
for secret in secrets:
digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
expected = "sha256=" + base64.b64encode(digest).decode()
if any(hmac.compare_digest(sig.encode(), expected.encode()) for sig in received):
return True
return False
Rutter does not send a timestamp or webhook ID header, so there is no signed timestamp to check. Use the payload (type, code, entity id) for idempotency. Rutter has no official webhook verification SDK helper, so the examples verify manually.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Payload and Event Types
Every payload has a type (entity group, e.g. CONNECTION, ORDER) and a code (the specific event), plus access_token and connection_id. Entity events add the entity object under a lowercase key (order, invoice, ...). Route on code.
type | code | Description |
|---|---|---|
CONNECTION | INITIAL_UPDATE | Initial data download finished; data can now be fetched |
CONNECTION | CONNECTION_NEEDS_UPDATE | Merchant unauthorized or auth failed; payload has update_url to re-authenticate |
CONNECTION | CONNECTION_DISABLED | Rutter disabled access (e.g. store suspended); has disable_error, disable_message |
ORDER | ORDER_CREATED / ORDER_UPDATED / ORDER_DELETED | Commerce order changes |
INVOICE | INVOICE_CREATED / INVOICE_UPDATED | Accounting invoice changes |
Other connection codes: HISTORICAL_UPDATE, INCREMENTAL_, CONNECTION_UPDATED, CONNECTION_LINK_ERROR, CONNECTION_ERROR, CONNECTION_AUTHENTICATED. See references/overview.md for the full list.
Rutter must receive a 2xx within 5 seconds; failures are retried with exponential backoff for up to 15 minutes. The same payload can be delivered more than once, and a small share of webhooks can be dropped, so handlers must be idempotent and you should also poll the API.
Environment Variables
RUTTER_CLIENT_SECRET=your_client_secret # Rutter dashboard, where you get your API keys
RUTTER_CLIENT_SECRET_PREVIOUS= # Optional: expiring secret during rotation
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 rutter --path /webhooks/rutter
Reference Materials
- references/overview.md - Rutter webhook concepts, payloads, event types
- references/setup.md - Dashboard configuration and secrets
- references/verification.md - Signature verification details and rotation