মূল অংশে যান
ওয়েবহুক

নিয়োগের প্রতিটি ধাপের খবর পান। সই করা, আবার চেষ্টা করা আর লগে রাখা।

পাইপলাইনে কিছু ঘটলে SeekIQ আপনার HTTPS এন্ডপয়েন্টে একটি ছোট JSON ইভেন্ট পাঠায়। সিগনেচার যাচাই করুন, ইভেন্ট id রেখে দিন আর 2xx দিয়ে উত্তর দিন।

এন্ডপয়েন্ট সেট আপ

  1. মালিক হিসেবে সেটিংস > API আর ওয়েবহুক খুলে একটি এন্ডপয়েন্ট যোগ করুন: তার HTTPS ঠিকানা আর যে ইভেন্টগুলো সেটি পাবে।
  2. সাইনিং সিক্রেট কপি করুন (এটি whsec_ দিয়ে শুরু হয়)। এটি একবারই দেখানো হয়।
  3. টেস্ট পাঠান চাপুন। একটি ping ইভেন্ট আসবে, অন্য সব ইভেন্টের মতোই সই করা।

কোড থেকেও একই কাজ করা যায়: webhooks:manage স্কোপ সহ একটি কী দিয়ে POST /webhooks। POST /webhooks

ইভেন্ট টাইপ

প্রতিটি এন্ডপয়েন্টের জন্য ইভেন্ট আলাদা করে বেছে নিন। নতুন ইভেন্ট টাইপ যোগ হতে পারে; যেগুলো আপনি সামলান না সেগুলো উপেক্ষা করুন।

ইভেন্টকখন পাঠানো হয়
application.createdযেকোনো উৎস থেকে নতুন আবেদন: ক্যারিয়ার সাইট, এম্বেড, API, জব ইনবক্স বা রেফারেল
application.stage_changedকোনো আবেদন এক ধাপ থেকে আরেক ধাপে গেছে, একজন মানুষ বা অটো-অ্যাডভান্স নিয়মের মাধ্যমে
interview.completedপ্রার্থী একটি এআই ইন্টারভিউ শেষ করেছেন
scorecard.readyএআই স্কোরকার্ড তৈরি হয়েছে, প্রতিটি উদ্ধৃতি যাচাই করে
decision.madeএকজন মানুষ এগিয়ে নেওয়া, আটকে রাখা বা বাদ দেওয়ার সিদ্ধান্ত রেকর্ড করেছেন
decision.undoneএকজন মানুষ পাঁচ মিনিটের আনডু সময়ের মধ্যে একটি সিদ্ধান্ত ফিরিয়ে নিয়েছেন
offer.sentঅনুমোদিত অফার প্রার্থীর কাছে গেছে
offer.signedপ্রার্থী অফারে সই করেছেন
offer.declinedপ্রার্থী অফার ফিরিয়ে দিয়েছেন, কারণের কোড সহ
document.sentএকটি চুক্তি বা কন্ট্রাক্ট সইয়ের জন্য পাঠানো হয়েছে
document.signedএকটি পক্ষ নথিতে সই করেছে; সবাই সই করলে complete হয় true
document.declinedএকটি পক্ষ নথি ফিরিয়ে দিয়েছে, ফলে নথিটি বন্ধ হয়ে গেছে
candidate.data_requestপ্রার্থী তাঁর তথ্য দেখতে বা মুছতে চেয়েছেন অথবা একজন মানুষের রিভিউ চেয়েছেন। আপনার কাছে তথ্যের কপি থাকলে আপনারও দায়িত্ব আছে
pingশুধু একটি এন্ডপয়েন্টে পাঠানো হয়, যখন আপনি টেস্ট পাঠান চাপেন বা টেস্ট এন্ডপয়েন্ট কল করেন।

পেলোড

প্রতিটি ইভেন্টের কাঠামো একই। data-তে থাকে id আর একটি ছোট সারাংশ, পুরো ব্যক্তিগত তথ্য নয়; আরও দরকার হলে API দিয়ে রিসোর্সটি নিয়ে নিন।

JSON
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "application.stage_changed",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": { ... }
}

হেডার

প্রতিটি ডেলিভারিতে এই হেডারগুলো থাকে:

