Scoring

Native scoring framework

Configure how Saber turns signal results into structured, explainable fit and urgency scores (0–100) for companies and contacts. Scoring sits on top of the signal layer — the engine is signal-agnostic, so any data the signal layer can ingest becomes scoreable.

How it fits together

  1. Profile — a named, org-scoped configuration bound to a single object type (company or contact). E.g. "EMEA Enterprise", "Mid-Market SaaS". A single object can be assigned multiple profiles of the matching type.

  2. Rule — within a profile, maps one signal template to point values for one dimension (fit or urgency). The shape of pointValues depends on the signal's answer type (boolean, number/percentage/currency ranges, or list choices).

  3. Assignment — links a profile to a specific company or contact. Triggers an immediate recompute so the score appears without waiting for the next signal run.

  4. Score result — the computed score for one (profile, object, dimension) triple. Includes a per-rule contribution breakdown so the number is always explainable, plus the previous score for delta views.

Computation semantics

Score is (earned / maxPossible) * 100. All rules in a profile/dimension count toward the denominator regardless of whether a signal answer exists — unanswered rules earn 0 points but their max still counts. This keeps low-coverage scores conservatively low so they don't falsely look high. signalCoverage and totalRules are returned alongside the score so consumers can see how complete it is.

When scores recompute

In v1 scoring is manual-trigger:

  • Assigning a profile to an object → immediate recompute

  • Upserting or deleting a rule → recompute every object assigned to the profile

  • Calling POST /v1/scoring/compute directly

Auto-trigger on signal completion is on the v1.5 roadmap.

List scoring profiles

get

List all scoring profiles for the authenticated organisation.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Responses
chevron-right
200

Profiles retrieved

application/json

Named, org-scoped scoring configuration that groups rules for a specific object type.

idstring · uuidRequiredExample: 442932e4-9a9f-48c0-a79e-6366a732a52b
organizationIdstringRequiredExample: 66575d79e8350cba826a36b1
typestring · enumRequired

Object type this profile scores. Immutable after creation.

Possible values:
namestringRequiredExample: EMEA Enterprise
descriptionstring · nullableOptionalExample: Companies with 1000+ headcount in EMEA
createdAtstring · date-timeRequired
updatedAtstring · date-timeRequired
get
/v1/scoring/profiles

Create a scoring profile

post

Create a named, org-scoped scoring profile. A profile groups scoring rules for a single object type (company or contact) and produces fit/urgency scores for any object assigned to it. A single object can be assigned to multiple profiles of the matching type.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Body
profileTypestring · enumRequired

Object type this profile will score

Possible values:
namestringRequiredExample: EMEA Enterprise
descriptionstring · nullableOptional
Responses
post
/v1/scoring/profiles

Get a scoring profile

get
Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Path parameters
profileIdstring · uuidRequired

Scoring profile UUID

Responses
chevron-right
200

Profile retrieved

application/json

Named, org-scoped scoring configuration that groups rules for a specific object type.

idstring · uuidRequiredExample: 442932e4-9a9f-48c0-a79e-6366a732a52b
organizationIdstringRequiredExample: 66575d79e8350cba826a36b1
typestring · enumRequired

Object type this profile scores. Immutable after creation.

Possible values:
namestringRequiredExample: EMEA Enterprise
descriptionstring · nullableOptionalExample: Companies with 1000+ headcount in EMEA
createdAtstring · date-timeRequired
updatedAtstring · date-timeRequired
get
/v1/scoring/profiles/{profileId}

Update a scoring profile

put

Rename or re-describe a profile. Profile type is immutable.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Path parameters
profileIdstring · uuidRequired

Scoring profile UUID

Body
namestringRequiredExample: Enterprise ICP
descriptionstring · nullableOptionalExample: Companies with 1000+ headcount
Responses
chevron-right
200

Profile updated

application/json

Named, org-scoped scoring configuration that groups rules for a specific object type.

