> ## Documentation Index
> Fetch the complete documentation index at: https://developers.cutshort.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Receive Real-Time Hiring Events with Cutshort Webhooks

> Configure Cutshort webhooks to receive real-time notifications when candidates are shortlisted, stages change, or offers are made.

Cutshort webhooks send HTTP POST requests to your server when key hiring events occur — a candidate is shortlisted, a stage changes, an invite is accepted. Use webhooks to trigger downstream automation, sync your ATS, or notify your team in real time.

## Setting up a webhook

<Steps>
  <Step title="Open Webhooks settings">
    Go to **Settings** → **Integrations** → **Webhooks** in your Cutshort dashboard.
  </Step>

  <Step title="Add an endpoint">
    Click **Add Endpoint** and enter your public HTTPS URL. Cutshort requires HTTPS for all webhook endpoints.
  </Step>

  <Step title="Select events">
    Select the events you want to receive. You can subscribe to individual events or all events at once.
  </Step>

  <Step title="Save and verify">
    Click **Save**. Cutshort immediately sends a test ping to your endpoint to confirm it is reachable. Respond with HTTP `200` to pass verification.
  </Step>
</Steps>

You can also register a webhook endpoint programmatically via the API:

```bash theme={null}
curl -X POST 'https://api.cutshort.io/v1/webhooks' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://yourapp.com/cutshort-events",
    "events": ["candidate.shortlisted", "candidate.stage_changed", "invite.accepted"]
  }'
```

## Available events

| Event                     | Description                              | Key payload fields                                 |
| ------------------------- | ---------------------------------------- | -------------------------------------------------- |
| `candidate.shortlisted`   | A candidate was added to a job shortlist | `candidate_id`, `job_id`, `match_score`            |
| `candidate.stage_changed` | Candidate moved to a new pipeline stage  | `candidate_id`, `job_id`, `from_stage`, `to_stage` |
| `invite.accepted`         | Candidate accepted an outreach invite    | `candidate_id`, `job_id`, `channel`                |
| `invite.declined`         | Candidate declined an invite             | `candidate_id`, `job_id`                           |
| `offer.made`              | An offer was sent to a candidate         | `candidate_id`, `job_id`, `offer_details`          |
| `job.closed`              | A job was closed                         | `job_id`, `reason`                                 |

## Webhook payload structure

Every webhook request shares the same envelope structure. The `event` field identifies the event type, and `data` contains the event-specific payload.

```json theme={null}
{
  "id": "evt_3mKpL8nQ",
  "event": "candidate.shortlisted",
  "created_at": "2024-01-15T10:30:00Z",
  "data": {
    "candidate_id": "cand_8f3kL9mN",
    "job_id": "job_4xRt2wPv",
    "match_score": 87,
    "candidate": {
      "name": "Priya Menon",
      "headline": "Senior React Developer",
      "location": "Bengaluru"
    }
  }
}
```

## Verifying webhook signatures

Each webhook request includes an `X-Cutshort-Signature` header containing an HMAC-SHA256 signature of the raw request body. Verify the signature using your webhook secret, which you can find in your Cutshort dashboard under **Settings** → **Integrations** → **Webhooks**.

```python theme={null}
import hmac, hashlib

def verify_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)
```

Pass the raw request body (before any JSON parsing) as `payload` to ensure the signature matches exactly.

<Warning>
  Always verify the webhook signature before processing the payload. Reject any requests with invalid or missing signatures to prevent spoofed events from triggering actions in your system.
</Warning>

## Retries and reliability

<Note>
  Cutshort retries failed webhook deliveries up to 5 times with exponential backoff (1 min, 5 min, 30 min, 2 hr, 8 hr). Return HTTP `2xx` within 10 seconds to acknowledge receipt. For slow processing jobs, return `200` immediately and handle the payload asynchronously in a background worker or queue.
</Note>
