Skip to content

should_send

Should this message go out now? POST /v1/decisions/should_send. $0.003 per answer. Scope decisions:write.

Call it as the last step before your agent sends a message, after the message is written. It weighs the message, the decisions that led to it and the inbox health numbers you supply. Verdict never sends anything; it only answers.

Field Type Required Description
message object yes The prepared message.
message.channel enum: “email”, “other” yes Channel the message will go out on.
message.subject string no Subject line.
message.body string yes Plain-text body as it will be sent. At most 8192 bytes of UTF-8.
decision_ids array of string yes The decisions behind the message (for example qualify_firm and pick_person), 1 to 10.
inbox_health InboxHealth yes Inbox health you measure; Verdict never reads your inbox.
inbox_health.bounce_rate_7d number no Share of sends that bounced over the last 7 days.
inbox_health.spam_complaint_rate_7d number no Share of sends marked as spam over the last 7 days.
inbox_health.reply_rate_7d number no Share of sends replied to over the last 7 days.
inbox_health.sent_today integer no Messages sent from this inbox today.
inbox_health.daily_limit integer no Your daily send limit for this inbox.
inbox_health.domain_age_days integer no Age of the sending domain in days.
recipient object no Optional contact history of the recipient.
recipient.last_contacted_at string (date-time) no When you last wrote to this recipient.
recipient.touches_30d integer no Messages sent to this recipient in 30 days.
icp_id string yes The ICP profile to decide against.

decision_ids are the earlier decisions behind this message (for example the qualify_firm and pick_person ids). inbox_health comes from your sending tool: bounce rate, complaint rate, today’s volume and limit, domain age.

The common envelope plus:

  • send: probability the message should go out now. Same value as p.
  • answer: send or hold.
  • hold_reason: why to hold, when answer is hold.
hold_reason Meaning
upstream_decision_weak A decision behind the message is below its threshold; re-check the firm, person or signal.
upstream_decision_missing A decision id behind the message is unknown; make the decision first.
inbox_health_degraded The sending inbox is unhealthy; pause sending from it.
daily_volume_limit The inbox has hit its daily volume; send tomorrow.
recently_contacted The recipient was contacted too recently; wait.
message_issue Fix the message before sending.
recipient_opted_out The recipient opted out; never send.
low_confidence The overall send probability is below threshold without a single dominant cause.
reason_code Meaning
all_checks_passed The upstream decisions, inbox health and message checks all support sending now.
upstream_decision_below_threshold At least one decision behind the message is below its current threshold.
upstream_decision_missing At least one decision id behind the message is unknown to this organization.
inbox_health_degraded The supplied inbox health (bounce, spam-complaint or reply rates) is outside safe bounds.
daily_volume_limit_reached The sending inbox has reached the daily volume the caller supplied.
recipient_recently_contacted The recipient was contacted too recently according to the supplied history.
message_quality_issue The message has a defect such as an unfilled template variable or an empty body.
recipient_opted_out An earlier outcome shows the recipient opted out.

$0.003 when an answer is returned. Errors bill nothing.

Request
curl -X POST 'https://api.askverdict.io/v1/decisions/should_send' \
-H "Authorization: Bearer $VERDICT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H 'Content-Type: application/json' \
-d '{
"message": {
"channel": "email",
"subject": "Trade ops after your raise",
"body": "Hi Dana, congratulations on the new fund. We help 10-person advisers automate trade reconciliation. Open to a short call next week?"
},
"decision_ids": [
"dec_01JC3Z4Y8R9K2M5N7P1Q3S5T7V"
],
"inbox_health": {
"bounce_rate_7d": 0.012,
"spam_complaint_rate_7d": 0.0005,
"sent_today": 38,
"daily_limit": 50
},
"recipient": {
"touches_30d": 1
},
"icp_id": "icp_01JC3Z4Y8R9K2M5N7P1Q3S5T7V"
}'
Response 200
{
"id": "dec_01JC3Z4Y8R9K2M5N7P1Q3S5T7V",
"version": "2026-11-01",
"question_set_version": "2026-11-01",
"model": "jev",
"calibration": {
"basis": "org",
"n_outcomes": 412,
"threshold": 0.6
},
"latency_ms": 180,
"created_at": "2026-11-07T14:03:00Z",
"decision": "should_send",
"p": 0.88,
"answer": "send",
"reason_code": "all_checks_passed",
"reason": "Upstream decisions clear their thresholds and inbox health is within bounds.",
"evidence": [
{
"source": "request",
"url": null,
"observed_at": "2026-11-07",
"pointer": "/inbox_health"
}
],
"send": 0.88,
"hold_reason": null,
"cost": {
"decision_usd": 0.003,
"vendor_usd": 0,
"total_usd": 0.003
},
"balance_usd": 18.301
}