Skip to main content

Profile Scoring Rules

Profile scoring rules assign points based on lead profile attributes (company size, industry, role, etc.) rather than behavioral actions. Use these to implement ICP (Ideal Customer Profile) scoring.

GET /profile-scoring/rulesets/{id}/rules

List all profile scoring rules for a specific ruleset.

Request

curl -u "CLIENT_ID:CLIENT_SECRET" \
"https://your-api.example.com/profile-scoring/rulesets/ruleset-abc/rules"

Response

Status: 200 OK

{
"rules": [
{
"id": "rule-123",
"ruleset_id": "ruleset-abc",
"profile_field": "company_employee_count",
"operator": "equals",
"value": "501+",
"weight": 50,
"active": true
},
{
"id": "rule-456",
"ruleset_id": "ruleset-abc",
"profile_field": "company_industry",
"operator": "equals",
"value": "Technology",
"weight": 30,
"active": true
}
]
}

POST /profile-scoring/rulesets/{id}/rules

Create a new profile scoring rule within a ruleset.

Request

curl -X POST https://your-api.example.com/profile-scoring/rulesets/ruleset-abc/rules \
-u "CLIENT_ID:CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{
"profile_field": "company_employee_count",
"operator": "equals",
"value": "501+",
"weight": 50
}'

Request Body

FieldRequiredTypeDescription
profile_fieldYesstringThe profile field to evaluate (must be mapped via /profile-scoring/mappings)
operatorYesstringComparison operator (see the full list under Operators Explained below)
valueYesstringThe value to match against
weightYesnumberPoints to award when rule matches (can be negative)
activeNobooleanWhether rule is active (default: true)

Response

Status: 201 Created

{
"id": "rule-789",
"ruleset_id": "ruleset-abc",
"profile_field": "company_employee_count",
"operator": "equals",
"value": "501+",
"weight": 50,
"active": true,
"created_at": "2025-01-15T11:30:00Z"
}

Operators Explained

OperatorDescriptionExample
equalsExact match (case-insensitive)company_size equals "501+"
not_equalsThe field has a value and it differsindustry not_equals "Healthcare"
containsSubstring match. A comma-separated value matches if the field contains any listed termtitle contains "Vice President,VP" (matches "VP of Sales")
not_containsThe field has a value that contains none of the (comma-separated) termstitle not_contains "Intern,Junior,Student"
starts_withThe value begins with the textdomain starts_with "app."
ends_withThe value ends with the textdomain ends_with ".edu"
greater_thanNumeric greater-thanemployees greater_than "100"
greater_than_or_equalNumeric greater-than-or-equalemployees greater_than_or_equal "100"
less_thanNumeric less-thanemployees less_than "50"
less_than_or_equalNumeric less-than-or-equalemployees less_than_or_equal "50"
inMatches any value in a comma-separated listseniority in "VP, Director, C-Level"
not_inThe field has a value that is not in the listseniority not_in "IC, Intern"
betweenNumeric value inside a low,high range (inclusive)employees between "100,1000"
not_betweenNumeric value outside a low,high rangeemployees not_between "100,1000"
is_nullThe field is empty or not providedemail is_null
is_not_nullThe field has a valueemail is_not_null

A note on negation and missing fields. The not_* operators (not_equals, not_contains, not_in, not_between) only match when the field actually has a value that differs. A lead that is missing the field does not match a negation rule, so a rule never awards points (or disqualifies) for data the lead simply does not have. To match leads that are missing a field, use is_null.

Common Errors

Status CodeErrorSolution
400Invalid profile_fieldEnsure field is mapped via /profile-mappings
400Invalid operatorUse one of the operators listed under Operators Explained above
404Ruleset not foundVerify ruleset ID is correct

Example Use Cases

Use Case 1: Enterprise ICP Scoring

Score leads higher if they match enterprise criteria:

# High-value company size
POST /profile-scoring/rulesets/{id}/rules
{"profile_field": "company_employee_count", "operator": "equals", "value": "501+", "weight": 50}

# Target industry
POST /profile-scoring/rulesets/{id}/rules
{"profile_field": "company_industry", "operator": "equals", "value": "Technology", "weight": 30}

# Decision-maker role
POST /profile-scoring/rulesets/{id}/rules
{"profile_field": "contact_seniority", "operator": "contains", "value": "C-Level", "weight": 40}

# Result: C-level contacts from 500+ employee tech companies score 120 points

Use Case 2: Negative Scoring for Poor Fit

Penalize leads that don't match your ICP:

# Too small
POST /profile-scoring/rulesets/{id}/rules
{"profile_field": "company_employee_count", "operator": "equals", "value": "1-10", "weight": -20}

# Wrong industry
POST /profile-scoring/rulesets/{id}/rules
{"profile_field": "company_industry", "operator": "equals", "value": "Retail", "weight": -15}

Important Notes

Profile Fields Must Be Mapped

Before creating profile scoring rules, ensure the profile field is mapped via /profile-mappings:

# 1. Create mapping
POST /profile-scoring/mappings
{"metadata_key": "company_size", "profile_field": "company_employee_count"}

# 2. Then create rule
POST /profile-scoring/rulesets/{id}/rules
{"profile_field": "company_employee_count", "operator": "equals", "value": "501+", "weight": 50}

Profile Data Must Be Sent

Profile scoring only works if you send profile data in event metadata:

POST /ingest
{
"alias_kind": "email",
"alias": "jane@example.com",
"event_type": "Form Submit",
"metadata": {
"company_size": "501+",
"industry": "Technology",
"job_title": "VP Sales"
}
}

See Also