idstring · uuidRequiredExample: 442932e4-9a9f-48c0-a79e-6366a732a52b
organizationIdstringRequiredExample: 66575d79e8350cba826a36b1
typestring · enumRequired

Object type this profile scores. Immutable after creation.

Possible values:
namestringRequiredExample: EMEA Enterprise
descriptionstring · nullableOptionalExample: Companies with 1000+ headcount in EMEA
createdAtstring · date-timeRequired
updatedAtstring · date-timeRequired
put
/v1/scoring/profiles/{profileId}

Delete a scoring profile

delete

Deletes the profile and cascades to its rules, assignments, and score results.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Path parameters
profileIdstring · uuidRequired

Scoring profile UUID

Responses
delete
/v1/scoring/profiles/{profileId}

No content

List scoring rules for a profile

get
Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Path parameters
profileIdstring · uuidRequired

Scoring profile UUID

Responses
chevron-right
200

Rules retrieved

application/json

Maps one signal template to point values for a given dimension within a profile.

idstring · uuidRequired
profileIdstring · uuidRequired
signalTemplateIdstringRequired

Stable parent template ID (not the version ID). Resolved at compute time across versions.

dimensionstring · enumRequiredPossible values:
selectorstring · nullableOptional

Reserved for future selector-based scoring (jsonpath, list filters). Always null in v1; multi-selector rules become possible in a later release without a follow-up migration.

createdAtstring · date-timeRequired
get
/v1/scoring/profiles/{profileId}/rules

Upsert a scoring rule

put

Create or replace the rule for (profileId, signalTemplateId, dimension). Triggers a recompute of every object assigned to the profile so existing scores reflect the new rule immediately.

The shape of pointValues depends on the answer type of the referenced signal template:

  • boolean{ "true": 20, "false": -5 }

  • number / percentage / currency{ "ranges": [{ "min": 0, "max": 500, "points": 15 }] } (upper bound is exclusive)

  • list{ "choices": { "Salesforce": 10, "HubSpot": 8 }, "mode": "additive" }mode is optional; supported values are additive (default), best-match, contains-all, contains-none, and exact-match.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Path parameters
profileIdstring · uuidRequired

Scoring profile UUID

Body
signalTemplateIdstringRequired
dimensionstring · enumRequiredPossible values:
answerTypestring · enumRequired

Drives shape validation for pointValues. Must match the referenced signal template's answer type — mismatch surfaces as an INVALID_POINT_VALUES 422 at write time rather than a silent compute failure later.

Possible values:
Responses
chevron-right
200

Rule upserted

application/json

Maps one signal template to point values for a given dimension within a profile.

idstring · uuidRequired
profileIdstring · uuidRequired
signalTemplateIdstringRequired

Stable parent template ID (not the version ID). Resolved at compute time across versions.

dimensionstring · enumRequiredPossible values:
selectorstring · nullableOptional

Reserved for future selector-based scoring (jsonpath, list filters). Always null in v1; multi-selector rules become possible in a later release without a follow-up migration.

createdAtstring · date-timeRequired
put
/v1/scoring/profiles/{profileId}/rules

Delete a scoring rule

delete

Removes the rule and triggers a recompute of every object assigned to the profile so scores never silently go stale.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Path parameters
profileIdstring · uuidRequired

Scoring profile UUID

ruleIdstring · uuidRequired

Scoring rule UUID

Responses
delete
/v1/scoring/profiles/{profileId}/rules/{ruleId}

No content

List profile assignments for an object

get

Returns every profile a given object is assigned to.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Query parameters
objectTypestring · enumRequired

Object type (company or contact)

Possible values:
objectIdstringRequired

For company use the domain (e.g. acme.com); for contact use the LinkedIn profile URL

Responses
chevron-right
200

Assignments retrieved

application/json

Links a scoring profile to one company or contact.

