Buying Groups API
The buyingGroup router provides buying group intelligence including role detection, completeness scoring, member engagement analysis, and candidate discovery for missing roles.
Router namespace: buyingGroup
Source: src/server/trpc/routers/buying-groups.ts
Procedures
| Procedure | Type | Access | Description |
|---|---|---|---|
listByAccount | query | tenant | List buying groups for an account |
getDetail | query | tenant | Full buying group with members, template, and completeness |
getMembers | query | tenant | Members with person details |
getMemberEngagement | query | tenant | Engagement heatmap data per member |
getCandidates | query | tenant | Candidate suggestions for missing roles |
confirmMemberRole | mutation | admin | Confirm a member's detected role |
listAccountsWithGroups | query | tenant | Paginated accounts that have buying groups |
listByAccount
Lists all buying groups associated with a specific account.
buyingGroup.listByAccount.queryOptions(input)
Input
| Field | Type | Required | Description |
|---|---|---|---|
accountId | string | Yes | Account identifier |
Response
[
{
"id": "bg_abc123",
"accountId": "acc_456",
"solutionTag": "enterprise-analytics",
"name": "Enterprise Analytics Buying Committee",
"completenessScore": 0.75,
"roleTemplateId": "tmpl_789",
"createdAt": "2026-03-01T12:00:00.000Z"
}
]
getDetail
Returns a comprehensive view of a buying group including members, the role template, and computed completeness scoring.
buyingGroup.getDetail.queryOptions(input)
Input
| Field | Type | Required | Description |
|---|---|---|---|
buyingGroupId | string | Yes | Buying group identifier |
Response
{
"id": "bg_abc123",
"accountId": "acc_456",
"solutionTag": "enterprise-analytics",
"name": "Enterprise Analytics Buying Committee",
"completenessScore": 0.75,
"roleTemplateId": "tmpl_789",
"members": [
{
"id": "bgm_001",
"personId": "prs_111",
"role": "champion",
"roleConfidence": 0.92,
"roleSource": "title_match",
"isConfirmed": true,
"isDiscovered": false,
"discoverySource": null,
"discoveredEmail": null
},
{
"id": "bgm_002",
"personId": "prs_222",
"role": "decision_maker",
"roleConfidence": 0.78,
"roleSource": "engagement_pattern",
"isConfirmed": false,
"isDiscovered": true,
"discoverySource": "delivrai",
"discoveredEmail": "vp@example.com"
}
],
"template": {
"id": "tmpl_789",
"tenantId": "tenant_001",
"name": "Enterprise Software",
"solutionTag": "enterprise-analytics",
"roles": [
{ "role": "champion", "required": true, "weight": 1.0 },
{ "role": "decision_maker", "required": true, "weight": 1.0 },
{ "role": "technical_evaluator", "required": true, "weight": 0.8 },
{ "role": "budget_holder", "required": false, "weight": 0.6 }
],
"isDefault": false
},
"completeness": {
"score": 0.75,
"filledRoles": ["champion", "decision_maker"],
"missingRoles": ["technical_evaluator"],
"optionalMissing": ["budget_holder"],
"multiplier": 1.15
}
}
The completeness score is computed in real time from the role template and current member roles. It reflects how many required and optional roles are filled, weighted by role importance.
getMembers
Returns buying group members enriched with person details (name, title, email).
buyingGroup.getMembers.queryOptions(input)
Input
| Field | Type | Required | Description |
|---|---|---|---|
buyingGroupId | string | Yes | Buying group identifier |
Response
[
{
"id": "bgm_001",
"personId": "prs_111",
"role": "champion",
"roleConfidence": 0.92,
"roleSource": "title_match",
"isConfirmed": true,
"isDiscovered": false,
"discoverySource": null,
"discoveredEmail": null,
"person": {
"firstName": "Sarah",
"lastName": "Johnson",
"title": "VP of Engineering",
"email": "sarah.johnson@example.com"
}
}
]
getMemberEngagement
Returns engagement heatmap data for buying group members within a configurable time window. Includes engagement status, velocity (increasing/decreasing/stable), and activity counts.
buyingGroup.getMemberEngagement.queryOptions(input)
Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
buyingGroupId | string | Yes | -- | Buying group identifier |
windowDays | number (1-90) | No | 30 | Engagement analysis window in days |
Response
[
{
"personId": "prs_111",
"personName": "Sarah Johnson",
"role": "champion",
"status": "active",
"velocity": "increasing",
"activityCount": 12,
"currentWindowScore": 45.5,
"previousWindowScore": 32.0
},
{
"personId": "prs_222",
"personName": "Mike Chen",
"role": "decision_maker",
"status": "cooling",
"velocity": "decreasing",
"activityCount": 3,
"currentWindowScore": 8.0,
"previousWindowScore": 22.0
}
]
Engagement Status Values
| Status | Description |
|---|---|
active | Significant engagement in current window |
cooling | Engagement declining compared to previous window |
inactive | No engagement in current window |
Velocity Values
| Velocity | Description |
|---|---|
increasing | Current window score > previous window score |
stable | Current and previous scores are similar |
decreasing | Current window score < previous window score |
getCandidates
Suggests candidates for missing roles based on Delivr.ai intent data and engagement patterns. Excludes people who are already members of the buying group.
buyingGroup.getCandidates.queryOptions(input)
Input
| Field | Type | Required | Description |
|---|---|---|---|
buyingGroupId | string | Yes | Buying group identifier |
Response
{
"missingRoles": ["technical_evaluator", "budget_holder"],
"candidates": {
"technical_evaluator": [
{
"personExternalId": "ext_333",
"score": 0.85,
"signals": ["title_match", "content_engagement"],
"email": "tech.lead@example.com"
}
],
"budget_holder": []
}
}
If no role template is assigned, candidates returns empty results with no missing roles. Assign a template via the buying group detail page first.
confirmMemberRole
Confirms a member's role assignment, overriding the detected role if needed. Sets isConfirmed to true on the member record.
buyingGroup.confirmMemberRole.mutationOptions(options)
Access: Admin only
Input
| Field | Type | Required | Description |
|---|---|---|---|
memberId | string | Yes | Buying group member identifier |
confirmedRole | string | Yes | Role to assign (e.g., "champion", "decision_maker") |
Response
{
"success": true,
"memberId": "bgm_001"
}
Example
const trpc = useTRPC();
const queryClient = useQueryClient();
const mutation = useMutation(
trpc.buyingGroup.confirmMemberRole.mutationOptions({
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: trpc.buyingGroup.getDetail.queryKey(),
});
},
})
);
mutation.mutate({ memberId: "bgm_002", confirmedRole: "technical_evaluator" });
listAccountsWithGroups
Returns a paginated list of accounts that have buying groups, with aggregate statistics.
buyingGroup.listAccountsWithGroups.queryOptions(input)
Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
page | number (min 1) | No | 1 | Page number |
pageSize | number (1-100) | No | 50 | Items per page |
sortBy | "name" | "completeness" | No | "completeness" | Sort field |
sortDir | "asc" | "desc" | No | "desc" | Sort direction |
Response
{
"items": [
{
"accountId": "acc_456",
"accountName": "Acme Corporation",
"groupCount": 2,
"bestCompleteness": 0.85
}
],
"total": 42,
"page": 1,
"pageSize": 50
}
Related Pages
- Scoring API -- Entity scoring with buying group completeness multiplier
- Connector API -- Data source connections feeding buying group intelligence
- tRPC Overview -- Client setup and procedure types