HTTP
Content-Type: application/json
User-Agent: SeekIQ-Webhooks/1.0 (+https://seekiq.io/developers/webhooks)
SeekIQ-Signature: t=1760779800,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
SeekIQ-Event-Id: evt_01JB7Y2K9T3V4W5X6Y7Z8A9B
SeekIQ-Event-Type: application.stage_changed
SeekIQ-Delivery-Id: 0193f1c2-7a4e-7b1d-9c3e-5f8a2b6d4e10
SeekIQ-Signatureটাইমস্ট্যাম্প আর এক বা দুটি HMAC সিগনেচার
SeekIQ-Event-Idইভেন্টটি, প্রতিটি রিট্রাইতে একই
SeekIQ-Event-Typeইভেন্ট টাইপ, বডিতেও থাকে
SeekIQ-Delivery-Idএই চেষ্টাটি; রিট্রাইতে নতুন id আসে

সিগনেচার যাচাই

সিগনেচার হলো টাইমস্ট্যাম্প, একটি ডট আর কাঁচা রিকোয়েস্ট বডির hex HMAC-SHA256, এন্ডপয়েন্টের সিক্রেট দিয়ে। JSON পার্স করার আগে, ঠিক যে বাইটগুলো পেয়েছেন তার ওপর হিসাব করুন আর constant time-এ মিলিয়ে দেখুন। আপনার ঘড়ি থেকে পাঁচ মিনিটের বেশি দূরের টাইমস্ট্যাম্প বাতিল করুন।

Node.js

verify.js
import crypto from 'node:crypto';

/** True when one of the v1 signatures matches and the timestamp is recent. */
export function verifySeekIQSignature(rawBody, header, secret, toleranceSec = 300) {
  if (!header) return false;
  const parts = header.split(',').map((p) => p.trim().split('='));
  const t = Number(parts.find(([k]) => k === 't')?.[1]);
  const sigs = parts.filter(([k]) => k === 'v1').map(([, v]) => v);
  if (!t || sigs.length === 0) return false;
  if (Math.abs(Math.floor(Date.now() / 1000) - t) > toleranceSec) return false;

  const expected = crypto.createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  return sigs.some((s) => {
    const got = Buffer.from(s, 'hex');
    return got.length === expected.length && crypto.timingSafeEqual(got, expected);
  });
}
server.js
import express from 'express';

const app = express();
const seen = new Set(); // use your database in production

// Read the raw body: the signature covers the exact bytes SeekIQ sent.
app.post('/seekiq/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
  const raw = req.body.toString('utf8');
  if (!verifySeekIQSignature(raw, req.get('SeekIQ-Signature'), process.env.SEEKIQ_WEBHOOK_SECRET)) {
    return res.sendStatus(400);
  }
  const event = JSON.parse(raw);
  if (!seen.has(event.id)) {
    seen.add(event.id);
    // queue your work here, then answer quickly
  }
  res.sendStatus(200);
});

Python

verify.py
import hashlib
import hmac
import time


