Get risk-tolerance report
/analytics/risk-toleranceReturns the per-number risk-tolerance report for every dedicated and inbound number in the organization over a bounded time window. Numbers are returned sorted by descending risk score (riskiest first). Each entry carries a risk_score (0-100), a risk_level (low/medium/high), a line_type indicating which scoring profile was applied, the raw metrics used to derive it, the ten scored risk_factors (value + points + status per factor), and a daily_data time series of new inbound/outbound conversations for charting. Scope — Org-scoped: any API key in the organization returns the full scorable fleet, regardless of which numbers the key is attached to. Eligibility — Requires at least one dedicated number (Dedicated Commercial or Dedicated Enterprise) or inbound number (Inbound Basic). Organizations with only shared or trial numbers receive 403 dedicated_plan_required. Inbound numbers are scored with the reply-only factor profile described on the Analytics tag. Computation — Real-time; recomputed from Postgres on every request (no cache). Definitions used across the metrics: a conversation is keyed by contact (or group); a new conversation is one whose all-time first message falls inside the window; a reply is a conversation that received 3 or more inbound messages; bursts are the peak count in any single UTC hour of the window. The expensive message-similarity (SimHash) metric is included automatically for fleets of 5 numbers or fewer, and otherwise only when compute=true (larger fleets return message_similarity_percentage: null unless requested).
Headers
AuthorizationRequiredstringYour API key, sent as a bearer token: Authorization: Bearer <api_key>. Editing this stays in sync with the API key box on the right.
Query parameters
daysoptionalintegerLength of the reporting window in days, ending now. Between 1 and 365; defaults to 30. Ignored when from/to are supplied.
fromoptionalintegerWindow start as a Unix epoch timestamp in milliseconds. When supplied, overrides days.
tooptionalintegerWindow end as a Unix epoch timestamp in milliseconds. Defaults to now.
computeoptionalbooleanSet to true to force the expensive message-similarity metric. Small fleets (<= 5 numbers) always compute it; larger fleets omit it unless this flag is set, so message_similarity_percentage may be null otherwise.
Returns
phone_numbersoptionalRiskPhoneReport[]Per-number reports, sorted by descending risk score.
phone_numbersoptionalRiskPhoneReport[]Per-number reports, sorted by descending risk score.
Array of RiskPhoneReport
phone_numberoptionalstringallocation_idoptionalstringline_typeoptionalstringThe line's allocation type, which determines the scoring profile applied. inbound lines are reply-only and use the reduced factor profile described on the Analytics tag; everything else is scored on the full dedicated profile.
"dedicated""inbound""2fa"nullrisk_scoreoptionalnumberOverall risk score, 0 (lowest) to 100 (highest). Clamped sum of the ten risk_factors.
risk_leveloptionalstringBanding of risk_score: low = 0-29 (healthy), medium = 30-59 (monitor), high = 60-100 (likely to be filtered/suspended by carriers).
"low""medium""high"has_activityoptionalbooleanWhether the number sent, received, or reached anyone in the window. Every factor guards on a minimum sample, so a number with no traffic sums to risk_score: 0 -- the same score a well-behaved line earns. Treat false as "nothing to score yet" rather than "lowest risk": don't present the score, and exclude the number from fleet averages.
metricsoptionalRiskMetricsRaw and derived usage metrics for a number over the window. A *conversation* is keyed by contact (1:1) or group; a *new conversation* is one whose all-time first message falls inside the window; a *reply* is a conversation that received 3 or more inbound messages. Averages divide by the days the number could actually send in -- the window length capped to the number's own tenure -- not by the days that happened to have activity. So a line that was quiet for half the period still reads as low volume, while one that only existed for the last 9 days of a 30-day window reports its real pace instead of a third of it.
metricsoptionalRiskMetricsRaw and derived usage metrics for a number over the window. A *conversation* is keyed by contact (1:1) or group; a *new conversation* is one whose all-time first message falls inside the window; a *reply* is a conversation that received 3 or more inbound messages. Averages divide by the days the number could actually send in -- the window length capped to the number's own tenure -- not by the days that happened to have activity. So a line that was quiet for half the period still reads as low volume, while one that only existed for the last 9 days of a 30-day window reports its real pace instead of a third of it.
avg_outbound_conversations_per_dayoptionalnumberNew outbound-initiated conversations started in the window, divided by days active (see the schema description). High values indicate cold-outreach volume (risk-raising).
avg_inbound_conversations_per_dayoptionalnumberNew inbound-initiated conversations (customer messaged first) in the window, divided by days active. High values indicate organic demand (risk-lowering).
inbound_initiated_percentageoptionalnumberShare of new conversations that the customer started, as a percentage: inbound_initiated / (inbound_initiated + outbound_initiated) * 100. Higher is healthier. Only scored once there are >= 5 new conversations.
total_contactsoptionalintegerDistinct contacts (conversation keys) messaged in the window. Large lists suggest broadcast/spam usage.
reply_rateoptionalnumberPercentage of conversations that received a meaningful reply, defined as 3 or more inbound messages: conversations_with_3plus_inbound / total_conversations * 100. One of the strongest spam signals; only scored once there are >= 10 conversations.
avg_inbound_messages_per_conversationoptionalnumberMean inbound messages per conversation in the window. Below 3 (with >= 3 conversations) indicates shallow, low-engagement outreach.
inbound_outbound_message_ratiooptionalnumberInbound messages as a percentage of all messages: total_inbound_messages / total_messages * 100. Low values mean one-way (monologuing) traffic. Only scored once there are >= 10 messages.
max_new_conversations_per_houroptionalintegerPeak number of NEW conversations the number itself opened in any sliding 60-minute window (burst detection). The window slides rather than snapping to clock hours, so a blast straddling :59 is reported at its real rate instead of being split across two buckets. Conversations the customer started are excluded, on every line type. A human pace is roughly <= 15/hour; sustained higher rates signal automation.
max_messages_per_houroptionalintegerPeak outbound messages sent in any sliding 60-minute window (burst detection). Sustained rates above ~100/hour signal automation.
message_similarity_percentageoptionalnumber | nullTemplated-content signal: the largest cluster of near-identical outbound messages (by SimHash) as a percentage of qualifying messages. Only outbound messages with >= 50 characters count, and a valid ratio needs >= 20 qualifying messages. null when not computed (large fleet without compute=true) or below the minimum sample.
inbound_initiatedoptionalintegerCount of new conversations the customer started in the window.
outbound_initiatedoptionalintegerCount of new conversations this number started in the window.
total_conversationsoptionalintegerConversations with any message activity in the window.
total_messagesoptionalintegerInbound + outbound messages in the window (excludes deleted).
total_inbound_messagesoptionalintegerInbound message count in the window.
total_outbound_messagesoptionalintegerOutbound message count in the window.
avg_messages_per_dayoptionalnumbertotal_messages divided by days active.
avg_conversation_depthoptionalnumbertotal_messages / total_conversations (0 when there are no conversations).
risk_factorsoptionalRiskFactorsThe ten additive risk factors that sum (clamped to 0-100) into risk_score. Each factor reports its measured value, the score (points) it contributed, a status, and its impact weight. Positive scores raise risk; negative scores are bonuses. Some factors only score once a minimum sample is reached (otherwise status: insufficient_data, score: 0). The scoring described below is for dedicated lines; where an inbound (reply-only) line differs, the difference is noted on the factor.
risk_factorsoptionalRiskFactorsThe ten additive risk factors that sum (clamped to 0-100) into risk_score. Each factor reports its measured value, the score (points) it contributed, a status, and its impact weight. Positive scores raise risk; negative scores are bonuses. Some factors only score once a minimum sample is reached (otherwise status: insufficient_data, score: 0). The scoring described below is for dedicated lines; where an inbound (reply-only) line differs, the difference is noted on the factor.
outboundConversationsoptionalRiskFactorAvg outbound-initiated conversations/day. Scoring: >50 = +30, 40-50 = +20, 30-40 = +8, else 0. Cold-outreach volume. **Inbound lines:** not_applicable, always 0 — a reply-only line cannot open cold threads.
outboundConversationsoptionalRiskFactorAvg outbound-initiated conversations/day. Scoring: >50 = +30, 40-50 = +20, 30-40 = +8, else 0. Cold-outreach volume. **Inbound lines:** not_applicable, always 0 — a reply-only line cannot open cold threads.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
inboundConversationsoptionalRiskFactorAvg inbound-initiated conversations/day (bonus). Scoring: >=100 = -20, 50-100 = -15, 30-50 = -10, 15-30 = -5, else 0. Organic demand lowers risk. **Inbound lines:** the value is still reported but earns no bonus, since inbound volume is the product working as sold rather than evidence of earned trust.
inboundConversationsoptionalRiskFactorAvg inbound-initiated conversations/day (bonus). Scoring: >=100 = -20, 50-100 = -15, 30-50 = -10, 15-30 = -5, else 0. Organic demand lowers risk. **Inbound lines:** the value is still reported but earns no bonus, since inbound volume is the product working as sold rather than evidence of earned trust.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
inboundPercentageoptionalRiskFactorPercentage of new conversations the customer started (gradient). Scoring ranges from -15 (>=90% inbound) up to +20 (<20% inbound). Requires >= 5 new conversations to score. **Inbound lines:** not_applicable, always 0 — a reply-only line sits at ~100% by construction.
inboundPercentageoptionalRiskFactorPercentage of new conversations the customer started (gradient). Scoring ranges from -15 (>=90% inbound) up to +20 (<20% inbound). Requires >= 5 new conversations to score. **Inbound lines:** not_applicable, always 0 — a reply-only line sits at ~100% by construction.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
totalContactsoptionalRiskFactorDistinct contacts messaged in the window. Scoring: >2000 = +15, 1500-2000 = +8, else 0.
totalContactsoptionalRiskFactorDistinct contacts messaged in the window. Scoring: >2000 = +15, 1500-2000 = +8, else 0.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
replyRateoptionalRiskFactorPercentage of conversations with 3+ inbound messages. Scoring: <20% = +35, 20-30% = +20, 30-40% = +8, >=50% = -5. Requires >= 10 conversations to score. Highest-weight (very_high) factor.
replyRateoptionalRiskFactorPercentage of conversations with 3+ inbound messages. Scoring: <20% = +35, 20-30% = +20, 30-40% = +8, >=50% = -5. Requires >= 10 conversations to score. Highest-weight (very_high) factor.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
inboundMsgCountoptionalRiskFactorAvg inbound messages per conversation. Scoring: <3 = +25 (with >= 3 conversations), else 0. **Inbound lines:** relaxed to <1.5 = +10, because a customer asking one question and getting an answer is the expected shape of an inbound thread.
inboundMsgCountoptionalRiskFactorAvg inbound messages per conversation. Scoring: <3 = +25 (with >= 3 conversations), else 0. **Inbound lines:** relaxed to <1.5 = +10, because a customer asking one question and getting an answer is the expected shape of an inbound thread.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
inboundOutboundRatiooptionalRiskFactorInbound share of all messages. Scoring: <=10% = +20, 11-29% = +10, >=30% = 0. Requires >= 10 messages to score. Detects one-way traffic.
inboundOutboundRatiooptionalRiskFactorInbound share of all messages. Scoring: <=10% = +20, 11-29% = +10, >=30% = 0. Requires >= 10 messages to score. Detects one-way traffic.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
newConversationBurstsoptionalRiskFactorPeak new conversations the number itself opened in any sliding 60-minute window; conversations the customer started are excluded on every line type, so a rush of inbound demand is never mistaken for a blast. Base scoring: >60 = +40, 40-60 = +30, 25-40 = +20, 15-25 = +10, else 0. The base score is then multiplied by decay_weight (see RiskFactor), so an old burst costs less than the same burst today. Very-high weight; hallmark of mass-outreach automation.
newConversationBurstsoptionalRiskFactorPeak new conversations the number itself opened in any sliding 60-minute window; conversations the customer started are excluded on every line type, so a rush of inbound demand is never mistaken for a blast. Base scoring: >60 = +40, 40-60 = +30, 25-40 = +20, 15-25 = +10, else 0. The base score is then multiplied by decay_weight (see RiskFactor), so an old burst costs less than the same burst today. Very-high weight; hallmark of mass-outreach automation.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
messageBurstsoptionalRiskFactorPeak outbound messages in any sliding 60-minute window. Base scoring: >200 = +30, 150-200 = +20, 100-150 = +10, else 0, then multiplied by decay_weight.
messageBurstsoptionalRiskFactorPeak outbound messages in any sliding 60-minute window. Base scoring: >200 = +30, 150-200 = +20, 100-150 = +10, else 0, then multiplied by decay_weight.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
messageSimilarityoptionalRiskFactorLargest near-identical outbound cluster (SimHash) as a percentage of qualifying messages (>= 50 chars). Scoring: >70% = +15, 50-70% = +8, <30% = -2. Only evaluated with >= 20 qualifying messages and when the expensive metric was computed; otherwise value: null, score: 0.
messageSimilarityoptionalRiskFactorLargest near-identical outbound cluster (SimHash) as a percentage of qualifying messages (>= 50 chars). Scoring: >70% = +15, 50-70% = +8, <30% = -2. Only evaluated with >= 20 qualifying messages and when the expensive metric was computed; otherwise value: null, score: 0.
valueoptionalnumber | nullThe measured value for this factor (units depend on the factor).
scoreoptionalnumberPoints this factor contributed to the total risk score.
statusoptionalstringQualitative status for display. not_applicable means the factor doesn't apply to this line type (e.g. outbound-initiation factors on a reply-only inbound number) and contributed 0 points.
"ok""bonus""warning""high""insufficient_data""not_applicable"impactoptionalstringRelative weight of this factor in the overall score.
"low""medium""high""very_high"sampleSizeoptionalintegerSample size backing the value, when the factor guards on a minimum sample.
peak_atoptionalstring | nullBurst factors only (newConversationBursts, messageBursts). UTC date (YYYY-MM-DD) on which the window reported in value began.
scored_valueoptionalnumberBurst factors only. The window count the score was actually taken from. Because each daily candidate is aged before comparison, the costliest burst is not always the biggest one: a month-old 639/h can score less than a 240/h from yesterday. Equals value whenever the peak is also the scored window.
scored_atoptionalstring | nullBurst factors only. UTC date (YYYY-MM-DD) of the window described by scored_value.
decay_weightoptionalnumberBurst factors only. Recency multiplier applied to the base band score, 0.5 ^ (age_days / 21) with a floor of 0.25. A burst is evidence that ages: without this, one two-minute event held a number at high risk for the entire window. Only the burst factors decay; every other factor is already a window average.
daily_dataoptionalRiskDailyData
daily_dataoptionalRiskDailyDataoutbound_conversationsoptionalRiskDailySeriesPoint[]
outbound_conversationsoptionalRiskDailySeriesPoint[]Array of RiskDailySeriesPoint
dateoptionalstringUTC calendar day (YYYY-MM-DD).
countoptionalintegerinbound_conversationsoptionalRiskDailySeriesPoint[]
inbound_conversationsoptionalRiskDailySeriesPoint[]Array of RiskDailySeriesPoint
dateoptionalstringUTC calendar day (YYYY-MM-DD).
countoptionalintegerperiod_daysoptionalintegerwindowoptionalRiskWindowThe concrete time window the report was computed over.
windowoptionalRiskWindowThe concrete time window the report was computed over.
fromoptionalintegerWindow start (Unix epoch ms).
tooptionalintegerWindow end (Unix epoch ms).
is_defaultoptionalbooleanTrue when the caller supplied no window params (default 30 days).
calculated_atoptionalintegerWhen the report was computed (Unix epoch ms).
computed_with_expensive_metricsoptionalbooleanWhether the message-similarity metric was included.
Response codes
Sends a live request with your values and shows the real response below. Your key is stored only in this browser.
curl -X GET https://api.blooio.com/v2/api/analytics/risk-tolerance?days=30&from=0&to=0&compute=false \{ "phone_numbers": [ { "phone_number": "+15551234567", "allocation_id": "obj_a1b2c3d4", "line_type": "dedicated", "risk_score": 0, "risk_level": "low", "has_activity": true, "metrics": { "avg_outbound_conversations_per_day": 0, "avg_inbound_conversations_per_day": 0, "inbound_initiated_percentage": 0, "total_contacts": 3, "reply_rate": 0, "avg_inbound_messages_per_conversation": 0, "inbound_outbound_message_ratio": 0, "max_new_conversations_per_hour": 0, "max_messages_per_hour": 0, "message_similarity_percentage": 0, "inbound_initiated": 0, "outbound_initiated": 0, "total_conversations": 3, "total_messages": 3, "total_inbound_messages": 3, "total_outbound_messages": 3, "avg_messages_per_day": 0, "avg_conversation_depth": 0 }, "risk_factors": { "outboundConversations": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "inboundConversations": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "inboundPercentage": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "totalContacts": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "replyRate": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "inboundMsgCount": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "inboundOutboundRatio": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "newConversationBursts": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "messageBursts": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 }, "messageSimilarity": { "value": 0, "score": 0, "status": "ok", "impact": "low", "sampleSize": 50, "peak_at": "2025-01-15T09:30:00Z", "scored_value": 0, "scored_at": "2025-01-15T09:30:00Z", "decay_weight": 0 } }, "daily_data": { "outbound_conversations": [ { "date": "2026-07-01", "count": 3 } ], "inbound_conversations": [ { "date": "2026-07-01", "count": 3 } ] } } ], "period_days": 0, "window": { "from": 0, "to": 0, "is_default": true }, "calculated_at": 37.7749, "computed_with_expensive_metrics": false}