For listed agencies

Webhook & CRM integration

When a creditor chooses your agency, we can POST the lead straight into your CRM at the same moment it lands in your dashboard and inbox. One JSON payload, one endpoint, no polling.

Setting it up

  1. Create an endpoint that accepts a JSON POST over HTTPS. Most CRMs have an inbound-webhook or “catch hook” feature; Zapier (Webhooks by Zapier → Catch Hook) and Make (Custom webhook) both work out of the box if yours doesn’t.
  2. Configure it in your dashboardProfile → Webhook: tick Enable webhook, paste your URL, set the auth header (see Authentication) and press Save profile.
  3. Press “Send test webhook” on the same tab. We fire a clearly-marked sample lead (event: "lead.test") at your saved settings and show you your endpoint’s response code.
  4. Map the fields into your CRM using the reference below, keyed on lead.id.

When it fires

You receive one POST per lead, at the moment the lead is assigned to you:

  • a creditor compares the panel and chooses your agency, or
  • Collect Compare reassigns an existing case to you (for example, when another agency couldn’t act on it).

The webhook is a mirror of the lead you’re also sent by email and shown in your dashboard — same data, machine-readable.

The payload

A single JSON object, sent with content-type: application/json:

{
  "version": 2,
  "event": "lead.assigned",
  "lead": {
    "id": 4182,
    "created_at": "2026-07-19T09:41:22.310Z",
    "status": "Active",
    "compare_or_match": "compare",
    "debt": {
      "amount_pence": 745000,
      "amount_gbp": 7450,
      "purpose": "unpaid_invoice",
      "ccj_status": "no",
      "description": "Three unpaid invoices from a wholesale customer, oldest is 5 months overdue."
    },
    "location": {
      "postcode": null,
      "region": "North West"
    },
    "creditor": {
      "name": "Jane Example",
      "email": "[email protected]",
      "phone": "07123456789",
      "address": null
    }
  }
}

Field reference

Any field can be null where marked — build your import to tolerate that.

FieldTypeMeaning
versionintegerPayload contract version. Currently 2 — only bumped for breaking changes.
eventstring"lead.assigned" for real leads. "lead.test" for test fires from your dashboard.
testbooleanPresent (and true) only on test fires. Real leads never carry this field.
lead.idintegerOur unique lead reference — use it as your upsert key. 0 on test fires.
lead.created_atstringISO 8601 UTC timestamp of when the creditor made their enquiry.
lead.statusstringLead status at the moment of delivery (currently always "Active").
lead.compare_or_matchstring | null"compare" — the creditor compared the panel and picked you. "match" — they asked to be matched.
lead.debt.amount_penceinteger | nullTotal debt in pence (all debts combined). Null if the creditor didn’t give a figure.
lead.debt.amount_gbpnumber | nullThe same figure in pounds, for convenience.
lead.debt.purposestring | nullOne of "unpaid_invoice", "commercial_rent", "residential_rent", "other".
lead.debt.ccj_statusstring | nullWhether a CCJ already exists: "yes", "no" or "unsure".
lead.debt.descriptionstring | nullThe creditor’s own free-text description of the situation, when they gave one. Genuinely useful first-call context.
lead.location.postcodestring | nullDebtor postcode. Usually null — we no longer ask for it.
lead.location.regionstring | nullUK region of the debtor (e.g. "North West"). May be "Unknown".
lead.creditor.namestring | nullThe creditor’s name — your new client.
lead.creditor.emailstring | nullCreditor email address.
lead.creditor.phonestring | nullCreditor phone number (UK format).
lead.creditor.addressstring | nullCreditor address, when captured.

Authentication

Set an auth header in your dashboard so your endpoint can reject anything that isn’t from us:

  • Bearer token (recommended): set the header type to Bearer and the value to a long random secret. We send Authorization: Bearer <your secret> with every delivery.
  • Custom scheme: any other header type X with value V is sent as Authorization: X: V.
  • Leave both blank and no Authorization header is sent — fine for catch-hook URLs that are themselves secret, but a token is better.

Verify the header on every request and respond 401 to anything that doesn’t match. Your token is stored securely and never shown again after saving — leave the field blank when saving other changes to keep the existing one.

Delivery behaviour

  • One attempt, no retries. If your endpoint is down or slow, the delivery is not re-tried — but you still have the lead: the email notification and your dashboard are the canonical channels, and both are unaffected.
  • Respond fast with a 2xx. We record your response code but ignore the response body. Do any heavy processing after acknowledging.
  • Delivery results are logged against the lead on our side, so if your CRM ever misses one we can tell you exactly what your endpoint returned.
  • Order isn’t guaranteed and, as with any webhook, build your import as an upsert on lead.id so a duplicate delivery can never create a duplicate record.

Testing

The Send test webhook button in your dashboard fires this at your saved settings — identical shape to a real lead, but marked so you can’t mistake it for one: event is "lead.test", a top-level test: true is present, and lead.id is 0.

To exercise your endpoint locally before saving anything, replay the same shape with cURL:

curl -X POST https://your-crm.example.com/webhooks/collect-compare \
  -H 'content-type: application/json' \
  -H 'authorization: Bearer YOUR_TOKEN' \
  -d '{"version":2,"event":"lead.test","test":true,"lead":{"id":0,"created_at":"2026-07-19T09:00:00.000Z","status":"Active","compare_or_match":"compare","debt":{"amount_pence":745000,"amount_gbp":7450,"purpose":"unpaid_invoice","ccj_status":"no","description":"Sample only"},"location":{"postcode":null,"region":"North West"},"creditor":{"name":"Test Creditor (webhook test)","email":"[email protected]","phone":"07000000000","address":null}}}'

Example receiver

// Node / Express example
app.post('/webhooks/collect-compare', (req, res) => {
  // reject anything without your secret
  if (req.get('authorization') !== `Bearer ${process.env.CC_WEBHOOK_TOKEN}`) {
    return res.sendStatus(401);
  }

  const { event, lead } = req.body;
  if (event === 'lead.test') return res.sendStatus(200); // test fire — nothing to import

  // upsert into your CRM keyed on lead.id, then acknowledge
  importLead(lead);
  res.sendStatus(200);
});

Data protection

The payload contains the creditor’s personal contact details, shared with you solely for this introduction under our agency terms and privacy policy. If a lead is ever reassigned away from you, we’ll email you asking you to delete the creditor’s details from your systems — that includes whatever your webhook imported into your CRM.

Questions, or need a hand wiring it up?

Email [email protected] and we’ll help you get connected. Not listed yet?

List your agency →