FurniOpsDocs

Overview

What FurniOps is, how its data reaches you, and the pieces you build with.

FurniOps collects furniture vendors' product data from wherever it lives (vendor APIs, platform feeds, CSV and Excel files, emailed price lists and product pages), turns it into one master record per product, and keeps it current. Every field records where its value came from. When a vendor changes a price, a stock level or a description, FurniOps writes the change once and tells every system that cares.

How data reaches you

There are three ways to read FurniOps, and they all carry the same objects and the same events:

WayUse it forStart with
REST APIReading the current state: products, variants, offers, sources, runs.GET /v1/products
Change feedKeeping a copy in sync. An ordered, replayable log of every change, read with a cursor; it is the source of truth.The change feed
WebhooksBeing told at once. Each change is POSTed to your endpoint, signed, retried for about three days.Your first webhook

A server-sent event stream (GET /v1/stream) carries the same events live, for dashboards and local tools such as furniops listen.

Webhooks are the doorbell, the feed is the ledger

Webhooks get a change to you within seconds, but a receiver can be down. The change feed keeps 30 days of events in commit order, so a system that must not miss a change follows the feed and treats webhooks as the signal to read it sooner. See Sync a catalogue.

The building blocks

  • Products, variants and offers. A product (prod_…) has sellable variants (var_…). Each variant has offers (ofr_…): one vendor's price, stock and availability at one location. Offers change far more often than product content, so they have their own fast path and their own events.
  • Sources. A source (src_…) is one connection to a vendor's data. Each pull is a run (run_…) that goes fetch, normalise, presence, master.
  • Events. Every change is an event (evt_…) with a type such as offer.changed, the version of the object after the change, and the fields that changed with their old and new values. See the event types.
  • Versions. Objects carry a version that only grows. Apply a change only when its version is newer than the one you hold, and retries and reordering can never take you backwards.

How you build

  • The REST API at https://api.furniops.com, JSON over HTTPS, with dated versions in the FurniOps-Version header.
  • The TypeScript SDK, @furniops/sdk: typed methods for every operation, retries, idempotency keys, pagination, webhook verification and the change stream, with no runtime dependencies.
  • The CLI, furniops: sign in from a terminal, forward events to a local webhook handler without a tunnel, trigger test events and tail the stream.

Every account has a test mode: a sandbox catalogue, seeded with sample products, that test keys read and write instead of your live data.

Conventions at a glance

  • Requests and responses are JSON with snake_case fields. Errors are RFC 9457 problem details with a stable code.
  • IDs are prefixed and opaque (prod_034XqBaL2mRLTZPXyRbaUc). A wrong prefix, like another organisation's resource, answers 404.
  • Money is an integer in minor units with its currency: 94900 with usd is $949.00.
  • Timestamps are RFC 3339 in UTC.
  • Lists use cursor pagination. Every POST takes an Idempotency-Key. Updates that could overwrite someone else's change take If-Match.
  • Every response carries a Request-Id; quote it to support, or find the request in your request logs.
  • Requests carry an API key or an OAuth access token as a bearer token.

On this page