FurniOpsDocs

Events reference

Every event FurniOps publishes, generated from the API's own contract. What each one means, which channels deliver it (webhooks, the change feed, the stream), whether test mode can emit a sample, and its payload.

Every change FurniOps makes is an event. Catalogue and source events reach you three ways (webhooks, the change feed and the stream); events about your organisation itself reach your webhook endpoints only. Every event shares one envelope:

{
  "id": "evt_034XqBaL2mRLTZPXyRbaUi",
  "type": "offer.changed",
  "spec_version": "1.0",
  "source": "furniops/catalog",
  "subject": "ofr_034XqBaL2mRLTZPXyRbaUg",
  "time": "2026-10-04T10:00:02Z",
  "tenant_id": "org_034XqBaL2mRLTZPXyRbaUj",
  "version": 12,
  "schema_version": 1,
  "correlation_id": "run_034XqBaL2mRLTZPXyRbaUk",
  "causation_id": null,
  "livemode": true,
  "data": {
    "id": "ofr_034XqBaL2mRLTZPXyRbaUg",
    "variant": "var_034XqBaL2mRLTZPXyRbaUf",
    "source": "src_034XqBaL2mRLTZPXyRbaUh",
    "catalogue": "cat_034XqBaL2mRLTZPXyRbaUd",
    "location": "DAL",
    "availability": "in_stock",
    "version": 12,
    "facets": ["price"],
    "fields": [
      {
        "path": "cost",
        "old": 89900,
        "new": 94900,
        "provenance": {
          "source": "src_034XqBaL2mRLTZPXyRbaUh",
          "method": "mapped",
          "confidence": 1,
          "observed_at": "2026-10-04T10:00:00Z"
        }
      }
    ]
  }
}

Each field is described in The event envelope. Deduplicate by id, which is also the webhook-id header of every delivery, and apply by version.

Every event

This table is generated from the contracts release these docs are built from. Each type links to its payload, field by field.

TypeSent whenDelivered bySample
catalogue.unverifiedA vendor catalogue is no longer verified by its brand: FurniOps took an approved claim back.Webhooks, feed, streamYes
catalogue.verifiedA vendor catalogue is now verified by its brand: FurniOps approved the brand's claim.Webhooks, feed, streamYes
credits.exhaustedAvailable credit reached zero: once today's allowance is spent too, Ask AI answers 429 ai_budget_reached.Webhooks onlyNo
credits.expiringA lot of credit expires in 30 days with credit left in it, once per lot.Webhooks onlyNo
credits.lowAvailable credit fell below the organisation's low_balance_micros, once each time it crosses.Webhooks onlyNo
credits.purchasedStripe reported a credit purchase's invoice paid and its credit was added: once per purchase.Webhooks onlyNo
delivery.disabledFurniOps disabled a webhook endpoint: no delivery succeeded for 72 hours, or it answered 410 Gone (status_reason). Sent to the organisation's other endpoints that subscribe to it.Webhooks onlyNo
export.completedAn export succeeded or failed. Read it (GET /v1/exports/{id}) for its files, or its error.Webhooks onlyNo
offer.changedA source's offer changed (price, stock or availability; see facets): the changed fields. A source that stops stating an offer withdraws it: withdrawn_at is set, quantity becomes 0, incoming empty and availability out_of_stock (facets stock and availability); stating it again clears withdrawn_at.Webhooks, feed, streamYes
offer.createdA source offered a variant at a location for the first time: every field.Webhooks, feed, streamYes
product.createdA master product was made from a source record: every field, with old: null.Webhooks, feed, streamYes
product.discontinuedA master product was discontinued: its sources stopped listing it for long enough (the absence ladder).Webhooks, feed, streamYes
product.mergedA master product was merged into another (matching or a person): it now redirects to merged_into, and reads of its ID answer with the survivor.Webhooks, feed, streamYes
product.publishedA vendor's product became visible to the network (its catalogue was published, or the product listed again): every field, with old: null, like product.created. Its variants and offers follow as their own .created events.Webhooks, feed, streamYes
product.unmergedA merge was undone: the product is its own again under its original ID, with every field.Webhooks, feed, streamYes
product.updatedA master product's data or lifecycle status changed (other than to discontinued): the changed fields.Webhooks, feed, streamYes
product.withdrawnA vendor's product left the network (its catalogue was withdrawn, or the product hidden): no fields. Drop it, its variants and its offers; a later product.published brings it back.Webhooks, feed, streamYes
proposal.appliedA proposal was applied: accepted by a person, or at once as low risk under auto_low_risk.Webhooks onlyNo
proposal.createdAn AI agent proposed a change that passed its proof and waits for a person: accept or reject it (POST /v1/proposals/{id}/accept).Webhooks onlyNo
source.blockedA source kept failing (or its URL is refused) and is now blocked: no runs until the organisation sets it active. status_reason says why.Webhooks, feed, streamYes
source.degradedA source failed several runs in a row and is now degraded; it is still scheduled. status_reason says why.Webhooks, feed, streamYes
source.recoveredA degraded source ran successfully and is active again.Webhooks, feed, streamYes
usage.threshold_reachedA meter reached 80% or 100% of its monthly quota in live mode, once a month per meter and threshold. At 100% the metered action is refused (429 quota_exceeded) until the month ends.Webhooks onlyNo
variant.createdA master variant was made from a source record: every field, with old: null.Webhooks, feed, streamYes
variant.mergedA master variant was merged into another (the same item from two sources): it now redirects to merged_into, and its offers moved there.Webhooks, feed, streamYes
variant.unmergedA variant merge was undone: the variant is its own again under its original ID, with every field and its offers back.Webhooks, feed, streamYes
variant.updatedA master variant's data changed: the changed fields.Webhooks, feed, streamYes
webhook.testA test event, sent only when asked for (POST /v1/webhook-endpoints/{id}/test), whatever the endpoint subscribes to.On requestNo
  • Webhooks, feed, stream: delivered by webhooks, and kept in the change feed and the stream, subject to licences.
  • Webhooks only: about your organisation, not a catalogue's records. Only your endpoints of the event's mode that subscribe to the type (or to *) receive it.
  • Sample: POST /v1/test/events can emit a sample of it in test mode.

Subscribing

An endpoint's event_types names the types it receives, or * for every public type, present and future. New types are added without a new API version, so a receiver should ignore a type it does not know. webhook.test is sent only when you ask for one, whatever an endpoint subscribes to.

In the dashboard

Developers › Events lists the events of the mode you are in, filtered by type, each with its payload and the endpoints it went to.

On this page