From 760a12e0f4006e3e526ad88522d37ad556ffe44c Mon Sep 17 00:00:00 2001
From: ChrisBasis <116389270+ChrisBasis@users.noreply.github.com>
Date: Fri, 10 Jul 2026 12:05:15 -0400
Subject: [PATCH 1/3] Update deal1.1.md
---
deal1.1.md | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/deal1.1.md b/deal1.1.md
index 3f08d41..00a814f 100644
--- a/deal1.1.md
+++ b/deal1.1.md
@@ -22,6 +22,7 @@
- [Object: DealRevision](#object-dealrevision)
- [Object: DealActor](#object-dealactor)
- [Object: DealResponse](#object-dealresponse)
+ - [Object: DealSignal](#object-dealsignal)
- [Object: SeatStatus](#object-seatstatus)
- [Implementation Guidance](#implementation-guidance) *(see [implementation-guidance.md](implementation-guidance.md))*
@@ -283,6 +284,26 @@ A DealResponse communicates a party's acceptance or rejection of a proposed revi
| `comment` | string | Optional human-readable note from the responding party explaining the acceptance or rejection. |
| `ext` | object | Placeholder for response-specific extensions. |
+
+## Object: DealSignal
+
+A DealSignal communicates a lightweight, non-obligating intent from one party to the other. It does not modify deal terms and does not, by itself, change `sellerstatus` or `buyerstatus`. Its initial defined use is a buyer-initiated request to resume a paused deal.
+
+Unlike a DealRevision (which proposes new terms) or a DealResponse (which accepts or rejects a revision), a DealSignal carries no term fields and no `negotiationstatus` — it expresses an intent that the receiving party may act on at its discretion, or not at all. A DealSignal is available only under the bidirectional model, since it requires a party to push to the counterparty's endpoint.
+
+| Attribute | Type | Description |
+|-----------|------|-------------|
+| `dealid` | string; **required** | The canonical deal identifier (`deal.id`) this signal pertains to. |
+| `signalid` | string; **required** | A UUID assigned by the initiating party that uniquely identifies this signal. Serves as the idempotency key for the signal, analogous to `revisionid` for revisions. |
+| `signaltype` | int; **required** | The intent being expressed:
`0` = RESUME_REQUEST — the signaling party requests that the counterparty resume a paused or non-spending deal.
Additional signal types may be defined in future versions. |
+| `signaledby` | DealActor object; **required** | The party issuing this signal. For a RESUME_REQUEST this is expected to be the buyer (`role=1`). See [Object: DealActor](#object-dealactor). |
+| `signaldate` | string; **required** | UTC timestamp in ISO-8601 of when this signal was issued. |
+| `liverevisionid` | string | The `revisionid` of the `liverevision` the signaling party intends to transact against. Allows the receiver to detect a request to resume against terms it no longer intends to honor, in which case it should propose a revision rather than resume. |
+| `comment` | string | Optional human-readable note from the signaling party. |
+| `ext` | object | Placeholder for signal-specific extensions. |
+
+A DealSignal is distinguished from the other push message types by a top-level `signaltype` and the absence of term fields, `revisionid`, and `negotiationstatus`.
+
## Object: SeatStatus
From 35fadcb53e06641cdf91a77ce9462fd819e29a25 Mon Sep 17 00:00:00 2001
From: ChrisBasis <116389270+ChrisBasis@users.noreply.github.com>
Date: Fri, 10 Jul 2026 12:06:36 -0400
Subject: [PATCH 2/3] Update implementation-guidance.md
---
implementation-guidance.md | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
diff --git a/implementation-guidance.md b/implementation-guidance.md
index 5fb4a65..f9ce8df 100644
--- a/implementation-guidance.md
+++ b/implementation-guidance.md
@@ -25,6 +25,7 @@ This document provides implementation guidance for the Deal Sync API v1.1 specif
- [Negotiation and Deal Lifecycle](#negotiation-and-deal-lifecycle)
- [full_history Query Parameter](#full-history-query-parameter)
- [Example Workflow](#example-workflow)
+- [Buyer-Initiated Reactivation](#buyer-initiated-reactivation)
- [Price and Floor Guidance](#price-and-floor-guidance)
- [Origin, Curator, and Seller](#origin-curator-and-seller)
- [Example 1](#example-1)
@@ -58,12 +59,13 @@ Supply Chain validation should always be done using Object: Supply Chain from Op
**Bidirectional model (optional):** When both parties agree to support bidirectionality, either party may initiate a deal or propose a revision by pushing (POST) to the counterparty's endpoint, and both parties implement both POST and GET. In this model, the buyer can also push DealResponse objects directly to the seller's endpoint for faster acceptance/rejection notification, and may initiate deals or propose revisions of their own. The conflict resolution rules described in [Revision Semantics](#revision-semantics) (simultaneous proposals, stale acceptance) apply only when both parties are actively pushing.
-**Push endpoint message types:** The push endpoint accepts two message types via HTTP POST:
+**Push endpoint message types:** The push endpoint accepts three message types via HTTP POST:
- **Deal object** — used to create a new deal or propose a revision. The Deal object contains `currentrevision` with the proposed changes.
- **DealResponse object** — used to accept or reject an existing proposed revision. The DealResponse references the target revision by `revisionid` and communicates the verdict via `negotiationstatus`.
+- **DealSignal object** — used to convey a lightweight, non-obligating intent that changes neither deal terms nor lifecycle status, such as a buyer request to resume a paused deal. A DealSignal has a top-level `signaltype` and `signalid` and no term fields, `revisionid`, or `negotiationstatus`.
-Implementations should distinguish between the two based on the payload structure: a DealResponse has a top-level `revisionid` and `negotiationstatus` with no deal term fields; a Deal push has the full Deal object structure. A counter-revision (proposing alternative terms in response to a proposal) is communicated as a new Deal push, not as a DealResponse.
+Implementations should distinguish among the three based on the payload structure: a DealResponse has a top-level `revisionid` and `negotiationstatus` with no deal term fields; a DealSignal has a top-level `signaltype` and `signalid` with no `revisionid`, `negotiationstatus`, or deal term fields; a Deal push has the full Deal object structure. A counter-revision (proposing alternative terms in response to a proposal) is communicated as a new Deal push, not as a DealResponse.
To ensure data integrity, implementers are encouraged to implement periodic polling as a fallback mechanism to handle any missed push notifications.
@@ -91,6 +93,8 @@ Network failures, timeouts, and retries are inevitable in any distributed system
| DealResponse for superseded revision | 200 | Discard response; return current deal state (sender discovers new `currentrevision`) |
| Status update representing forward progress | 200 | Apply status change; return current deal state |
| Status update representing same or prior state | 200 | No-op; return current deal state |
+| RESUME_REQUEST received (new `signalid`) | 200 | Record signal; return current deal state. Seller may act via PAUSED → LIVE at its discretion |
+| Duplicate RESUME_REQUEST (same `signalid`, already processed) | 200 | No-op; return current deal state |
All 200 responses should include the current Deal object in the response body. This ensures the sender always receives the most up-to-date view of the deal, regardless of whether their push caused a state change.
@@ -112,6 +116,7 @@ When two parties independently act on a deal at the same time — each operating
| Push received while deal is in terminal state | 409 | Current Deal object (showing terminal status) | Acknowledge terminal state; stop further updates |
| DealResponse references superseded `revisionid` | 409 | Current Deal object (showing new `currentrevision`) | Evaluate new `currentrevision` and respond to it |
| Simultaneous revision proposals (buyer's revision loses) | 200 | Current Deal object (showing seller's revision as `currentrevision`, buyer's as SUPERSEDED) | Evaluate seller's `currentrevision` |
+| RESUME_REQUEST received while deal is in terminal state | 409 | Current Deal object (showing terminal status) | Acknowledge terminal state; create a new deal to transact |
**Consistency through polling.** Even with these deterministic rules, implementations should not rely solely on push delivery for correctness. Periodic polling (GET) serves as the consistency backstop: if a push is lost, delayed, or its response is not received, both parties will converge on the next poll cycle. Implementations should poll at a reasonable interval (suggested: at least once every 15 minutes for active deals) to bound the window of inconsistency.
@@ -333,6 +338,23 @@ The following illustrates a typical revision lifecycle. Revision labels (Revisio
7. **Seller accepts.** Seller pushes a DealResponse with `revisionid=` and `negotiationstatus=1` (ACCEPTED). `negotiationstatus` on Revision 4 transitions to `1` (ACCEPTED). `liverevision` is updated to Revision 4. The deal's operative terms are now those of Revision 4 relative to Revision 1.
+
+## Buyer-Initiated Reactivation
+
+The lifecycle model gives the sell side exclusive control over resumption: only `sellerstatus` transitions `PAUSED (4) → LIVE (2)` and `LIVE_NOT_SPENDING (3) → LIVE (2)` — both seller-initiated — restore auction eligibility, because the seller controls bid request construction. A buyer with demand ready to spend on a dormant deal has no in-band way to request resumption; `buyerstatus` reflects only the buyer's own operational view and does not drive seller delivery.
+
+The DealSignal object with `signaltype=0` (RESUME_REQUEST) standardizes this request. It is intentionally minimal.
+
+**Non-obligating.** A RESUME_REQUEST does not change any status field and does not compel the seller to act — it is a request, not a command. The seller resumes, if it chooses, by performing the already-defined `PAUSED → LIVE` (or `LIVE_NOT_SPENDING → LIVE`) transition. No dedicated acknowledgment message is defined; the buyer observes the outcome through the seller's next status push or the buyer's next poll.
+
+**Terminal-state aware.** A RESUME_REQUEST received while the receiver's record shows a terminal `sellerstatus` (COMPLETED, EXPIRED, CANCELED) is rejected under the existing terminal-dominance rule with an HTTP 409 and the current Deal object. This enforces the paused-versus-terminated distinction without a new rule — paused deals may be signaled for resumption, terminal deals may not, and the sender is directed to create a new deal.
+
+**Terms-aware.** A resume request should carry `liverevisionid` naming the terms the buyer intends to transact against. If the seller wishes to resume only under different terms, it responds by proposing a revision through the normal revision workflow rather than transitioning to LIVE. This prevents a silent economics mismatch on resumption.
+
+**Idempotent.** `signalid` is the idempotency key. A DealSignal whose `signalid` has already been processed is a no-op returning an HTTP 200 with the current deal state. Distinct `signalid` values are distinct requests; sellers may de-duplicate or rate-limit repeated resume requests on the same deal at their discretion.
+
+A DealSignal is available only when both parties support the bidirectional model. Under the seller-push-only baseline the buyer cannot push, so buyer readiness remains discoverable only when the seller polls the buyer's endpoint.
+
## Price and Floor Guidance
From 64eac387ac2542f0dd05326cc2dd6b97f5c1b366 Mon Sep 17 00:00:00 2001
From: ChrisBasis <116389270+ChrisBasis@users.noreply.github.com>
Date: Tue, 14 Jul 2026 10:45:42 -0400
Subject: [PATCH 3/3] Update examples.md
---
examples.md | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 113 insertions(+)
diff --git a/examples.md b/examples.md
index 03493e4..2f1a37c 100644
--- a/examples.md
+++ b/examples.md
@@ -19,6 +19,10 @@
- [Step 4: Buyer Accepts the Revision](#step-4-buyer-accepts-the-revision-1)
- [Step 5: Seller Pauses the Deal](#step-5-seller-pauses-the-deal)
- [Step 6: Buyer Cancels the Deal](#step-6-buyer-cancels-the-deal)
+- [Scenario 4: Buyer-Initiated Resume of a Paused CTV Deal (DealSignal)](#scenario-4-buyer-initiated-resume-of-a-paused-ctv-deal-dealsignal)
+ - [Step 1: Seller Pauses the Live Deal](#step-1-seller-pauses-the-live-deal)
+ - [Step 2: Buyer Sends a RESUME_REQUEST Signal](#step-2-buyer-sends-a-resume_request-signal)
+ - [Step 3: Seller Resumes via the Existing PAUSED to LIVE Transition](#step-3-seller-resumes-via-the-existing-paused-to-live-transition)
---
@@ -1140,3 +1144,112 @@ Content-Type: application/json
```
The seller receives this push, validates the terminal state, and transitions `sellerstatus` from `4` (PAUSED) to `7` (CANCELED). The deal is now closed on both sides.
+
+
+---
+
+
+## Scenario 4: Buyer-Initiated Resume of a Paused CTV Deal (DealSignal)
+
+A seller (Harbor Retail Media, `harbor-rmn.com`) and a buyer (`buyerco.com`) have a live, accepted CTV deal (`deal-ctv-retail-q4-114`) covering shoppable connected TV inventory. The accepted terms are captured in `liverevision` `7b2e1a9c-4d6f-4a13-8c0e-2f9b5d1a7e60`. Both parties support the **bidirectional model**.
+
+The seller pauses the deal to investigate a measurement discrepancy. A week later the buyer has fresh budget ready to spend against the same terms and wants the deal turned back on. Because only the seller can restore auction eligibility (`sellerstatus` `PAUSED → LIVE`), and `buyerstatus` does not drive seller delivery, the buyer uses a `DealSignal` with `signaltype=0` (RESUME_REQUEST) to make the request in-band.
+
+---
+
+### Step 1: Seller Pauses the Live Deal
+
+The seller pauses the deal by pushing a status-only Deal update to the buyer's push endpoint with `sellerstatus=4` (PAUSED). No revision is involved; the live terms are unchanged. Because a seller pause is the effective deal-dark signal, the deal is no longer eligible for auction regardless of the buyer's status.
+
+**Request**
+```
+POST https://dsp.buyerco.com/deal-sync/v1/push
+Content-Type: application/json
+```
+
+**Payload**
+```json
+{
+ "id": "deal-ctv-retail-q4-114",
+ "sellerstatus": 4
+}
+```
+
+The buyer records that the seller has paused the deal. The buyer's own `buyerstatus` remains `2` (LIVE) — the buyer is still willing to traffic, but no bid requests will arrive while the seller side is paused.
+
+---
+
+### Step 2: Buyer Sends a RESUME_REQUEST Signal
+
+The buyer pushes a `DealSignal` to the seller's push endpoint. The signal carries `signaltype=0` (RESUME_REQUEST), a `signalid` (its idempotency key), and `liverevisionid` naming the terms the buyer intends to transact against. It carries no term fields, no `revisionid`, and no `negotiationstatus` — it is a request, not a term change and not a response to a revision.
+
+**Request**
+```
+POST https://harbor-rmn.com/deal-sync/v1/push
+Content-Type: application/json
+```
+
+**Payload**
+```json
+{
+ "dealid": "deal-ctv-retail-q4-114",
+ "signalid": "9d1f6c3b-8a24-4e57-b6d0-1c7e2a4f9b35",
+ "signaltype": 0,
+ "signaledby": {
+ "partyid": "dsp-seat-ttd-001",
+ "contactemail": "trader@buyerco.com",
+ "role": 1
+ },
+ "signaldate": "2026-11-18T15:20:00Z",
+ "liverevisionid": "7b2e1a9c-4d6f-4a13-8c0e-2f9b5d1a7e60",
+ "comment": "Fresh Q4 budget ready to spend against current terms. Requesting resume when the measurement issue is resolved."
+}
+```
+
+The seller records the signal and returns an HTTP 200 with the current Deal object. The deal is still `sellerstatus=4` (PAUSED) — the signal does not change any status field and does not compel the seller to act.
+
+**Response**
+```json
+{
+ "id": "deal-ctv-retail-q4-114",
+ "sellerdealid": "HRM-2026-CTV-114",
+ "name": "Q4 2026 Shoppable CTV — Harbor Retail Media",
+ "origin": "harbor-rmn.com",
+ "seller": "harbor-rmn.com",
+ "created": "2026-09-30T12:00:00Z",
+ "sellerstatus": 4,
+ "liverevision": {
+ "revisionid": "7b2e1a9c-4d6f-4a13-8c0e-2f9b5d1a7e60",
+ "revisedate": "2026-10-02T09:15:00Z",
+ "revisedby": {
+ "partyid": "harbor-rmn.com",
+ "contactemail": "deals@harbor-rmn.com",
+ "role": 0
+ },
+ "negotiationstatus": 1,
+ "comment": "Accepted Q4 terms."
+ }
+}
+```
+
+---
+
+### Step 3: Seller Resumes via the Existing PAUSED to LIVE Transition
+
+The measurement issue is resolved and the seller chooses to honor the request. It resumes by performing the already-defined `PAUSED (4) → LIVE (2)` transition — a status-only Deal push to the buyer's endpoint. No dedicated acknowledgment message is defined: the RESUME_REQUEST is answered by the status change itself, which the buyer observes on this push or on its next poll.
+
+**Request**
+```
+POST https://dsp.buyerco.com/deal-sync/v1/push
+Content-Type: application/json
+```
+
+**Payload**
+```json
+{
+ "id": "deal-ctv-retail-q4-114",
+ "sellerstatus": 2
+}
+```
+
+The buyer receives the push, sees `sellerstatus=2` (LIVE), and resumes trafficking against the deal's `liverevision` terms. The resume is complete without any new object type or acknowledgment round-trip.