Skip to content
Docs menu

Lead scoring

Rule-based scores you can sort contacts by. Compute on-demand or in a sweep.

Rules have a kind (FIT, ENGAGEMENT, MANUAL), a condition (field, op, value), and a point award between −1000 and 1000. Operators: eq, ne, gt, lt, contains.

POST/api/lead-scoring/rulesBearer token (ADMIN/MANAGER)

Create a rule

ADMIN or MANAGER only.

Required scopes:contacts.write

Request body

NameTypeDescription
namerequiredstringRule display name.
kindrequiredstringFIT | ENGAGEMENT | MANUAL.
conditionrequiredobject{ field, op, value }.
pointsrequiredintegerAward amount. −1000 to 1000.
isActivebooleanActive flag.

Request body

JSON
{ "name": "Has insurance on file", "kind": "FIT", "condition": { "field": "hasInsurance", "op": "eq", "value": true }, "points": 10 }

Responses

  • 201 CreatedCreated.
    example
    {
      "id": "lsr_9k2j3p…",
      "name": "Has insurance on file",
      "kind": "FIT",
      "condition": { "field": "hasInsurance", "op": "eq", "value": true },
      "points": 10,
      "isActive": true
    }

Code samples

Shell
curl -X POST https://app.contactfollowup.com/api/lead-scoring/rules \
  -H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Has insurance on file", "kind": "FIT", "condition": { "field": "hasInsurance", "op": "eq", "value": true }, "points": 10 }'

List rules

Every rule, active or not.

Required scopes:contacts.read

Responses

  • 200 OKRules.
    example
    { "rules": [{
      "id": "lsr_9k2j3p…",
      "name": "Has insurance on file",
      "kind": "FIT",
      "condition": { "field": "hasInsurance", "op": "eq", "value": true },
      "points": 10,
      "isActive": true
    }] }

Code samples

Shell
curl -X GET https://app.contactfollowup.com/api/lead-scoring/rules \
  -H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
  -H "Content-Type: application/json"

Compute score for one contact

Run every active rule against the contact and persist the result.

Required scopes:contacts.write

Request body

NameTypeDescription
contactIdrequiredstringContact id.

Request body

JSON
{ "contactId": "cln…" }

Responses

  • 200 OKComputed score.
    example
    {
      "contactId": "cln1f8s7p…",
      "score": 47,
      "components": [
        { "ruleId": "lsr_9k2j3p…", "ruleName": "Has insurance on file", "points": 10 },
        { "ruleId": "lsr_5d8w2x…", "ruleName": "Opened email in last 7d", "points": 7 }
      ],
      "computedAt": "2026-05-18T14:00:00Z"
    }

Code samples

Shell
curl -X POST https://app.contactfollowup.com/api/lead-scoring/compute \
  -H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "contactId": "cln…" }'
POST/api/lead-scoring/compute-allBearer token (ADMIN/MANAGER)

Compute scores in bulk

Recompute scores for every contact. Use sparingly.

Required scopes:contacts.write

Responses

  • 200 OKSweep summary.
    example
    { "processed": 1284, "updated": 1284, "durationMs": 4172 }

Code samples

Shell
curl -X POST https://app.contactfollowup.com/api/lead-scoring/compute-all \
  -H "Authorization: Bearer $HEARTHNOTE_TOKEN" \
  -H "Content-Type: application/json"