Prove that the receiving server denied the message permanently. A bounce event with the type bounce states it. A block states the type blocked, and a block never satisfies this level.

Contract identity.
FactValue
Contract idsendgrid.email.bounced
Version1.0.0
Hash1100fbbefd59997c
Completion levelbounced
PublisherBuilt and signed by Provely.
CertificationProvisional
SkillTwilio SendGrid Mail API 0.1.0
Valid for provider API versionsv3

What is the intent?

Confirm that the message bounced.

What is the subject and the action?

MemberValue
Subject typesendgrid.message
Subject identityprovely_operation_id = $action.result.provely_operation_id
Canonical effectmessaging.email_send
Provider operationPOST /v3/mail/send
Idempotencynone, retry is not safe

How does the evidence correlate with this operation?

StrategyAssuranceKeysRequired
resource_idstrongprovely_operation_id from $action.result.provely_operation_idyes
fingerprintweakemail from $input.tono

Which evidence does the contract require?

Minimum evidence level E3. An independent channel is required. Minimum channels: 1.

ChannelLevelIndependenceVerifierDescription
processed_by_recipientE3provider eventwebhookThe processed events for this recipient since the operation started, whatever custom argument they carry. A count above one shows a second message. The verifier returns {events, count, latest, earliest, types, duplicates_dropped}.
hard_bounce_eventsE3provider eventwebhookThe bounce events of this operation that state the type bounce. A hard bounce is a permanent denial. The match drops a block, which is a temporary denial. The verifier returns {events, count, latest, earliest, types, duplicates_dropped}.
processed_eventsE3provider eventwebhookThe processed events that carry the custom argument of this operation. Twilio SendGrid accepted the message and can deliver it. The verifier returns {events, count, latest, earliest, types, duplicates_dropped}.
delivered_eventsE3provider eventwebhookThe delivered events that carry the custom argument of this operation. The receiving server accepted the message. The verifier returns {events, count, latest, earliest, types, duplicates_dropped}.
dropped_eventsE3provider eventwebhookThe dropped events of this operation. Twilio SendGrid dropped the message, and it never reached a receiving server. The verifier returns {events, count, latest, earliest, types, duplicates_dropped}.

Which conditions must all hold for VERIFIED?

ConditionMeaningPathOperatorExpectedEvidence
hard_bounce_presentAt least one bounce event of this operation states the type bounce. The denial is permanent.$observed.hard_bounce_events.countgte1hard_bounce_events
hard_bounce_present_in_windowThe provider clock of the earliest matched event is after the start of the operation. An older event belongs to another send.$observed.hard_bounce_events.earliest.provider_timestamptime_after$operation.created_athard_bounce_events

Which conditions give CONTRADICTED?

ConditionClassReasonPathOperatorExpected
wrong_recipientwrong subjectThe message went to a different recipient than the intent named.$observed.processed_events.latest.payload.emailne$input.to
message_predates_operationpre existing stateThe earliest event of this message is older than the operation. It proves nothing.$observed.processed_events.earliest.provider_timestamptime_before$operation.created_at
duplicate_message_presentduplicate side effectTwilio SendGrid processed more than one message for this recipient since the operation started. Do not retry.$observed.processed_by_recipient.countgt1

Which observed states map to a verdict before completion?

RuleMatchVerdictReason
message_delivered$observed.delivered_events.count gte 1CONTRADICTEDThe receiving server accepted the message. It did not bounce.
message_dropped$observed.dropped_events.count gte 1FAILEDTwilio SendGrid dropped the message. It never reached a receiving server.

How long does the runtime observe?

Timing memberValue
Initial delay2000 ms
Poll interval10000 ms
Backoffexponential factor 2, max 300000 ms
Maximum attempts60
Timeout259200000 ms
Stale read window30000 ms
On timeoutUNVERIFIABLE (evidence_unavailable_before_timeout), escalated to a person

Where do these rules come from?

  • sendgrid.openapi#/paths/~1v3~1mail~1send/post: sendgrid.openapi, retrieved 2026-09-08
  • sendgrid.docs.events#event-webhook/the-bounce-event/p1: sendgrid.docs.events, retrieved 2026-09-08
  • sendgrid.events#/events/bounce: sendgrid.events, retrieved 2026-09-08
  • sendgrid.docs.events#event-webhook/custom-arguments/p1: sendgrid.docs.events, retrieved 2026-09-08
  • sendgrid.docs.events#event-webhook/the-event-time/p1: sendgrid.docs.events, retrieved 2026-09-08
  • sendgrid.docs.events#event-webhook/the-properties-of-a-delivery-event/p1: sendgrid.docs.events, retrieved 2026-09-08

Can sendgrid.email.bounced return VERIFIED from the action response alone?

No. The minimum evidence level is E3. The action response is E1. The completion conditions read hard_bounce_events.

What happens after the timeout?

The verdict is UNVERIFIABLE with the reason evidence_unavailable_before_timeout. The operation goes to a person for review.