| Internet-Draft | Event Delivery Semantics | June 2026 |
| Panke | Expires 30 December 2026 | [Page] |
Event- and webhook-based integrations are a common application-layer mechanism for interoperability across Internet services, yet they lack a shared delivery semantics contract. Existing implementations vary widely in retry behavior, acknowledgment signaling, failure classification, idempotency identifiers, and replay handling, resulting in fragile integrations and ambiguous operational expectations.¶
This document defines a minimal, application-layer delivery semantics profile for event and webhook delivery over existing transports, and specifies a concrete binding for the Hypertext Transfer Protocol (HTTP). The profile constrains only sender-observable behavior and signaling; it does not impose receiver-side storage or processing requirements and does not redefine existing transport protocols.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 30 December 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Event- and webhook-based delivery is widely used to notify external systems of state changes or occurrences across administrative boundaries. These integrations are typically implemented over HTTP and are expected to operate in the presence of partial failure, independent failure domains, and variable network conditions.¶
Despite their ubiquity, there is no common, interoperable delivery semantics model that defines how delivery attempts, retries, acknowledgments, or failures are signaled and interpreted between independently operated producers and consumers. In practice, every producer publishes its own retry policy, its own acknowledgment convention, its own idempotency header, and its own classification of failure; every consumer must adapt to those conventions per producer. The result is fragile integrations, repeated rediscovery of the same edge cases, and operational practices that do not transfer between vendors.¶
This document addresses that gap by defining a minimal, application-layer semantics profile focused on sender-observable behavior, and by specifying a concrete binding of that profile to HTTP (see Section 9). The profile is intentionally narrow: it does not attempt to define new transport primitives, new cryptographic mechanisms, or new payload formats. Its goal is to give independently developed producers and consumers a shared, interoperable vocabulary for the few signals that determine whether a delivery succeeded, may be retried, or must be abandoned.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
The following terms are used throughout this document.¶
Event- and webhook-based delivery is a widely deployed application-layer integration pattern used to notify external systems of state changes or occurrences. Such delivery is commonly implemented over existing transports, most frequently HTTP, and is typically expected to operate in the presence of partial failure, network interruption, and independent administrative control of endpoints.¶
Despite widespread deployment, there is no common, interoperable delivery semantics contract governing how Event Producers, Consumers, and Intermediaries signal Delivery Attempts, retries, acknowledgment, or failure. As a result, independently developed implementations rely on implicit assumptions, vendor-specific conventions, or informal documentation, leading to fragile integrations and inconsistent operational behavior.¶
The absence of a shared delivery semantics model results in recurring issues, including:¶
These issues arise from missing application-layer semantics rather than deficiencies in underlying transport protocols.¶
Transport protocols such as HTTP [RFC9110] provide generic delivery and error signaling mechanisms but intentionally do not define application-specific semantics such as retry interpretation, acknowledgment meaning, or deduplication scope. Correct use of transport semantics alone is therefore insufficient to ensure interoperable event delivery behavior.¶
This document does not attempt to:¶
All requirements defined in this document apply to sender-observable behavior and signaling.¶
The goals of this specification are to:¶
This specification considers three primary roles: Event Producer, Event Consumer, and an optional Intermediary. The delivery semantics defined in this document apply to interactions between these roles at the application layer.¶
+----------------+ Delivery Attempt +----------------+
| | ---------------------> | |
| Event Producer | | Event Consumer |
| | <--------------------- | |
+----------------+ Sender-Observed Outcome+----------------+
(or)
+----------+ Delivery +--------------+ Delivery +----------+
| Producer | ---------> | Intermediary | ---------> | Consumer |
+----------+ Outcome +--------------+ Outcome +----------+
<--------- <---------
An Intermediary takes the Producer role with respect to its downstream Consumer, and the Consumer role with respect to its upstream Producer. The semantics defined in this document therefore apply recursively at each hop.¶
This specification defines a sender-observable delivery semantics model for event and webhook delivery. The model applies to each Delivery Attempt independently and does not infer receiver-side processing behavior beyond what is explicitly signaled.¶
A Delivery Attempt represents a single, discrete effort by an Event Producer or Intermediary to deliver an Event to a Consumer endpoint. Each Delivery Attempt MUST be treated as best-effort, MUST NOT imply receipt, durability, or processing, and MAY be retried according to sender policy when Sender-Observed Outcomes indicate a non-terminal condition.¶
This specification defines three Sender-Observed Outcomes for a Delivery Attempt:¶
Senders MUST base retry behavior solely on Sender-Observed Outcomes and MUST NOT infer receiver-side state beyond what is explicitly signaled.¶
Retry behavior is sender-driven and policy-dependent. This specification standardizes only retry signaling, not retry guarantees. Consumers MAY provide retry guidance (for example, by indicating a minimum delay before the next attempt), and senders MAY honor such guidance. When a Consumer provides explicit retry guidance and the sender intends to retry, the sender SHOULD not retry sooner than indicated.¶
Senders SHOULD apply backoff between retries to avoid amplifying load on Consumers experiencing Transient Failure conditions. An algorithm for the HTTP binding is specified in Section 9.6; interactions with denial-of-service mitigation are discussed in Section 11.8.¶
This document defines bindings for HTTP only (Section 9). The model in this section is intentionally transport-independent so that bindings to other transports (for example, AMQP, MQTT, or queue-based protocols) may be specified separately without revisiting the abstract semantics. No such bindings are defined here.¶
Idempotency and deduplication are addressed through explicit signaling mechanisms only. This specification does not require or assume receiver-side deduplication behavior.¶
An Idempotency Identifier is a producer-supplied identifier intended to correlate multiple Delivery Attempts representing the same logical Event. When present, the identifier MUST remain stable across retries of the same logical Event and MUST be scoped to the producer-consumer context.¶
Producers SHOULD generate Idempotency Identifiers with sufficient entropy to make collisions across distinct logical Events negligible within the relevant deduplication window.¶
Consumers MAY choose to perform deduplication based on the Idempotency Identifier and local policy. Senders MUST tolerate duplicate delivery in all cases. Deduplication remains an optimization, not a correctness requirement.¶
A Consumer that performs deduplication SHOULD maintain Idempotency Identifier state for a finite Deduplication Window. When no value is communicated out of band or by prior agreement, a minimum Deduplication Window of 24 hours is RECOMMENDED.¶
A Producer MUST NOT reuse an Idempotency Identifier for a distinct logical Event within the Consumer's Deduplication Window. When the Window is not known to the Producer, the Producer SHOULD treat it as at least the RECOMMENDED minimum above and SHOULD generate fresh identifiers per distinct logical Event regardless.¶
Failure classification in this specification is minimal and sender-centric. Two failure classes are defined:¶
Failure classifications are used solely to inform sender behavior such as retry decisions, alternate delivery paths, or operator intervention. They carry no semantic guarantees about Consumer-side processing.¶
This section defines a binding of the delivery semantics model (Section 6) to HTTP [RFC9110]. Producers and Consumers exchanging Events over HTTP SHOULD implement this binding to enable interoperability. Other transport bindings are out of scope for this document.¶
A Delivery Attempt using the HTTP binding SHOULD use the POST method. PUT MAY be used when Producer and Consumer have prior agreement that the Event payload represents the replacement state of the resource identified by the request URI. Safe methods (GET, HEAD, OPTIONS) are NOT RECOMMENDED for Delivery Attempts because they imply no state change and are subject to intermediary caching behavior that may suppress retries.¶
The Content-Type of the request MUST accurately identify the Event payload media type. This document does not constrain payload media type; see Section 10 for a discussion of common choices.¶
When a Consumer returns an HTTP response to a Delivery Attempt, the sender derives the Sender-Observed Outcome from the response. The mappings in this section represent the default behavior that applies in the absence of out-of-band agreement.¶
Producers and Consumers MAY agree on alternative interpretations for individual status codes, provided that any such agreement (a) is documented in writing, (b) is discoverable by operators of both parties, and (c) does not weaken the security properties required by Section 11. Absent such an agreement, the defaults below apply.¶
A 2xx (Successful) status code SHOULD be treated as Accepted. The following finer-grained guidance applies:¶
The presence or absence of a response body MUST NOT alter the Sender-Observed Outcome derived from a 2xx status code, except as stated above for 207.¶
The following status codes SHOULD be treated as Transient Failure:¶
| Code | Name | Notes |
|---|---|---|
| 408 | Request Timeout | Ambiguous: the request may or may not have been processed. Safe retry depends on the Idempotency-Key field, which is required by Section 9.4. |
| 421 | Misdirected Request | Indicates routing error at the Consumer; retry MAY succeed against a re-resolved endpoint. |
| 425 | Too Early | Retry after the early-data condition clears. |
| 429 | Too Many Requests | Honor Retry-After (Section 9.5) if present. |
| 500 | Internal Server Error | Generic server error; retry with backoff. |
| 502 | Bad Gateway | Upstream of Consumer failed; retry. |
| 503 | Service Unavailable | Honor Retry-After if present. |
| 504 | Gateway Timeout | Same ambiguity as 408; safe retry depends on the Idempotency-Key field required by Section 9.4. |
| 511 | Network Authentication Required | Typically injected by an on-path captive portal; resolves out of band. |
Other 5xx status codes not listed above SHOULD be treated as Transient Failure unless prior agreement specifies otherwise.¶
The following status codes SHOULD be treated as Terminal Failure:¶
| Code | Name | Notes |
|---|---|---|
| 400 | Bad Request | Malformed request; retry will produce the same outcome. |
| 401 | Unauthorized | Producers operating with rotating credentials MAY attempt one credential refresh and a single subsequent retry before classifying as Terminal. |
| 403 | Forbidden | Authorization decision; retry not useful absent policy change. |
| 404 | Not Found | Endpoint missing; reconfiguration required. |
| 405 | Method Not Allowed | Producer-Consumer agreement mismatch; see Section 9.1. |
| 410 | Gone | Endpoint permanently removed; Producer SHOULD mark the subscription inactive. |
| 413 | Content Too Large | Event payload exceeds Consumer limit; retry without payload reduction will fail. |
| 414 | URI Too Long | Typically a Producer configuration error. |
| 415 | Unsupported Media Type | Renegotiate media type out of band. |
| 422 | Unprocessable Content | Schema or semantic validation failure. |
| 451 | Unavailable for Legal Reasons | Producer SHOULD record and escalate to operator review. |
Other 4xx status codes not listed above SHOULD be treated as Terminal Failure unless prior agreement specifies otherwise.¶
When a Consumer signals deprecation via the Sunset header field [RFC8594], Producers SHOULD treat continued Delivery Attempts past the indicated Sunset time as candidates for Terminal classification on the next non-Accepted outcome.¶
1xx (Informational) status codes are handled per [RFC9110] and do not in themselves constitute a Sender-Observed Outcome.¶
3xx (Redirection) status codes are handled per [RFC9110]. In particular, 308 (Permanent Redirect) SHOULD cause the Producer to update its stored endpoint URI for the subscription before issuing the next Delivery Attempt. 307 (Temporary Redirect) MUST NOT cause the Producer to update stored configuration.¶
Consumers MAY return problem details in the response body using the format defined in [RFC9457] to aid operator diagnosis. The Sender-Observed Outcome MUST still be derived from the status code; problem details are advisory.¶
A Delivery Attempt that fails before a complete HTTP response status line is received (for example, due to connection refusal, connection reset, TLS handshake failure, request timeout, or name-resolution failure) MUST be treated as a transport-level failure as defined in Section 8 and, by default, as Transient Failure.¶
A Delivery Attempt for which the request was transmitted but the response was not received in full MUST be treated as Transient Failure with unknown outcome. Safe retry in this case depends on the Idempotency-Key header field, which is required by Section 9.4 for all Delivery Attempts in the HTTP binding.¶
In the HTTP binding defined by this document, every Delivery Attempt MUST include an Idempotency-Key header field carrying the Idempotency Identifier defined in Section 7.1. The header field's syntax and processing rules MUST be those defined by [I-D.ietf-httpapi-idempotency-key].¶
The value of the Idempotency-Key header field MUST be identical across all Delivery Attempts for the same logical Event from the same Producer-Consumer Context (defined below). The value MUST be a string of sufficient entropy to make collisions negligible across the Deduplication Window (Section 7.2); a UUID [RFC9562] or a base64url-encoded random value of at least 128 bits satisfies this requirement.¶
For the purposes of this document, a Producer-Consumer Context is the tuple (Producer identity, Consumer endpoint URI), where:¶
Two Delivery Attempts share an Idempotency-Key scope if and only if they share a Producer-Consumer Context.¶
When a Consumer returns a response classified as Transient Failure, the Consumer MAY include a Retry-After header field as defined in Section 10.2.3 of [RFC9110] to indicate a minimum delay before the next Delivery Attempt.¶
When a Retry-After header field is present in a response classified as Transient Failure and the sender intends to retry, the sender SHOULD NOT initiate the next Delivery Attempt for the same logical Event sooner than indicated by the Retry-After value. Senders MAY apply additional backoff beyond the Retry-After value at their discretion.¶
A Retry-After value of 0 indicates that the Consumer has no preferred delay; the Producer's local retry policy applies (see Section 9.6).¶
Producers retrying after Transient Failure outcomes SHOULD apply an algorithm with the following properties:¶
A widely deployed default that satisfies these requirements is full-jitter exponential backoff. For retry attempt n (with n = 0 denoting the first retry), the sender selects a delay uniformly at random from the interval [0, min(cap, base * 2^n)], where base is a baseline delay (a value of 1 second is commonly used) and cap is an upper bound on a single delay (commonly between 60 and 600 seconds). Producers MAY use other algorithms that satisfy the properties above.¶
When a Retry-After value is supplied (Section 9.5) and exceeds the delay selected by the algorithm above, the Retry-After value MUST be honored as the lower bound for the next Delivery Attempt.¶
When an Intermediary (Section 5) relays an Event over the HTTP binding:¶
An Intermediary that buffers Events MAY return Accepted upstream prior to successful downstream delivery (store-and-forward operation) only when both of the following conditions hold:¶
Absent both conditions, an Intermediary MUST NOT return Accepted upstream before the downstream Delivery Attempt has itself yielded an Accepted Sender-Observed Outcome.¶
The examples in this section are illustrative and non-normative. Line breaks within header fields are inserted for readability only. All hostnames use example.com per [RFC2606].¶
For clarity, the Content-Length header field and other framing headers are omitted from the examples; the message-body length is determined per [RFC9110].¶
A Producer delivers an Event; the Consumer acknowledges with 200 OK.¶
Sender-Observed Outcome: Accepted. No retry is performed.¶
The Consumer is under load and asks the Producer to retry after 30 seconds.¶
Sender-Observed Outcome: Transient Failure. The Producer waits at least 30 seconds, then retries the same Delivery Attempt with the same Idempotency-Key.¶
The retry is Accepted. Because the Idempotency-Key is preserved, a Consumer that performs deduplication (see Section 7.2) processes the Event exactly once across the two Delivery Attempts.¶
The Consumer rejects the Event as semantically invalid.¶
Sender-Observed Outcome: Terminal Failure. The Producer MUST NOT retry the Delivery Attempt; the problem details are recorded for operator diagnosis.¶
The Producer establishes a TCP connection to consumer.example.com on port 443. TLS negotiation completes. The Producer transmits the request in full and waits for a response. After 60 seconds with no response bytes received, the Producer's local timeout fires and the connection is closed.¶
Sender-Observed Outcome: Transient Failure, with unknown receiver state per Section 9.3. The Producer retries using the same Idempotency-Key to permit Consumer-side deduplication. The next retry delay is governed by Section 9.6.¶
The Delivery Attempt semantics defined in this section are version-independent at the application layer. The following version-specific behaviors apply:¶
Event delivery mechanisms are commonly used to convey security-sensitive notifications across administrative boundaries. This section profiles existing security mechanisms and provides guidance on their application to the delivery semantics defined in this document. No new cryptographic mechanisms are defined. The guidance below follows the structure recommended by [RFC3552].¶
The principal threats to event and webhook delivery considered by this document are:¶
Producers and Consumers SHOULD use TLS [RFC8446] for all Delivery Attempts. Producers SHOULD validate Consumer endpoint certificates and SHOULD NOT deliver Events to endpoints that fail certificate validation.¶
In the HTTP binding (Section 9), Consumers MUST authenticate the Producer of each Delivery Attempt. This requirement supports the Producer-Consumer Context definition in Section 9.4 and is the basis of the replay-mitigation requirement in Section 11.5.¶
Suitable authentication mechanisms include, but are not limited to, HTTP Message Signatures [RFC9421], mutual TLS, and bearer tokens carried in the Authorization header field as defined in [RFC9110]. Selection of a specific mechanism is a deployment decision and is out of scope for this document.¶
Whatever mechanism is chosen, Consumers MUST NOT treat a Delivery Attempt as Accepted on the basis of its payload alone when authentication has not been verified.¶
Producers SHOULD protect the integrity of Event payloads and security-relevant metadata in transit. Use of TLS (Section 11.2) provides integrity for the transport channel. Use of HTTP Message Signatures [RFC9421] additionally provides integrity over selected message components that survives intermediary processing.¶
Consumers that act on Events MUST mitigate replay attacks. At least one of the following mechanisms MUST be in effect for any Consumer for which replay would have security consequences:¶
The Idempotency Identifier alone is NOT RECOMMENDED as a sole replay countermeasure outside the bounded Deduplication Window, because Producers may legitimately reuse identifiers beyond that window per local policy. Consumers that do not perform deduplication MUST implement mechanism (2) above to satisfy the requirement in this section.¶
When Delivery Attempts traverse TLS 1.3 [RFC8446], neither mechanism above mitigates replay of TLS 1.3 0-RTT (early) data, which is replayable at the transport layer. Producers MUST NOT transmit Delivery Attempts as 0-RTT data except under the conditions stated in Section 9.9. When Delivery Attempts are transmitted as 0-RTT data under those conditions, Consumers MUST rely on mechanism (2) above for replay protection; the Deduplication Window alone is insufficient because a 0-RTT replay may deliver an Event with an Idempotency Identifier that the Consumer has not yet seen.¶
Event payloads may contain confidential data. Producers and Consumers SHOULD use TLS to provide confidentiality on the transport channel and SHOULD avoid logging full Event payloads at intermediary points where such logs are not subject to equivalent protection.¶
Producers SHOULD deliver Events only to Consumer endpoints that have been explicitly registered or otherwise authorized to receive them. Producers that accept user-supplied delivery URLs (for example, customer-configurable webhook endpoints) SHOULD validate those URLs and SHOULD NOT permit delivery to addresses inside their own trust boundary unless explicitly intended, to mitigate server-side request forgery.¶
Retry behavior interacts directly with availability. The bounding and jitter requirements in Section 9.6 are motivated in part by the need to prevent senders from amplifying load against a Consumer recovering from a Transient Failure condition. Senders MUST NOT retry without bound; the finite-retry requirement in Section 9.6 is normative for that reason.¶
When a Consumer returns a Retry-After value (Section 9.5), honoring that value contributes directly to mitigating retry amplification.¶
Producers SHOULD additionally treat repeated Terminal Failure outcomes from a single Consumer endpoint as a signal to disable further Delivery Attempts to that endpoint until operator intervention, so as not to amplify load against endpoints that have been removed, misconfigured, or unsubscribed.¶
This document makes no request of IANA.¶
The HTTP header field name "Idempotency-Key" referenced in Section 9.4 is registered by [I-D.ietf-httpapi-idempotency-key]; this document defers to that registration.¶
This section will be removed prior to publication.¶
Structural and editorial changes:¶
Model and normative content:¶
Security:¶
References added:¶
Internal-consistency and second-pass review changes:¶
This appendix is non-normative. It documents the empirical basis for the default values recommended in Section 7.2 and Section 9.6 and for the status-code mappings in Section 9.2. Values reported here are taken from publicly available vendor documentation as of the date of this revision and are intended to illustrate the design space rather than to assert the current state of any individual system. Implementers SHOULD consult current vendor documentation for the specific systems they integrate with.¶
The following event and webhook platforms publish delivery-semantics documentation and were considered in framing this document:¶
Surveyed systems report total retry windows ranging from approximately ten minutes (for low-tolerance notification systems) to several days (for billing- and account-state systems), with the central tendency falling between four and seventy-two hours. Retry counts within those windows range from a single-digit fixed-count strategy (e.g., a small number of attempts at fixed offsets) to exponential strategies extending to one or two hundred attempts.¶
The dominant backoff shape is exponential with random jitter. Base delays in the range of a few seconds and per-attempt caps in the range of several minutes to ten minutes are common. The default algorithm and parameters in Section 9.6 (base of 1 second, cap between 60 and 600 seconds) fall within this central range.¶
Surveyed systems are uniform in providing a producer-supplied identifier intended to support consumer-side deduplication, though they vary in naming (Idempotency-Key, delivery GUID, event id, and others) and in whether the identifier is carried in an HTTP header field or in the payload body.¶
Reported deduplication windows, where stated, range from approximately one hour to seven days. Twenty-four hours is the most commonly reported value among systems that publish a specific window. The RECOMMENDED minimum of 24 hours in Section 7.2 reflects this observation.¶
Surveyed systems are broadly consistent in treating 2xx responses as Accepted, 5xx responses as retriable, and 4xx responses as non-retriable, with the exceptions and special cases captured in Section 9.2. Specific divergences observed include:¶
The default values and mappings recommended in this document are positioned to interoperate with the central range of observed practice rather than with any single system's specific behavior. Where this document adopts a tighter or stronger position than current practice (for example, requiring authentication and Idempotency-Key in the HTTP binding), that position is motivated by the security and interoperability goals stated in Section 4.¶
The author thanks early reviewers of -00 for their feedback and discussion. Specific acknowledgements will be added in future revisions as the document attracts community review.¶