Webhooks

Register an endpoint to receive push notifications as each carrier finishes, when a job needs agent input, and when a run completes. Because runs take minutes, webhooks are the preferred integration path; polling remains available as a fallback.

Register a Webhook

POST /v1/webhooks
Authorization: Bearer qs_live_xxxxx
Content-Type: application/json
{
  "url": "https://partner.example.com/hooks/quotesweep",
  "events": [
    "job.completed",
    "quote.action_required",
    "quote.completed",
    "quote.failed"
  ]
}

Response 201 Created

{
  "success": true,
  "data": {
    "id": "wh_01HV...",
    "status": "active",
    "secret": "whsec_xxxxxxxxxxxx"
  }
}

The signing secret is returned once, at registration. Store it securely.

Events

ValueDescription

job.completed

{
  "event": "job.completed",
  "quoteRequestId": "qr_01HV...",
  "externalReference": "0065f00000ABCDE",
  "jobId": "job_01HV...",
  "carrierId": "carrier-a",
  "lineOfBusiness": "bop",
  "status": "success",
  "result": {
    "annualPremium": 12450.22,
    "quoteNumber": "CARR-884213"
  },
  "timestamp": "2026-08-25T14:07:31Z"
}

quote.action_required

{
  "event": "quote.action_required",
  "quoteRequestId": "qr_01HV...",
  "externalReference": "0065f00000ABCDE",
  "jobId": "job_02HV...",
  "carrierId": "carrier-b",
  "actionRequired": {
    "type": "mfa",
    "message": "Carrier sent a verification code to the agent's phone",
    "deepLink": "https://app.quotesweep.com/quotes/qr_01HV.../jobs/job_02HV..."
  },
  "timestamp": "2026-08-25T14:06:10Z"
}

quote.completed

{
  "event": "quote.completed",
  "quoteRequestId": "qr_01HV...",
  "externalReference": "0065f00000ABCDE",
  "status": "partial",
  "summary": {
    "carriersRequested": 5,
    "quotesReturned": 3,
    "lowestAnnualPremium": 12450.22,
    "failedCount": 1,
    "actionRequiredCount": 1
  },
  "timestamp": "2026-08-25T14:09:52Z"
}

Every payload carries quoteRequestId and externalReference, so events can be correlated back to the originating record without holding local state.

Verification

Each request includes an X-QuoteSweep-Signature header. Compute HMAC-SHA256(raw_body, webhook_secret) and compare against it using a constant-time comparison before trusting the payload.

import hmac, hashlib

def verify_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, signature)

Retry Policy

Failed deliveries retry up to three times with exponential backoff (5s, 30s, 5min). Respond 2xx to acknowledge.

Acknowledge quickly

Return a 2xx within 5 seconds and process the payload asynchronously. Delivery is at-least-once, so handlers must be idempotent — key on jobId for job events and quoteRequestId for request events.