DealsOfferUpdatedPayload deals.offer.updated@1
Generated at from
openvibe-contracts v0.34.2 and
openvibe-sdk v0.5.0.
- Version
- 1.0.0
- Owner
- deals
- Visibility
- first-party
- Status
- active
- Compatibility
- backward
- Schema
https://openvibe.network/contracts/events/payloads/deals.offer.updated.v1.json
deals.offer.updated v1 (OpenVibe.Deals server/domain/indexing.js emitOffer, called from server/domain/offers.js and server/domain/importer.js). Something about a canonical offer changed; `changed` says what, and a few call sites add one reference: an edit (offers.js update: the edited columns, among title, description, category, expires_at, product_id, ai_summary, review_state, text_origin); a price/availability report by a person (observe) or a newer or re-fetched Sources item (importer importItem) ([observation] + observation_id); a second Sources item with the same link attached to an existing offer ([sources] + observation_id); a Sources item removed at the source ([sources] + source_removed; an imported offer left with no live source is disabled in the same transaction, so status is then disabled); moderators disabling it or re-activating a disabled or expired offer ([status] + moderation); a person reviewing imported or AI text ([review_state]); a merge ([merged] + merged_offer_id, sent for the merge target); an unmerge (two events: [unmerged] + unmerged_offer_id for the former target, and [unmerged] + unmerged_from for the restored offer). Written in the transaction that made the change, next to the offer's (and its product's) deals.index_document.* event. The rest of the payload is the offer as it now stands, as in deals.offer.created. Deliberately left out: old values, the description text, identities and vote counts (deals.vote.changed carries those counts). Envelope: subject { type: offer, id: <offer_id> }, visibility public when the offer is active and the SEO gate lets it be listed, otherwise internal, priority important (default), actor user:<the person who acted, usr_…>, service:<calling service> when a service acts without a person, service:deals for the importer. No consumer is built yet.
Fields
| Field | Type | Required | Description | Constraints |
|---|---|---|---|---|
offer_id | string | yes | The canonical (root) offer id. |
|
slug | string | yes | Page slug: the slugified title plus the last six characters of the id. |
|
url | string | yes | Canonical offer page URL on Deals (/d/<slug>). |
|
title | string | yes |
| |
status | enum | yes |
| |
store | string | null | yes | Store domain: the offer link's host without a leading www.; null when none could be derived. |
|
product_id | string | null | yes | Deals product the offer is attached to, if any. |
|
latest_observation | object | null | yes | The newest observation across the offer's merge group; null only when the group has none. | |
freshness | enum | yes | fresh while the latest observation is younger than DEALS_FRESHNESS_HOURS, stale after, unobserved without one. |
|
indexability | object | yes | The SEO gate decision in Search's shape (index-hooks searchIndexability). |
|
indexability.decision | enum | yes |
| |
indexability.reasons | array of string | yes | Search reason names, e.g. stale_price, expired, takedown, owner_decision (imported or AI text awaiting review). |
|
changed | array of enum | yes | What changed: edited columns (update), or one of observation, sources, status, review_state, merged, unmerged. |
|
observation_id | string | changed [observation] or [sources] from a report or an import: the observation just recorded. |
| |
source_removed | string | changed [sources] after a removal: the OpenVibe.Sources item that was removed (takedown, licence). |
| |
moderation | enum | changed [status] by a moderator: disabled, or enabled (a disabled or expired offer made active again). |
| |
merged_offer_id | string | changed [merged]: the duplicate now merged into this offer. |
| |
unmerged_offer_id | string | changed [unmerged], on the former target: the offer split back out. |
| |
unmerged_from | string | changed [unmerged], on the restored offer: the offer it had been merged into. |
|
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: edit
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"slug": "usb-c-charger-65w-k0mnpq",
"url": "https://openvibe.deals/d/usb-c-charger-65w-k0mnpq",
"title": "USB-C charger 65W (GaN)",
"status": "active",
"store": "shop.example",
"product_id": null,
"latest_observation": {
"price": "29.99",
"currency": "USD",
"availability": "in_stock",
"observed_at": "2026-09-23T10:15:00.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "index",
"reasons": []
},
"changed": [
"title",
"category"
]
}Valid: merge
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"slug": "usb-c-charger-65w-k0mnpq",
"url": "https://openvibe.deals/d/usb-c-charger-65w-k0mnpq",
"title": "USB-C charger 65W",
"status": "active",
"store": "shop.example",
"product_id": null,
"latest_observation": {
"price": "29.99",
"currency": "USD",
"availability": "in_stock",
"observed_at": "2026-09-23T10:15:00.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "index",
"reasons": []
},
"changed": [
"merged"
],
"merged_offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPV"
}Valid: observation
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"slug": "usb-c-charger-65w-k0mnpq",
"url": "https://openvibe.deals/d/usb-c-charger-65w-k0mnpq",
"title": "USB-C charger 65W",
"status": "active",
"store": "shop.example",
"product_id": null,
"latest_observation": {
"price": "24.99",
"currency": "USD",
"availability": "limited",
"observed_at": "2026-09-23T14:02:11.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "index",
"reasons": []
},
"changed": [
"observation"
],
"observation_id": "dpo_01JAB2C3D4E5F6G7H8J9K0MNPT"
}Valid: source-removed-disabled
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPR",
"slug": "garden-hose-reel-weekend-sale-k0mnpr",
"url": "https://openvibe.deals/d/garden-hose-reel-weekend-sale-k0mnpr",
"title": "Garden hose reel weekend sale",
"status": "disabled",
"store": "garden.example",
"product_id": "dpr_01JAB2C3D4E5F6G7H8J9K0MNPS",
"latest_observation": {
"price": null,
"currency": null,
"availability": null,
"observed_at": "2026-09-23T06:00:00.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "noindex",
"reasons": [
"takedown",
"owner_decision"
]
},
"changed": [
"sources"
],
"source_removed": "itm_01JAB2C3D4E5F6G7H8J9K0MNPW"
}Valid: unmerge-restored
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPV",
"slug": "usb-c-charger-65w-k0mnpv",
"url": "https://openvibe.deals/d/usb-c-charger-65w-k0mnpv",
"title": "USB-C charger 65W",
"status": "active",
"store": "shop.example",
"product_id": null,
"latest_observation": {
"price": "29.99",
"currency": "USD",
"availability": "in_stock",
"observed_at": "2026-09-23T10:15:00.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "index",
"reasons": []
},
"changed": [
"unmerged"
],
"unmerged_from": "dof_01JAB2C3D4E5F6G7H8J9K0MNPQ"
}Rejected: bad-merged-id
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"slug": "usb-c-charger-65w-k0mnpq",
"url": "https://openvibe.deals/d/usb-c-charger-65w-k0mnpq",
"title": "USB-C charger 65W",
"status": "active",
"store": "shop.example",
"product_id": null,
"latest_observation": {
"price": "29.99",
"currency": "USD",
"availability": "in_stock",
"observed_at": "2026-09-23T10:15:00.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "index",
"reasons": []
},
"changed": [
"merged"
],
"merged_offer_id": "B"
}Rejected: missing-changed
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"slug": "usb-c-charger-65w-k0mnpq",
"url": "https://openvibe.deals/d/usb-c-charger-65w-k0mnpq",
"title": "USB-C charger 65W",
"status": "active",
"store": "shop.example",
"product_id": null,
"latest_observation": {
"price": "29.99",
"currency": "USD",
"availability": "in_stock",
"observed_at": "2026-09-23T10:15:00.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "index",
"reasons": []
}
}Rejected: unknown-change
{
"offer_id": "dof_01JAB2C3D4E5F6G7H8J9K0MNPQ",
"slug": "usb-c-charger-65w-k0mnpq",
"url": "https://openvibe.deals/d/usb-c-charger-65w-k0mnpq",
"title": "USB-C charger 65W",
"status": "active",
"store": "shop.example",
"product_id": null,
"latest_observation": {
"price": "29.99",
"currency": "USD",
"availability": "in_stock",
"observed_at": "2026-09-23T10:15:00.000Z"
},
"freshness": "fresh",
"indexability": {
"decision": "index",
"reasons": []
},
"changed": [
"price"
]
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('deals.offer.updated@1', value); // { valid, errors: [{ path, message }] }