Agent skill
TutorCruncher Webhooks Skill
Receive and verify TutorCruncher webhooks (tutoring agency management software). Use when setting up a TutorCruncher integration endpoint, debugging Webhook-Signature verification, or handling actions such as CREATED_A_CONTRACTOR, CREATED_AN_APPOINTMENT, CLIENT_ENQUIRY and RAISED_INVOICE.
Install this skill
npx skills add hookdeck/webhook-skills --skill tutorcruncher-webhooks
TutorCruncher sends a webhook for every action on the account (a tutor created, a client enquiry, an invoice raised, ...). Each request body is {"events": [...]} and each element carries its own action.
When to Use This Skill
- How do I receive TutorCruncher webhooks?
- How do I verify the TutorCruncher
Webhook-Signatureheader? - Why does my TutorCruncher signature check fail, or return 401?
- How do I handle
CREATED_A_CONTRACTOR,CREATED_AN_APPOINTMENTorCLIENT_ENQUIRYactions?
Verification (core)
Webhook-Signature is the bare lowercase hex HMAC-SHA256 of the raw request body, keyed with your integration's private API key (there is no separate webhook secret). No prefix, no id and no timestamp. The header name matches Standard Webhooks, but this is not Standard Webhooks. Compare the whole header value as one digest.
const crypto = require('crypto');
function verifyTutorCruncherSignature(rawBody, signature, secret) {
// rawBody: Buffer of the exact bytes received (empty Buffer for no body)
if (!secret || typeof signature !== 'string' || !/^[0-9a-fA-F]{64}$/.test(signature)) return false;
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const received = Buffer.from(signature.toLowerCase(), 'utf8'); // hex is case-insensitive
const wanted = Buffer.from(expected, 'utf8');
return received.length === wanted.length && crypto.timingSafeEqual(received, wanted);
}
- The key is the secret's UTF-8 bytes as-is (not hex- or base64-decoded).
- Missing or empty header, malformed value or mismatch:
401. - Nothing time-based is signed, so there is no replay window to check.
- Read the body raw (
express.raw({ type: '*/*' })) and parse JSON only after the check. - Python:
hmac.compare_digeston bytes, neverstr.
HTTP method: TutorCruncher's docs don't name the method, so accept GET, POST, PUT, PATCH and DELETE, verify the signature first for each, and treat a missing body as zero bytes (a verified empty body gets 200). Hookdeck's TutorCruncher source pre-selects POST without managing the method, so allow any other method the sender uses on the source too.
For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.
Hookdeck Setup
Hookdeck's TutorCruncher source type verifies the signature (HMAC, SHA-256, header webhook-signature, hex). Hookdeck shows this note for the source:
"Paste your TutorCruncher private API key. TutorCruncher signs webhooks with it."
Common Event Types
The event name is the action of each element in events. Loop over every element.
action | Fired when |
|---|---|
CREATED_A_CONTRACTOR | A Tutor is created |
CHANGED_ | A Tutor's status is updated |
CREATED_A_CLIENT | A Client is created |
CLIENT_ENQUIRY | A Client makes an Enquiry |
CREATED_A_SERVICE | A Job is created |
CREATED_AN_APPOINTMENT | A Lesson is created |
MARKED_ | A Lesson is marked as complete |
RAISED_INVOICE | An Invoice is sent (once per Invoice) |
For the full list, see the Action Types section of the TutorCruncher API reference.
Environment Variables
TUTORCRUNCHER_WEBHOOK_SECRET=your_private_api_key # the integration's private API key
Delivery and Retries
Timeouts, no response and 5xx are retried up to 4 times with exponential backoff (after 1 s, 10 s, 100 s and 1000 s). Redirects and 4xx other than 429 are not retried. An endpoint whose failure rate stays above 20% is disabled. Each integration keeps webhook logs with request and response data.
Local Development
# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 tutorcruncher --path /webhooks/tutorcruncher
Reference Materials
- references/overview.md - Webhook concepts, payload shape, common actions
- references/setup.md - Add an integration, get the private API key
- references/verification.md - Signature details and debugging