def verify_seekiq_signature(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    """True when one of the v1 signatures matches and the timestamp is recent."""
    if not header:
        return False
    parts = [p.strip().split("=", 1) for p in header.split(",") if "=" in p]
    t = next((v for k, v in parts if k == "t"), "")
    sigs = [v for k, v in parts if k == "v1"]
    if not t.isdigit() or not sigs:
        return False
    if abs(int(time.time()) - int(t)) > tolerance:
        return False
    expected = hmac.new(secret.encode(), t.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
    return any(hmac.compare_digest(expected, s) for s in sigs)
app.py
import os
from flask import Flask, abort, request

app = Flask(__name__)


@app.post("/seekiq/webhooks")
def seekiq_webhook():
    raw = request.get_data()  # the exact bytes, before JSON parsing
    if not verify_seekiq_signature(raw, request.headers.get("SeekIQ-Signature", ""),
                                   os.environ["SEEKIQ_WEBHOOK_SECRET"]):
        abort(400)
    event = request.get_json()
    # skip event["id"] if you have handled it, otherwise queue the work
    return "", 200

সিক্রেট বদলানো

সিক্রেট বদলালে (সেটিংসে বা rotate-secret এন্ডপয়েন্ট দিয়ে) পুরোনোটি আরও ২৪ ঘণ্টা কাজ করে। এই সময়ে হেডারে দুটি v1 মান থাকে, নতুন সিক্রেটেরটি আগে। যেকোনো একটি মিললেই ইভেন্টটি গ্রহণ করুন।

রিট্রাই আর বিরতি

১০ সেকেন্ডের মধ্যে যেকোনো 2xx এলে ডেলিভারি সফল। এ ছাড়া সবকিছু, যেমন রিডাইরেক্ট, টাইমআউট বা প্রত্যাখ্যাত কানেকশন, আবার চেষ্টা করা হয়।

রিট্রাইয়ের সময়সূচি
১ মিনিট, ৫ মিনিট, ৩০ মিনিট, ২ ঘণ্টা, ৬ ঘণ্টা, ১২ ঘণ্টা আর ২৪ ঘণ্টা পরে, প্রতিটিতে ১০ শতাংশ কমবেশি: প্রায় দুই দিনে মোট ৮টি চেষ্টা।

টানা ৩ দিন ব্যর্থ হলে এন্ডপয়েন্টটি বন্ধ হয়ে যায় আর ওয়ার্কস্পেসের মালিকেরা ইমেইল পান। সেটিংস থেকে বা PATCH active: true দিয়ে আবার চালু করুন।

দ্রুত উত্তর দিন: ইভেন্টটি রেখে দিন, HTTP 200 ফেরত দিন আর কাজটি ব্যাকগ্রাউন্ডে করুন।

আইডেমপোটেন্সি

একই ইভেন্ট একাধিকবার আসতে পারে, যেমন আপনার HTTP 200 ফেরার পথে হারিয়ে গেলে। প্রতিটি চেষ্টায় একই SeekIQ-Event-Id আর বডি থাকে, শুধু SeekIQ-Delivery-Id নতুন। ইভেন্ট id রেখে দিন আর আগে সামলানো ইভেন্ট বাদ দিন।

ক্রম

ইভেন্ট ক্রম অনুযায়ী আসবে এমন নিশ্চয়তা নেই, আর রিট্রাই নতুন ইভেন্টের আগেও পৌঁছাতে পারে। ইভেন্টের created_at আর রিসোর্সের updated_at ব্যবহার করুন, অথবা API দিয়ে বর্তমান অবস্থা নিয়ে নিন।

ডেলিভারি টেস্ট

টেস্ট পাঠান একটি এন্ডপয়েন্টে একটি ping ইভেন্ট পাঠায়। সেটিংসের ডেলিভারি লগে প্রতিটি চেষ্টা দেখা যায়: স্ট্যাটাস কোড, কত সময় লাগল, আপনার উত্তরের প্রথম ১ KB আর পরের রিট্রাই কখন। যেকোনো ডেলিভারি আবার পাঠানো যায়। কোড থেকেও একই সুবিধা আছে:

curl
# Send a ping to one endpoint
curl -X POST "https://app.seekiq.io/api/v1/webhooks/whk_01JBCJ7W/test" \
  -H "Authorization: Bearer $SEEKIQ_API_KEY"

# Read the delivery log (pending, succeeded or failed)
curl "https://app.seekiq.io/api/v1/webhooks/whk_01JBCJ7W/deliveries?status=failed" \
  -H "Authorization: Bearer $SEEKIQ_API_KEY"

# Send one delivery again
curl -X POST "https://app.seekiq.io/api/v1/webhooks/whk_01JBCJ7W/deliveries/dlv_01JBDK8X/redeliver" \
  -H "Authorization: Bearer $SEEKIQ_API_KEY"

আবার পাঠানো মানে নতুন delivery id সহ একটি চেষ্টা, যা নিজে থেকে আর রিট্রাই হয় না।

এন্ডপয়েন্টের ঠিকানা

এন্ডপয়েন্টের ঠিকানা https হতে হবে আর পাবলিক ইন্টারনেট থেকে পৌঁছানো যেতে হবে। প্রাইভেট, লুপব্যাক ও অন্যান্য সংরক্ষিত ঠিকানা সেভ করার সময় বাতিল হয় আর প্রতিটি ডেলিভারির আগে আবার যাচাই হয়। রিডাইরেক্ট অনুসরণ করা হয় না। লোকাল কাজের জন্য পাবলিক HTTPS ঠিকানা সহ একটি টানেল ব্যবহার করুন।

Zapier, Make আর n8n

Zapier বা Make-এর ডিরেক্টরিতে এখনো SeekIQ অ্যাপ নেই। তবে তাদের catch hook আজই কাজ করে:

  1. একটি catch hook তৈরি করুন: Zapier-এ Webhooks by Zapier আর Catch Hook, Make-এ Custom webhook অথবা n8n-এ Webhook নোড।
  2. এর ঠিকানাটি সেটিংস > API আর ওয়েবহুক-এ এন্ডপয়েন্ট হিসেবে যোগ করে ইভেন্টগুলো বেছে নিন।
  3. টুলটি type আর data ফিল্ড হিসেবে দেখবে। টুলে কোড চালানো গেলে SeekIQ-Signature যাচাই করুন; না গেলে hook-এর ঠিকানা গোপন রাখুন, কারণ সেটিই একমাত্র সিক্রেট।
  4. অ্যাকশনের জন্য টুলের HTTP ধাপ ব্যবহার করুন, এমন সার্ভিস কী দিয়ে যাতে শুধু ফ্লোর দরকারি স্কোপ আছে, আর রাইটে Idempotency-Key দিন।

Slack আর Microsoft Teams-এর বার্তার জন্য কোনো টুল লাগে না: সেটিংস > ইন্টিগ্রেশন সরাসরি সেগুলো পাঠায়।

ইভেন্টের পেলোড

প্রতিটি ইভেন্ট যে data বহন করে। নমুনার মানগুলো বানানো; ফিল্ডের নাম ও টাইপ OpenAPI ফাইল থেকে নেওয়া।

ping

শুধু একটি এন্ডপয়েন্টে পাঠানো হয়, যখন আপনি টেস্ট পাঠান চাপেন বা টেস্ট এন্ডপয়েন্ট কল করেন।

  • messagestringআবশ্যিক
পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "ping",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "message": "Hello from SeekIQ"
  }
}

