Receive real-time HTTP notifications when events occur on your Techspert account.
To start receiving webhooks, contact your Techspert representative to configure your endpoint URL and obtain your signing key for verifying signatures.
Once a webhook is configured for your account, Techspert will send an HTTP POST request to your endpoint URL whenever a call recording finishes processing. You can use these notifications to automate workflows, trigger downstream processing, or keep your own systems in sync with activity on your Techspert account.
Techspert sends a POST request to your endpoint with the following headers:
POST <your-endpoint-url>
Content-Type: application/json
X-Webhook-Signature: t=<unix-timestamp>,v1=<hmac-hex>
The request body is a JSON object containing the event payload.
Your endpoint must return a 2xx HTTP status code within the request timeout to be considered a successful delivery. Any other status code or a connection error will be treated as a failure and the delivery will be retried.
Events are delivered asynchronously. If your endpoint does not return a 2xx response, Techspert will retry the delivery automatically with exponential backoff (capped at 4 hours between attempts) for a maximum of 15 attempts. After 15 consecutive failures, the delivery is marked as permanently failed and will not be retried.
To avoid unnecessary retries, ensure your endpoint:
2xx status code.Every webhook delivery includes an X-Webhook-Signature header. You should verify this header on receipt to confirm the request genuinely originated from Techspert and has not been tampered with in transit.
The signature is an HMAC-SHA256 digest, computed using a signing key shared with you at setup. The header has the form:
X-Webhook-Signature: t=<unix-timestamp>,v1=<hmac-hex>
t — Unix timestamp (seconds) at the time of delivery.v1 — HMAC-SHA256 hex digest of the signed string., to extract the t and v1 values.., and the raw request body: <t>.<raw-body>.HMAC-SHA256 of that string using your signing key.v1 value using a constant-time comparison to prevent timing attacks.now - t is within your tolerance window (we recommend 5 minutes) to guard against replay attacks.Important: always verify against the raw request body bytes, not a re-serialised version of the parsed JSON, as key ordering may differ.
import { createHmac, timingSafeEqual } from 'crypto';
function verifyWebhookSignature(
rawBody: string,
header: string,
signingKey: string,
toleranceSeconds = 300,
): boolean {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const timestamp = Number(parts['t']);
const expected = parts['v1'];
if (!timestamp || !expected) return false;
const now = Math.floor(Date.now() / 1000);
if (now < timestamp || now - timestamp > toleranceSeconds) {
return false; // Outside tolerance window — possible replay attack
}
const computed = createHmac('sha256', signingKey)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const computedBuffer = Buffer.from(computed, 'hex');
const expectedBuffer = Buffer.from(expected, 'hex');
if (computedBuffer.length !== expectedBuffer.length) {
return false;
}
return timingSafeEqual(computedBuffer, expectedBuffer);
}
If you need to rotate your signing key (e.g. as part of a security policy), contact Techspert to initiate a rotation.
When a rotation is performed:
Update your stored signing key before or at the cutover time to avoid verification failures.
2xx status code to acknowledge receipt.X-Webhook-Signature header before acting on the payload.Fired when a call has finished processing and associated files are available.
Note: Presigned URLs expire. Download files promptly after receiving the notification, before the
presigned_url_expirytimestamp.
If the call belongs to a project created through the RFQ self-serve form, the payload also
includes the RFQ details submitted for that project: project_type, recruiting_criteria,
timelines, additional_services, next_steps, aob, client_contact_emails, and
file_upload_urls.
null or an empty string/array.| X-Webhook-Signature required | string Example: t=1715680800,v1=a3f9c2... HMAC-SHA256 signature for verifying request authenticity. See Verifying Signatures. |
| type required | string Value: "call_processing_complete" The event type identifier. |
| case_code_id required | string Your provided project identifier, or the Techspert identifier if not provided, for the project/case code associated with the call. |
| expert_id required | string The Techspert identifier for the expert on the call, this is unique to each expert & project, so will differ for the same person on another project. |
| expert_name required | string The display name of the expert. |
| call_timestamp required | string <date-time> The date and time the call took place (ISO 8601, UTC). |
required | Array of objects (CallProcessingCompleteFile) List of files available for download. |
| project_type | string Enum: "Qual" "Quant" "Mixed" "Other" The type of project selected on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if no value was provided. |
| recruiting_criteria | string The recruiting criteria submitted on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if no value was provided. |
| timelines | string The timelines submitted on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if no value was provided. |
| additional_services | Array of strings Items Enum: "Data Capture" "Translation services" "Moderation services" "Recruitment Grid" "Survey programming and hosting" Additional services requested on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if no services were selected. |
| next_steps | Array of strings Items Enum: "Kick off immediately" "Book a kick-off call" "Share feasibility and pricing" "Book a project portal demo" Next steps selected on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if no next steps were selected. |
| aob | string Any other business/information submitted on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if no value was provided. |
| client_contact_emails | Array of strings Additional client contact emails submitted on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if none were provided. |
Array of objects (CallProcessingCompleteUploadedFile) Files uploaded on the RFQ self-serve form. Only present for projects created through the RFQ self-serve form, and omitted if no files were uploaded. |
{- "type": "call_processing_complete",
- "case_code_id": "PROJ-001",
- "expert_id": "22222222-2222-2222-2222-222222222222",
- "expert_name": "Jane Smith",
- "call_timestamp": "2026-05-14T10:00:00.000Z",
- "files": [
- {
- "asset_type": "transcription",
- "presigned_url_expiry": "2026-05-21T10:00:00.000Z"
}
]
}