Skip to main content

Overview

Ropes can send webhook notifications to your server when key events occur during the assessment lifecycle. This allows you to build automated workflows, sync data with your systems, and react to candidate progress in real-time.

Configuration

To enable webhooks, navigate to Settings → Integrations and configure:
  1. Webhook URL - The HTTPS endpoint where Ropes will send POST requests
  2. Webhook Secret - A secret key used to sign webhook payloads for verification
  3. Subscribed Events - Select which events you want to receive

Events

You can subscribe to any combination of the following events:
EventDescription
interview.sentAn assessment has been sent to a candidate
interview.startedA candidate has started their assessment
interview.completedA candidate has completed their assessment
interview.expiredAn assessment has expired (with or without being started)

Payload Structure

All webhook payloads include these base fields:
{
  "event": "interview.completed",
  "timestamp": "2025-11-25T14:30:00.000Z",
  "interviewId": "abc123",
  "email": "[email protected]",
  "problemId": "prob_456",
  "problemName": "React Dashboard Challenge"
}
Full example payloads for each specific event are below:

Event-Specific Payloads

interview.sent

{
  "event": "interview.sent",
  "timestamp": "2025-11-25T14:30:00.000Z",
  "interviewId": "abc123",
  "email": "[email protected]",
  "problemId": "prob_456",
  "problemName": "React Dashboard Challenge",
  "assessmentLink": "https://yourcompany.ropes.ai/assessment/abc123",
  "expiresAt": "2025-12-02T14:30:00.000Z"
}
FieldTypeDescription
assessmentLinkstringThe URL sent to the candidate
expiresAtstring (optional)ISO 8601 expiration date, if set

interview.started

{
  "event": "interview.started",
  "timestamp": "2025-11-25T14:30:00.000Z",
  "interviewId": "abc123",
  "email": "[email protected]",
  "problemId": "prob_456",
  "problemName": "React Dashboard Challenge",
  "startedAt": "2025-11-25T14:30:00.000Z"
}
FieldTypeDescription
startedAtstringISO 8601 timestamp when the candidate started

interview.completed

{
  "event": "interview.completed",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "interviewId": "abc123-def456-ghi789",
  "email": "[email protected]",
  "problemId": "problem-123",
  "problemName": "Reverse Linked List",
  "completionDate": "2025-01-15T10:30:00.000Z",
  "finalScore": 85,
  "plagiarism": false,
  "reportLink": "https://yourorg.ropes.ai/results/abc123-def456-ghi789",
  "timeTaken": 2700,
  "integrationSource": "LOXO",
  "externalId": "external-job-123",
  "candidateExternalId": "candidate-ats-id-123"
}
FieldTypeDescription
completionDatestringISO 8601 timestamp when the assessment was completed
finalScorenumberThe candidate’s final score (0-100)
plagiarismbooleanWhether integrity risk was flagged as high or very high
reportLinkstringURL to view the detailed results
timeTakennumberTime taken in seconds

interview.expired

{
  "event": "interview.expired",
  "timestamp": "2025-11-25T14:30:00.000Z",
  "interviewId": "abc123",
  "email": "[email protected]",
  "problemId": "prob_456",
  "problemName": "React Dashboard Challenge",
  "expiredAt": "2025-11-25T14:30:00.000Z",
  "wasStarted": false
}
FieldTypeDescription
expiredAtstringISO 8601 timestamp when the assessment expired
wasStartedbooleanWhether the candidate had started the assessment before it expired

Security

Signature Verification

Every webhook request includes an x-ropes-webhook-signature header containing an HMAC-SHA256 signature of the request body, signed with your webhook secret. Use the following code as an example of how to conduct signature verification.
const crypto = require('crypto')

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex')

  return crypto.timingSafeEquals(Buffer.from(signature), Buffer.from(expectedSignature))
}

// In your webhook handler
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-ropes-webhook-signature']

  if (!verifyWebhookSignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature')
  }

  // Process the webhook
  const { event, interviewId } = req.body
  console.log(`Received ${event} for interview ${interviewId}`)

  res.status(200).send('OK')
})

Best Practices

  • Always verify the webhook signature before processing
  • Use HTTPS endpoints only
  • Respond with a 2xx status code within 10 seconds
  • Process webhooks asynchronously if they trigger long-running operations
  • Store your webhook secret securely (e.g., environment variables)

Delivery & Retries

Ropes will attempt to deliver each webhook up to 3 times:
  1. Initial delivery - Immediately when the event occurs
  2. First retry - 1 minute after the initial failure
  3. Second retry - 5 minutes after the first retry
A delivery is considered successful when your endpoint returns a 2xx HTTP status code. After all retry attempts are exhausted, the delivery is marked as failed.

Timeout

Webhook requests timeout after 10 seconds. Ensure your endpoint responds quickly to avoid unnecessary retries. Clients are responsible for handling idempotency on retries.

Testing

During development, you can use tools like webhook.site or ngrok to receive webhooks locally and inspect the payloads.