application.created

যেকোনো উৎস থেকে নতুন আবেদন: ক্যারিয়ার সাইট, এম্বেড, API, জব ইনবক্স বা রেফারেল

  • application_idIdআবশ্যিক
  • job_idIdআবশ্যিক
  • candidate_idIdআবশ্যিক
  • sourceApplicationSourceআবশ্যিক
    careers_siteembedapiemail_inboxreferralsourcedjob_board
  • originstring | nullআবশ্যিক

    Host origin for embed applications

  • answersApplicationAnswer[]আবশ্যিক

    The apply form answers, as on the Application.

পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "application.created",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "application_id": "app_01JB7X4M2Q8Z",
    "job_id": "job_01JB7X4M2Q8Z",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "source": "careers_site",
    "origin": "string",
    "answers": [
      {
        "question_id": "string",
        "label": {},
        "type": "string",
        "value": "string"
      }
    ]
  }
}

application.stage_changed

কোনো আবেদন এক ধাপ থেকে আরেক ধাপে গেছে, একজন মানুষ বা অটো-অ্যাডভান্স নিয়মের মাধ্যমে

  • application_idIdআবশ্যিক
  • job_idIdআবশ্যিক
  • from_stageStageআবশ্যিক
  • to_stageStageআবশ্যিক
  • actorActorআবশ্যিক
  • reasonstring | nullআবশ্যিক
পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "application.stage_changed",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "application_id": "app_01JB7X4M2Q8Z",
    "job_id": "job_01JB7X4M2Q8Z",
    "from_stage": {
      "id": "stg_01JB7X4M2Q8Z",
      "type": "applied",
      "name": "Phone screen",
      "order": 1
    },
    "to_stage": {
      "id": "stg_01JB7X4M2Q8Z",
      "type": "applied",
      "name": "Phone screen",
      "order": 1
    },
    "actor": {
      "type": "user",
      "id": "usr_01JB7X4M2Q8Z"
    },
    "reason": "Strong on customer empathy"
  }
}

interview.completed

প্রার্থী একটি এআই ইন্টারভিউ শেষ করেছেন

  • interview_idIdআবশ্যিক
  • application_idIdআবশ্যিক
  • kindstringআবশ্যিক

    Always ai today; human interviews are scheduled meetings with feedback, not sessions.

    aihuman
  • completed_atstring (date-time)আবশ্যিক
পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "interview.completed",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "interview_id": "int_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "kind": "ai",
    "completed_at": "2026-10-26T09:30:00Z"
  }
}

scorecard.ready

