RFX docs

Listing feed

RFX does not own its public listings (level 1). A licensed provider supplies them through the API below. Until the provider's API is ready, a mock implements the same contract, so switching means changing one address and one key.

Connection

Base addressCATALOG_URL in RFX
AuthenticationAuthorization: Bearer <key>, the key in CATALOG_API_KEY. Calls without it get 401
FormatJSON. Every path starts with /v1; a change that breaks a caller gets a new version

Endpoints

Method and pathReturns
GET /v1/marketsThe markets (categories) with id, name, source, updated_at, vendor_count
GET /v1/markets/{id}/vendorsOne page of a market's listings and next_cursor (null on the last page). Query: limit 1 to 500, cursor, updated_since
GET /v1/vendors/{id}One listing
GET /healthNo key. Whether the API can serve

A listing

{
  "id": "hubspot",
  "vendor": "HubSpot",
  "product": "HubSpot Sales Hub",
  "website": "https://www.hubspot.com",
  "rating": null,
  "ratings_count": null,
  "rating_verified": false,
  "source_url": "https://provider.example/vendors/hubspot",
  "market_id": "crm",
  "updated_at": "2026-11-10T08:00:00Z"
}

How RFX reads it

  1. At start, every page of every market. Only when all were read does RFX replace the listings it holds, so a failure half-way changes nothing.
  2. Again every hour (CATALOG_REFRESH_MINUTES, 0 turns it off). If the provider cannot be reached, RFX keeps what it has and logs a warning.
  3. A listing that leaves the feed leaves level 1. A vendor that had claimed it keeps its account, documents and deals.

At 10,000 listings and 500 per page, a refresh is about 20 calls. The full contract, with error codes and limits, is docs/CATALOG_API.md in the repository.