Agent skill

Truework Webhooks Skill

Receive and authenticate Truework webhooks for income and employment verification. Use when setting up a Truework webhook endpoint, checking the X-Truework-Token header (Truework has no payload signature, so compare the webhook's authentication token in constant time), or handling order.completed and verification_request.state.change events.

Install this skill

npx skills add hookdeck/webhook-skills --skill truework-webhooks


Truework sends a webhook when an income or employment verification finishes (order.completed) or when a verification request within an order changes state (verification_request.state.change, used with Smart Outreach). Each is an HTTPS POST with a JSON body.

Truework does not sign webhook payloads. There is no HMAC and no signature header. Each webhook you create has an authentication token (shown in Developer Settings) that Truework sends unchanged in the X-Truework-Token header. You authenticate a request by comparing that header with the token, in constant time. A deleted and recreated webhook gets a new token.

When to Use This Skill

  • How do I receive Truework webhooks?
  • How do I verify a Truework webhook? (There is no signature: check X-Truework-Token.)
  • How do I handle order.completed or verification_request.state.change events?
  • Why does my Truework webhook return 401 after I recreated the webhook?
  • How do I react to a Smart Outreach action-required state?

Verification (core): compare the X-Truework-Token header, constant-time

Node:

const crypto = require('crypto');

// Hash both sides so timingSafeEqual gets equal-length buffers and never throws.
function safeEqual(a, b) {
  if (typeof a !== 'string' || typeof b !== 'string') return false;
  const h = (s) => crypto.createHash('sha256').update(s).digest();
  return crypto.timingSafeEqual(h(a), h(b));
}

const token = process.env.TRUEWORK_WEBHOOK_TOKEN;
// Fail closed: never let an empty token match an empty header
if (!token) return res.status(500).send('Auth not configured');
if (!safeEqual(req.get('X-Truework-Token'), token)) return res.status(401).send('Unauthorized');

Python:

import hashlib, hmac, os
token = os.environ.get("TRUEWORK_WEBHOOK_TOKEN", "")
if not token:  # fail closed
    raise HTTPException(500, "Webhook authentication not configured")
h = lambda s: hashlib.sha256(s.encode()).digest()
if not hmac.compare_digest(h(request.headers.get("x-truework-token") or ""), h(token)):
    raise HTTPException(401, "Invalid or missing X-Truework-Token")

Nothing is signed, so no raw-body handling is needed for verification. The examples still read the raw body (express.raw({ type: '*/*' })) so any content type works, and parse JSON only after the token check passes.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Common Event Types

Event (hook.event)Triggered WhenNotes
order.completedAll verifications on the order are completed or canceleddata.order_id; fetch results from the API. Recommended for Credentials and Documents verification
verification_request.state.changeA verification request within an order changes statedata.order_id, data.verification_request_id, data.credentials_session_token, data.state (pending-approval, processing, action-required, completed, canceled, invalid; the event reference page spells it action-requred, so accept both), data.metadata. Recommended for Smart Outreach

Payload: { "version", "hook": { "id", "event", "target", "triggered_at" }, "data": { ... } }. Dispatch on hook.event. hook.id is the webhook's ID, not an event ID.

Webhooks can be delivered more than once, so handlers must be idempotent. Failed deliveries are retried for 48 hours, and Truework emails the service account about failures.

Environment Variables

TRUEWORK_WEBHOOK_TOKEN=...   # authentication token from Developer Settings > Webhooks

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 truework --path /webhooks/truework

Use the printed URL as the webhook URL in Truework's Developer Settings.

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Nov 5, 2026

View on GitHub →