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
| Field | Required | Type | Description |
|---|---|---|---|
profile_field | Yes | string | The profile field to evaluate (must be mapped via /profile-scoring/mappings) |
operator | Yes | string | Comparison operator (see the full list under Operators Explained below) |
value | Yes | string | The value to match against |
weight | Yes | number | Points to award when rule matches (can be negative) |
active | No | boolean | Whether 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
| Operator | Description | Example |
|---|---|---|
equals | Exact match (case-insensitive) | company_size equals "501+" |
not_equals | The field has a value and it differs | industry not_equals "Healthcare" |
contains | Substring match. A comma-separated value matches if the field contains any listed term | title contains "Vice President,VP" (matches "VP of Sales") |
not_contains | The field has a value that contains none of the (comma-separated) terms | title not_contains "Intern,Junior,Student" |
starts_with | The value begins with the text | domain starts_with "app." |
ends_with | The value ends with the text | domain ends_with ".edu" |
greater_than | Numeric greater-than | employees greater_than "100" |
greater_than_or_equal | Numeric greater-than-or-equal | employees greater_than_or_equal "100" |
less_than | Numeric less-than | employees less_than "50" |
less_than_or_equal | Numeric less-than-or-equal | employees less_than_or_equal "50" |
in | Matches any value in a comma-separated list | seniority in "VP, Director, C-Level" |
not_in | The field has a value that is not in the list | seniority not_in "IC, Intern" |
between | Numeric value inside a low,high range (inclusive) | employees between "100,1000" |
not_between | Numeric value outside a low,high range | employees not_between "100,1000" |
is_null | The field is empty or not provided | email is_null |
is_not_null | The field has a value | email 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 Code | Error | Solution |
|---|---|---|
| 400 | Invalid profile_field | Ensure field is mapped via /profile-mappings |
| 400 | Invalid operator | Use one of the operators listed under Operators Explained above |
| 404 | Ruleset not found | Verify 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"
}
}
Related Endpoints
- Update/Delete Profile Rules
- Profile Mappings - Map metadata to profile fields
- Profile Rulesets - Manage rulesets
- Engagement Scoring Rules - Score based on behavioral actions
See Also
- Profile Scoring Guide
- Event Ingestion - How to send profile data in metadata