Email Outcome Calibration
Build an owned accuracy loop by attaching real delivery and bounce outcomes to earlier email-validation decisions. Outcome operations are append-only and charge zero credits. Use separate API keys in production:email:outcomes:writeimports evidence but cannot read reports.email:outcomes:readreads aggregate reports but cannot upload addresses.
Automate EmailBison outcomes
Create a revocable, write-only connector URL with an API key carryingemail:outcomes:write:
cURL
webhook_url once. Add that URL in EmailBison and enable
only email_sent, email_opened, email_bounced, lead_replied,
lead_interested, and lead_unsubscribed. Creating another connector rotates
the credential and immediately invalidates the previous URL.
email_sent is mandatory because it supplies the denominator for prospective
bounce-rate measurement. If other events arrive before any sent event, the
connector reports denominator_status=sent_event_missing and all accuracy
gates remain fail-closed.
GTM APIs stores only the connector-token hash. The webhook accepts only a
bounded JSON body, deduplicates retries by EmailBison’s stable scheduled-email
ID, and never stores campaign message bodies or arbitrary EmailBison metadata.
Known DSN fields are used transiently for bounce classification. Replies become
confirmed delivery evidence; opens and sent-with-no-bounce observations remain
separate, weaker signals.
cURL
connector_unavailable means the
account cannot use this connector. Retry connector_status_failed,
connector_create_failed, or connector_revoke_failed with bounded backoff.
After connector_revoke_failed, treat the existing webhook credential as
active until a later revoke request succeeds.
Import outcomes
source plus external_id is the
idempotency key. Include the provider’s enhanced SMTP code and diagnostic text
when available; specific DSN evidence takes precedence over a coarse label such
as bounce or rejected.
cURL
email or lead_email, bounce_type, status, smtp_code,
action, enhanced_status, bounce_reason, diagnostic, dsn_message, dsn_subject,
bounced_at, arrival_date, last_attempt_date, will_retry_until, original_recipient,
final_recipient, remote_mta, reporting_mta, dsn_gateway, received_from_mta, and emailbison_lead_id
columns. Raw diagnostic text is used for classification but is not persisted as
outcome metadata.
RFC-native exports can use Action and Status directly. The importer keeps
the transport-independent Status code as classification evidence instead of
replacing it with the coarse event outcome. Action accepts only failed,
delayed, delivered, relayed, or expanded, without regard to case. A
different non-empty value rejects that row as invalid_dsn_semantics and
cannot create a suppression. Balanced RFC comments are ignored before the
action is selected. Comment text cannot supply or override the action, and a
malformed comment rejects the row.
Action and Status are not redundant. A failed report can keep a 4.x
temporary-failure Status after the MTA abandons retries. The importer accepts
that standards-defined pair as bounced_soft and does not create a permanent
recipient suppression.
When a recognized Action is supplied, a non-empty Status must use the RFC
3464 status-code form, such as 5.1.1. The second and third fields cannot have
leading zeroes, and an RFC comment can follow the code. Comment text is ignored
for classification and cannot add another status code or diagnostic. Malformed
structured Status evidence rejects that row as invalid_dsn_semantics and
cannot create a suppression. Without an RFC Action, generic vendor status
text keeps its existing import behavior.
RFC Original-Recipient and Final-Recipient values use
rfc822; person@example.com form. When Original-Recipient is supplied, it
must match email and can safely correlate a different final address after
forwarding. Without it, Final-Recipient must match email. Malformed,
foreign-address, and conflicting recipient evidence rejects the row before it
can affect suppression or accuracy reports.
RFC comments are removed before the address type and mailbox are checked.
Comment text cannot supply either value, and malformed comments reject the row.
RFC Remote-MTA uses dns; mx.example.com form when the remote system has a
DNS name. A valid DNS hostname is bounded provider evidence for the system that
issued the diagnostic, and it takes precedence over route aliases and
diagnostic prose. Foreign MTA types, malformed hosts, IP literals, and
provider lookalikes remain non-attributing evidence and cannot activate a
provider-specific rule.
RFC comments are removed before the MTA type and hostname are checked. Comment
text cannot supply either value, and malformed comments fail closed.
RFC Reporting-MTA uses the same typed form and is required in a complete DSN.
When Remote-MTA is absent, a valid DNS Reporting-MTA identifies the system
that issued the diagnostic and takes precedence over route aliases and prose.
When Remote-MTA is supplied, it always controls issuer selection. An invalid
or foreign Remote-MTA blocks Reporting-MTA fallback instead of attributing the
remote diagnostic to the reporting gateway.
RFC DSN-Gateway identifies the gateway that translated a foreign delivery
notification. It is not the diagnostic issuer. Remote-MTA or Reporting-MTA
still controls attribution when present. Without either issuer field, supplied
DSN-Gateway evidence blocks provider inference from route aliases and prose.
RFC Received-From-MTA identifies the upstream MTA that handed the message to
the reporting MTA. It is not the diagnostic issuer. Remote-MTA or
Reporting-MTA still controls attribution when present. Without either issuer
field, supplied Received-From-MTA evidence also blocks route-alias and prose
provider inference.
When occurred_at is absent, RFC Last-Attempt-Date supplies the delivery
attempt time. It must use RFC 822 date-time syntax with a numeric +HHMM or
-HHMM timezone. Invalid or future-dated values reject that row instead of
falling back to import time. An explicit valid occurred_at takes precedence.
occurred_at uses RFC 3339 syntax. Lowercase t and z are accepted and
normalized to uppercase UTC. Z, +00:00, and -00:00 all identify a UTC
instant; -00:00 additionally reports that local-zone provenance is unknown.
Fractions through the sixth fractional position are preserved and compared at
microsecond precision. Non-zero precision beyond that position is rejected as
invalid_timestamp before PostgreSQL can round it; supply the source system’s
canonical timestamp at microsecond precision or lower.
Leap-second notation such as 23:59:60Z is rejected as invalid_timestamp
because the canonical UTC chronology cannot represent the extra second
without loss. Supply the source system’s canonical POSIX timestamp instead.
RFC Arrival-Date uses the same numeric-timezone syntax and records when the
message reached the Reporting MTA. It never replaces occurred_at or
Last-Attempt-Date as the outcome time. Malformed or future values reject the
row, as does an Arrival-Date later than a supplied valid Last-Attempt-Date.
RFC Will-Retry-Until uses the same syntax and is accepted only with
Action: delayed. It records the retry horizon, so a future value is valid and
never becomes occurred_at. Malformed values, use with any other action, and a
deadline before Arrival-Date or Last-Attempt-Date reject the row.
For all three RFC date fields, balanced comments are removed before parsing.
Comment text cannot supply or replace the timestamp, and malformed comments
reject the row through the same date-field error.
The weekday is optional. When supplied, it must match the stated local calendar
date before timezone conversion. A mismatch rejects the row through the same
date-field error and cannot affect suppression freshness.
Both +0000 and -0000 identify Universal Time. The -0000 form additionally
reports that local-zone provenance is unknown; it is accepted and normalized to
the same canonical UTC instant.
cURL
index, stable machine-readable code, and
human-readable reason; the response does not repeat their email addresses.
Branch on code, do not parse reason, and preserve unknown non-empty future
codes.
Import request errors use
invalid_json, invalid_csv, missing_outcomes,
too_many_outcomes, or payload_too_large. Retry outcome_import_failed with
the same provider event identities. outcome_suppression_failed means the
outcome import did not finish its fail-closed suppression step; retry the same
import rather than creating different event identities.
Evidence semantics
Only
delivered and confirmed bounced_hard are decision-grade mailbox labels.
For RFC DSNs, include the per-recipient action field. failed leaves the
specific status and diagnostic in control. delayed means the MTA will keep
trying, while delivered, relayed, and expanded do not report a bounce
failure and cannot create a recipient suppression.
RFC continuation lines are accepted only as CRLF followed by a space or tab.
Each legal fold becomes one space before parsing. Bare LF, bare CR, and
unindented continuation lines reject structured evidence instead of being
treated as field contents.
For a typed RFC Diagnostic-Code, comments in parentheses are human-readable
context only. The classifier removes them before it reads the diagnostic type
or SMTP reply. Comment text cannot create SMTP evidence, and a foreign
diagnostic type remains opaque. Untyped vendor diagnostics keep the legacy
compatibility parser.
Any other supplied non-empty action value is invalid structured evidence. The
importer rejects that row instead of ignoring the value or applying its status
and diagnostic.
Use delivered only for a provider’s final delivery event. A successful API
request, queued message, SMTP handoff, or absence of a bounce is not delivery
proof. smartlead and webhook rows must include an immutable external_id
plus either an RFC 3339 occurred_at or RFC Last-Attempt-Date. This prevents
provider retries from changing event meaning and prevents old evidence from
becoming fresh at import time. csv and manual rows can omit these fields;
their missing timestamp uses import time only when Last-Attempt-Date is also
absent. A supplied invalid timestamp is always rejected instead of being
replaced with the import time.
A recipient reply is accepted as confirmed delivery evidence. Opens and clicks
are not: privacy proxies and security scanners can generate them without proving
recipient mailbox engagement.
Confirmed permanent recipient bounces are added to that tenant’s mailbox
suppression list only while the evidence is fresh: mailbox-not-found evidence
is reused for 90 days, disabled/inactive mailbox evidence for 14 days, and
domain/DNS failure evidence for 24 hours. Older rows remain in calibration but
increment stale_suppressions_skipped and require a fresh validation. Expiry
never marks an address valid or recommends sending. Explicit complaints and
unsubscribes are stored independently as durable contact
preferences: they return unknown plus send_recommendation=do_not_send
instead of falsely labeling the mailbox invalid. Policy, reputation, and
temporary delivery failures are not suppressed.
An unqualified DNS error or DNS failure without structured status evidence
is retryable because it does not distinguish a missing domain from a temporary
resolver outage. Only explicit Null MX, no-mail-route, no-MX, or recipient-domain
nonexistence evidence can create a domain/DNS suppression.
Reusing confirmed deliveries
A recentdelivered outcome can improve future coverage for the same tenant
without another SMTP probe. The reuse gate requires all of the following:
- the delivery occurred within the previous 30 days;
sourceiscsv,smartlead, orwebhookandexternal_idis present;- this tenant has an immutable, current-policy validation decision from before the delivery;
- the latest decision-grade outcome is still
delivered; and - no tenant hard-bounce suppression exists for the address.
validation_source=recent_delivery_evidence
and charge zero credits. Delivery evidence is never shared between tenants or
written into the global validation cache. A manual outcome is retained for
calibration but cannot create a positive validation result.
Platform recipient bounce consensus
GTM APIs can conservatively downgrade an otherwise SMTP-accepted recipient when provider-observed message outcomes show recent hard bounces from at least three independent tenants. Each tenant contributes at most one latest vote, every send must follow an immutable current-policy SMTP-accepted decision, and any confirmed reply within the 30-day evidence window vetoes the downgrade. Consensus responses retainsmtp_valid=true as raw protocol evidence, return
result=risky, validation_source=platform_recipient_bounce_consensus,
send_recommendation=do_not_send, and charge zero credits. The function is
service-role only and returns no tenant, workspace, message, or event detail.
It never labels the recipient permanently invalid.
Read the calibration report
start and end values with Z or a numeric UTC offset for a window of at
most 366 days. Date-only, zone-less, locale-style, and padded timestamps return
invalid_report_timestamp.
Repair invalid_report_timestamp, invalid_report_range, or
report_range_too_large before retrying. Retry outcome_report_failed with
bounded backoff.
cURL
report, a send_observations report, and
a gateway_shadow report.
The latter measures the latest unique recipient sent through EmailBison and
separates:
- confirmed delivery from replies/interested events;
- open signals, which may come from proxies or scanners;
- hard, soft, policy, and unknown bounces;
- sends matured for seven days without any bounce; and
- unresolved recent sends that have not yet reached the maturity window.
gateway_shadow evaluates enterprise-gateway inference separately for
Proofpoint, Mimecast, Barracuda, Cisco, Sophos, Trend Micro, Fortinet, Broadcom,
Hornetsecurity, and an other_gateway fallback. Each gateway/action pair remains
in shadow until it has at least 300 decision-grade unique-recipient outcomes,
an observed hard-bounce rate no greater than 1%, and a Wilson 95% upper bound no
greater than 1%. A passing family never promotes a different gateway family or
a different inferred action.
The response also includes evidence_readiness. Treat
evidence_readiness.market_claim_ready as the only public market-claim signal.
It becomes true only when the statistical and provider-breadth claim gates pass
and the prospective ledger has at least 300 unique sends, at least 95%
validation linkage, and at least 90% outcome resolution. The same denominator
gate is also evaluated independently in
send_observations.provider_evidence_gates; another provider’s sends cannot
satisfy the Microsoft gate.
Before promoting a Microsoft SMTP route, require
evidence_readiness.microsoft_route_outcome_ready=true. It combines the
Microsoft matched-outcome operational gate with the Microsoft-only prospective
send gate. It does not replace the separate route-bound controlled canary.
Both nested reports expose decision_version. Only predictions created by that
exact policy version enter calibration. Sends tied only to a legacy policy stay
in the prospective denominator as unmatched, so every decision-changing release
must establish fresh linkage and outcome evidence.
Claim-grade predictions are read from an append-only ledger with stable decision
IDs and timestamps. The operational history table can still be upserted during
CSV retries, but those mutations cannot rewrite or backdate accuracy evidence.
Older mutable rows are intentionally not backfilled.
Matured no-bounce rows contribute only to operational bounce-risk resolution.
They never count as confirmed delivery, reusable address evidence, or a
claim-grade positive control. A late bounce automatically replaces the inferred
no-bounce state because maturity is calculated from the current observation
ledger rather than persisted as a delivery outcome.
Both reports contain aggregate counts and rates only. Raw email addresses,
domains, and MX hosts remain inside the tenant-scoped database join and are
never returned. Outcomes use bounded provider segments: Microsoft consumer,
authoritative Microsoft 365, security gateway, Google, Yahoo, Zoho, Amazon,
Apple, Fastmail, Proton, and other.
Promotion gates include:
- one latest decision-grade label per unique address, so repeated sends to the same recipient cannot inflate sample size or statistical confidence;
- observed hard-bounce rate for
validandvalid_role_baseddecisions; - the Wilson 95% upper confidence bound;
- Wilson bounds for delivery recall and false-invalid risk;
- a minimum of 300 decision-grade outcomes per Microsoft segment;
- at least 50% send-decision coverage across decision-grade segment outcomes;
- at least 90% delivery send recall, so an overly cautious policy cannot win by
hiding deliverable mail behind
risky,unknown, orinvalid; - no more than 1% delivered-after-
invalidoutcomes; - separate operational and statistically supported sub-1% claim states;
- an overall gate plus gates for each bounded provider segment;
- provider-breadth readiness requiring at least four named provider families, each with at least 20 decision-grade outcomes; and
- delivered-after-
invalidand hard-bounce-after-send-recommended counters.
sub_one_percent_claim_ready for the stricter state that also requires the
hard-bounce and false-invalid upper bounds plus the delivery-recall lower bound
to meet their targets.
Use report.readiness.operational_rollout_ready as the fail-closed rollout
signal. It requires the overall operational gate, the combined Microsoft gate,
and provider breadth to pass. Use
report.readiness.sub_one_percent_claim_ready as the statistical claim result:
the overall and combined Microsoft confidence gates must pass, and at least
four provider families must independently be claim-grade. A large cohort from
only Microsoft cannot satisfy either breadth requirement. The strongest
first-party prospective signal is evidence_readiness.market_claim_ready,
which additionally requires representative prospective send coverage,
including a passing Microsoft-only prospective gate.
Despite its compatibility name, that field does not evaluate another
validator. Comparative market-leadership language also requires a verified
competitive benchmark v9 report for GTMAPIs and at least two named competitors,
with every loss and abstention published. It must pass its domain-diversity
input gate and publish both subject-level paired tests and equal-domain-weight
exact sign tests.