Sales reps and follow-up tasks
SalesRep is a workspace-scoped identity for a human seller. It is deliberately separate from
Profile: a rep must exist in the system — assignable, syncable to HubSpot and Nooks — before, or
even without, having a login.
SalesRep
| Field | Meaning |
|---|---|
|
Identity; unique on |
|
Optional link to a |
|
HubSpot owner, used to assign contacts and tasks |
|
Nooks user, used to attribute Nooks calls and assign sequences |
|
HubSpot active list backing the rep’s sequences |
|
HubSpot call segment for attributing calls |
|
Only active reps are assignable |
The record is workspace-scoped so the same person can carry different CRM ids in different workspaces.
Endpoints: GET|POST /api/sales-reps, GET|PATCH|DELETE /api/sales-reps/{id},
GET /api/sales-reps/{id}/calls, GET /api/sales-reps/{id}/tasks, and
GET /api/sales-reps/profile-match?email= which resolves the signed-in user to their rep record.
Rep resolution
| Context | Resolution order |
|---|---|
Nooks call attribution |
|
Sequence |
Contact’s |
Dashboard "my tasks" |
|
SalesRep.nooksUserId must be populated for the primary Nooks match to work; email is only a
fallback and breaks when a rep uses a different address in Nooks.
FollowUpTask
A task assigned to a rep about a specific lead, optionally mirrored into HubSpot and/or Nooks.
| Field | Meaning |
|---|---|
|
Assignee |
|
The lead |
|
Optional links to what created the task |
|
|
|
|
|
External identifiers |
|
|
|
|
|
Stored so an escalation run can be cancelled programmatically |
|
Last escalation timestamp |
|
Scheduling |
|
Per-platform sync timestamps |
|
Free text |
Both external ids are nullable because a workspace may have only one of the two integrations
active. Storing inngestRunId on the row is what allows a completed task to cancel its own pending
escalation instead of letting it fire against work already done.
Escalation
escalationStage advances when a task is not actioned within its window, and reaching stage 3
marks the task failed. Each advance stamps lastEscalatedAt. The escalation ladder is what turns
Contact.heatStatus from hot to warming: a failed rep task hands the lead back to an automated
email track.
Endpoints
GET /api/follow-up-tasks filters by search, status, type, sales_rep_id, due_filter,
sort, created_from, created_to, with pagination. The response includes a stats block
alongside data/total/page/pageSize, so the task board can render its counters from one
request.
POST /api/follow-up-tasks creates a task; GET|PATCH /api/follow-up-tasks/{id} reads and updates
one. The board is at /tasks, and a rep-scoped view at /sales-reps/{id}/tasks.
Nooks-driven outcomes
Calls made by reps in Nooks arrive at POST /api/webhooks/nooks and are stored as Call rows with
channelType = "nooks_call", campaignId = null and targetId = null — they are not campaign
activity. Two disposition-gated flows follow:
| Flow | Trigger |
|---|---|
AI analysis |
Any disposition not in |
CRM closed-lost |
A disposition in |
See Nooks events for payloads and contact-id resolution.