idstring · uuidRequired
profileIdstring · uuidRequired
organizationIdstringRequired
objectTypestring · enumRequiredPossible values:
objectIdstringRequired

For companies, the domain (e.g. acme.com); for contacts, the LinkedIn profile URL.

Example: acme.com
assignedAtstring · date-timeRequired
get
/v1/scoring/assignments

Assign a profile to a single object

post

Links one company or contact to a scoring profile. Triggers immediate score computation so the score appears without waiting for the next signal run. Returns 422 if the object type does not match the profile's configured type.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Body
profileIdstring · uuidRequired
objectTypestring · enumRequiredPossible values:
objectIdstring · min: 1 · max: 500Required

For company, the domain; for contact, the LinkedIn profile URL.

Responses
post
/v1/scoring/assignments

Assign a profile to many objects at once

post

Links many company or contact IDs to a single profile in one call. Skips duplicates (returns only newly created rows) and triggers an immediate score computation per newly assigned object.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Body
profileIdstring · uuidRequired
objectTypestring · enumRequiredPossible values:
objectIdsstring[] · min: 1 · max: 500Required

Capped at 500 per request to bound fan-out (one DB insert + one Temporal workflow start per object). Paginate larger lists by issuing multiple requests.

Example: ["acme.com","stripe.com","framer.com"]
Responses
post
/v1/scoring/assignments/bulk

Remove a profile assignment

delete

Removes the assignment and cleans up any score results computed for this (profile, object) pair.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Path parameters
assignmentIdstring · uuidRequired

Profile assignment UUID

Responses
delete
/v1/scoring/assignments/{assignmentId}

No content

Read scores for one or more objects

get

Returns one row per (profile, object, dimension) triple. Pass objectId multiple times to read scores for several objects in a single call. The response includes the per-rule contribution breakdown so the score is always explainable.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Query parameters
objectTypestring · enumRequiredPossible values:
objectIdstring[]Required

Repeatable. For company use the domain; for contact use the LinkedIn profile URL.

Responses
chevron-right
200

Scores retrieved (empty array if no scores exist for the given objects)

application/json

Latest computed score for one (profile, object, dimension) triple. Includes the per-rule contribution breakdown so the score is always explainable, plus a delta view of the previous score.

idstring · uuidRequired
profileIdstring · uuidRequired
organizationIdstringRequired
objectTypestring · enumRequiredPossible values:
objectIdstringRequired
dimensionstring · enumRequiredPossible values:
scorenumber · max: 100Required

Score in [0, 100] computed as (earned / maxPossible) * 100. All rules count toward the denominator regardless of whether a signal answer exists, so low-coverage scores stay conservatively low.

Example: 40
previousScorenumber · nullableOptional

Score from the previous compute, or null on first compute.

Example: 35
signalCoverageintegerRequired

Number of rules with a signal answer available at compute time.

Example: 1
totalRulesintegerRequired

Total rules in the profile/dimension.

Example: 1
computedAtstring · date-timeRequired
versionintegerRequired

Increments on every recompute.

Example: 3
get
/v1/scoring/scores

Trigger score recomputation

post

Queues a Temporal workflow per object to recompute scores against the latest signal data. Idempotent — duplicate triggers for the same object attach to the running workflow rather than starting a new one.

Returns 202 Accepted with {queued, failed} counts as soon as dispatches finish (not the computes — those run asynchronously, and results become available via GET /v1/scoring/scores). A non-zero failed means some objects' dispatches failed (typically Temporal unavailable for those specific calls); if every dispatch fails the endpoint returns 502 instead.

Authorizations
AuthorizationstringRequired

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

Body
objectTypestring · enumRequiredPossible values:
objectIdsstring[] · min: 1 · max: 500Required

For company, domains; for contact, LinkedIn profile URLs. Capped at 500 per request — paginate larger lists.

Responses
post
/v1/scoring/compute

Last updated