Integrations

Every plan

API and webhooks

Send each finished result to your own systems the moment it is ready, or pull results whenever you like with a key.

Where to find it

In your console, open Settings, Integrations, then API & webhooks. Only admins of your team can change these settings.

Webhooks: we tell your system

A webhook is a web address on your side that we send a message to whenever a candidate finishes. Paste the address, save it, and press Send a test event to check it works. The address must start with https://.

If your system does not answer, we try three times over a few seconds. Every attempt is listed under Recent deliveries, failures in red.

What a webhook sends

{
  "event": "assessment.completed",
  "at": "2026-09-27T14:05:00.000Z",
  "candidate": {
    "name": "Emily Carter",
    "roleTitle": "Product Analyst",
    "jobRef": "JOB-1042",
    "externalId": "GH-88213",
    "level": "Mid"
  },
  "result": { "grade": "A-", "scored": 92, "available": 100, "percent": 92,
              "completed": true, "decisions": 6 },
  "reportUrl": null,
  "runId": "run_..."
}

externalId is the candidate's ID in your own system, when you invited them from a CSV with an ID column. A test event has "event": "assessment.test" and made-up details. The candidate's email is left out on purpose, because a webhook address can be shared; the API includes it.

Checking a webhook came from us

Every delivery carries a header:

x-trialday-signature: t=1759000000,v1=5f2c...

To check it, join the time and the raw body with a full stop (t.body), compute an HMAC-SHA256 of that with your signing secret, and compare it with v1. Reject anything more than five minutes old. In Node.js:

import { createHmac, timingSafeEqual } from "node:crypto";

function fromTrialDay(header, rawBody, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;
  const mine = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return timingSafeEqual(Buffer.from(mine), Buffer.from(v1));
}

The API: your system asks us

Create a key in the same panel and copy it at once; it is stored scrambled and cannot be shown again. One key works at a time, and making a new one retires the old.

curl https://trialday.co/api/v1/results \
  -H "Authorization: Bearer YOUR_KEY"

It answers with every finished result for your company: an id that stays the same between calls, the candidate's name and email, the role, your externalId, whether it was one of your own team, how the candidate proved their email address, when they finished, and the result (recommendation, headline and percentage).

Other integrations: ZapierGreenhouseAshbyLeverWorkableSmartRecruiters