এআই স্কোরকার্ড তৈরি হয়েছে, প্রতিটি উদ্ধৃতি যাচাই করে

  • application_idIdআবশ্যিক
  • scorecard_versionintegerআবশ্যিক
  • open_flagsintegerআবশ্যিক
পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "scorecard.ready",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "application_id": "app_01JB7X4M2Q8Z",
    "scorecard_version": 1,
    "open_flags": 0
  }
}

decision.made

একজন মানুষ এগিয়ে নেওয়া, আটকে রাখা বা বাদ দেওয়ার সিদ্ধান্ত রেকর্ড করেছেন

  • decision_idIdআবশ্যিক
  • application_idIdআবশ্যিক
  • outcomeDecisionOutcomeআবশ্যিক
    advanceholdreject
  • decided_byActorআবশ্যিক
পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "decision.made",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "decision_id": "dec_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "outcome": "advance",
    "decided_by": {
      "type": "user",
      "id": "app_01JB7X4M2Q8Z"
    }
  }
}

decision.undone

একজন মানুষ পাঁচ মিনিটের আনডু সময়ের মধ্যে একটি সিদ্ধান্ত ফিরিয়ে নিয়েছেন

  • decision_idIdআবশ্যিক
  • application_idIdআবশ্যিক
  • outcomeDecisionOutcomeআবশ্যিক
    advanceholdreject
  • undone_byActorআবশ্যিক
পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "decision.undone",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "decision_id": "dec_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "outcome": "advance",
    "undone_by": {
      "type": "user",
      "id": "app_01JB7X4M2Q8Z"
    }
  }
}

offer.sent

অনুমোদিত অফার প্রার্থীর কাছে গেছে

  • offer_idIdআবশ্যিক
  • application_idIdআবশ্যিক
  • candidate_idIdআবশ্যিক
  • statusOfferStatusআবশ্যিক
    draftpending_approvalapprovedsentsigneddeclinedexpiredwithdrawn
  • document_sha256string | null

    sha256 of the offer letter PDF as sent (offer.sent and offer.signed)

  • signed_sha256string

    sha256 of the signed copy (offer.signed)

  • expires_onstring (date)

    Last day the offer can be signed (offer.sent)

  • reasonstring

    The candidate's decline reason code (offer.declined)

পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "offer.sent",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "offer_id": "off_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "status": "draft"
  }
}

offer.signed

প্রার্থী অফারে সই করেছেন

  • offer_idIdআবশ্যিক
  • application_idIdআবশ্যিক
  • candidate_idIdআবশ্যিক
  • statusOfferStatusআবশ্যিক
    draftpending_approvalapprovedsentsigneddeclinedexpiredwithdrawn
  • document_sha256string | null

    sha256 of the offer letter PDF as sent (offer.sent and offer.signed)

  • signed_sha256string

    sha256 of the signed copy (offer.signed)

  • expires_onstring (date)

    Last day the offer can be signed (offer.sent)

  • reasonstring

    The candidate's decline reason code (offer.declined)

পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "offer.signed",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "offer_id": "off_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "status": "draft"
  }
}

offer.declined

প্রার্থী অফার ফিরিয়ে দিয়েছেন, কারণের কোড সহ

  • offer_idIdআবশ্যিক
  • application_idIdআবশ্যিক
  • candidate_idIdআবশ্যিক
  • statusOfferStatusআবশ্যিক
    draftpending_approvalapprovedsentsigneddeclinedexpiredwithdrawn
  • document_sha256string | null

    sha256 of the offer letter PDF as sent (offer.sent and offer.signed)

  • signed_sha256string

    sha256 of the signed copy (offer.signed)

  • expires_onstring (date)

    Last day the offer can be signed (offer.sent)

  • reasonstring

    The candidate's decline reason code (offer.declined)

পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "offer.declined",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "offer_id": "off_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "status": "draft"
  }
}

document.sent

একটি চুক্তি বা কন্ট্রাক্ট সইয়ের জন্য পাঠানো হয়েছে

  • document_idIdআবশ্যিক
  • kindstringআবশ্যিক
    offeremployment_agreementndacontractor_agreementpolicyother
  • titlestringআবশ্যিক
  • statusstringআবশ্যিক
    sentcompleteddeclinedvoidedexpired
  • candidate_idId | nullআবশ্যিক
  • application_idId | nullআবশ্যিক
  • offer_idId | nullআবশ্যিক
  • original_sha256string | nullআবশ্যিক

    sha256 of the PDF as sent

  • party_rolestring

    The party that signed or declined (document.signed and document.declined)

    candidatecompanywitness
  • completeboolean

    True once every party has signed (document.signed)

  • signed_sha256string

    sha256 of the copy this signature produced, each copy with its own fingerprint (document.signed)

  • final_sha256string | null

    sha256 of the final copy with every signature and the certificate once complete, else null (document.signed)

পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "document.sent",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "document_id": "app_01JB7X4M2Q8Z",
    "kind": "offer",
    "title": "Customer support lead",
    "status": "sent",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "offer_id": "off_01JB7X4M2Q8Z",
    "original_sha256": "string"
  }
}

document.signed

একটি পক্ষ নথিতে সই করেছে; সবাই সই করলে complete হয় true

  • document_idIdআবশ্যিক
  • kindstringআবশ্যিক
    offeremployment_agreementndacontractor_agreementpolicyother
  • titlestringআবশ্যিক
  • statusstringআবশ্যিক
    sentcompleteddeclinedvoidedexpired
  • candidate_idId | nullআবশ্যিক
  • application_idId | nullআবশ্যিক
  • offer_idId | nullআবশ্যিক
  • original_sha256string | nullআবশ্যিক

    sha256 of the PDF as sent

  • party_rolestring

    The party that signed or declined (document.signed and document.declined)

    candidatecompanywitness
  • completeboolean

    True once every party has signed (document.signed)

  • signed_sha256string

    sha256 of the copy this signature produced, each copy with its own fingerprint (document.signed)

  • final_sha256string | null

    sha256 of the final copy with every signature and the certificate once complete, else null (document.signed)

পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "document.signed",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "document_id": "app_01JB7X4M2Q8Z",
    "kind": "offer",
    "title": "Customer support lead",
    "status": "sent",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "offer_id": "off_01JB7X4M2Q8Z",
    "original_sha256": "string"
  }
}

document.declined

একটি পক্ষ নথি ফিরিয়ে দিয়েছে, ফলে নথিটি বন্ধ হয়ে গেছে

  • document_idIdআবশ্যিক
  • kindstringআবশ্যিক
    offeremployment_agreementndacontractor_agreementpolicyother
  • titlestringআবশ্যিক
  • statusstringআবশ্যিক
    sentcompleteddeclinedvoidedexpired
  • candidate_idId | nullআবশ্যিক
  • application_idId | nullআবশ্যিক
  • offer_idId | nullআবশ্যিক
  • original_sha256string | nullআবশ্যিক

    sha256 of the PDF as sent

  • party_rolestring

    The party that signed or declined (document.signed and document.declined)

    candidatecompanywitness
  • completeboolean

    True once every party has signed (document.signed)

  • signed_sha256string

    sha256 of the copy this signature produced, each copy with its own fingerprint (document.signed)

  • final_sha256string | null

    sha256 of the final copy with every signature and the certificate once complete, else null (document.signed)

পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "document.declined",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "document_id": "app_01JB7X4M2Q8Z",
    "kind": "offer",
    "title": "Customer support lead",
    "status": "sent",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "application_id": "app_01JB7X4M2Q8Z",
    "offer_id": "off_01JB7X4M2Q8Z",
    "original_sha256": "string"
  }
}

candidate.data_request

প্রার্থী তাঁর তথ্য দেখতে বা মুছতে চেয়েছেন অথবা একজন মানুষের রিভিউ চেয়েছেন। আপনার কাছে তথ্যের কপি থাকলে আপনারও দায়িত্ব আছে

  • request_idIdআবশ্যিক
  • candidate_idIdআবশ্যিক
  • kindstringআবশ্যিক
    accessdeletehuman_reviewhuman_interview
  • due_atstring (date-time)আবশ্যিক
পেলোডের উদাহরণ
{
  "id": "evt_01JB7Y2K9T3V4W5X6Y7Z8A9B",
  "type": "candidate.data_request",
  "api_version": "v1",
  "created_at": "2026-10-26T09:30:00Z",
  "org_id": "org_01JB2M0Q",
  "data": {
    "request_id": "app_01JB7X4M2Q8Z",
    "candidate_id": "cand_01JB7X4M2Q8Z",
    "kind": "access",
    "due_at": "2026-10-26T09:30:00Z"
  }
}