TBBNMerchantDocs
API

Catalog feed (scheduled sync)

If you already export a product feed, you can point TBBN at a feed file instead of writing API-calling code. It's the lower-effort alternative to direct listing sync. You can also use both: bulk catalog through the feed, and fast-moving items through the API. Once ingested, a listing looks the same to TBBN whichever path created it.

Your obligation is the listing's status, not its sales. If you list only for reach (not through the trade engine), you never report sales to TBBN. You do keep each item's status current. With a feed, that means the feed itself: mark sold-out items out of stock or drop them, and TBBN follows on its next pull.

Read this before you build around a feed. Three things to plan around:

  • Map your field names. TBBN's feed uses its own column names (table below), and they aren't identical to Google's or Meta's (item_id, not id; original_price, not price). Most feed tools can export a second feed with renamed columns. Your categories also need to map onto TBBN's taxonomy.
  • Sellers are optional. A row with no external_seller_id is your store's own item, shown under your store's name (or goes to defaultSellerId, if you set one).
  • Multi-seller catalogs: name the seller on each row. One feed covers your whole catalog. Put your own reference for each item's seller in external_seller_id, the same attribute Google's marketplace feeds use — any stable value per customer; it needn't be your customer id. Until that customer links their TBBN account (with the same reference as merchant_seller_ref), the row is listed under your store and the sync result says how many are waiting; when they link, those items become theirs. You can also put a linked customer's TBBN seller id in external_seller_id. See Seller account linking.
  • Delisting follows the pull, not the moment. Each pull takes a listing down (it becomes UNAVAILABLE) when its row has availability set to out_of_stock (or "out of stock"), a quantity of 0, or an item_id that's no longer in the feed. Pulls happen every 24 hours, so an item that sells elsewhere can stay visible until the next pull. When that gap matters — one-of-a-kind items, stock that also sells in store — update the feed file and trigger a pull with POST /v1/merchant/feed-source/fetch-now, or sync those items through the API instead, where POST /merchant/listings/{id}/availability takes an item down the moment it sells.

How delisting behaves:

  • It applies only to listings the feed manages. A listing you created through the API is never taken down by the feed.
  • A listing reserved in a trade isn't taken down mid-trade.
  • A listing the feed took down comes back once its item is in stock and in the feed again. One you marked unavailable yourself stays that way.
  • If a pull fails or looks incomplete, TBBN leaves your listings as they are and reports it in the sync result. Check that the feed file is complete.

TBBN never replaces your own stock check: whatever a listing shows, re-check availability at your checkout.

Set up a feed source

POST /v1/merchant/feed-source
{
  "feedUrl": "https://yourstore.example.com/feeds/tbbn.xml",
  "feedFormat": "XML",
  "feedUsername": "...",
  "feedPassword": "..."
}
  • feedUrl must be a public address (http or https) — TBBN fetches it, so an address on a private network is refused with 400 FEED_URL_NOT_ALLOWED, and so is a redirect to one.
  • feedFormat is XML (RSS 2.0-shaped) or CSV. A tab-separated file works as CSV.
  • feedUsername/feedPassword are sent as HTTP Basic Auth when TBBN fetches your URL. Never embed credentials in the URL itself.
  • defaultSellerId is optional. When set it must be one of your own sellers (403 SELLER_NOT_LINKED otherwise), and it's credited with every row that has no external_seller_id. Without it those rows are your store's own items.

TBBN pulls the feed every 24 hours. Trigger an immediate pull any time with:

POST /v1/merchant/feed-source/fetch-now

The response, and GET /v1/merchant/feed-source afterwards, shows the sync result: items synced, rows skipped and why, listings taken down or put back. Monitor it. A live feed on a Business still on the free Sandbox plan adds and changes nothing — the result says so — but still takes items down; choose a plan to sync it (see Pricing).

Feed fields

FieldRequiredNotes
item_idYesYour unique key; identifies this listing across pulls.
categoryYesA TBBN category name (GET /v1/catalog/categories). Common other names are recognised; anything else is placed in Other — see Listing kinds.
original_priceYesAmount and ISO 4217 currency code, e.g. 19.99 USD. Must be your store's country's currency.
listing_typeYesSALE / TRADE / BOTH. A SALE listing is discovery-only and never receives offers — visitors follow product_link to buy on your site.
titleNoShown on the listing. Without it the listing shows item_id, so send it.
sub_category, brand, conditionNoImprove search and matching. sub_category is one of the category's subcategories.
image_link, additional_image_linkNoOne primary image and optional extra images, as https links. A listing shows the first five; TBBN copies each into its own storage within minutes and drops any that can't be fetched or aren't images.
product_linkNoThe item's page on your site. Send it for every SALE listing — it's the only way a visitor can buy.
availability, quantityNoout_of_stock, or a quantity of 0, takes the listing down until the item is back in stock.
external_seller_idNoYour reference for this item's seller, or their TBBN seller id (see "Multi-seller catalogs" above). Without it, defaultSellerId, else your store.
location_idNoThe store number you gave the location this stock is at.
<want> (XML feeds only)NoWhat the seller would take in trade: repeated <want> elements with category, sub_category, brand.

A row missing a required field is skipped. Every other row goes through the same validation as a direct API call, including the prohibited-items screen; a matching row is held for review rather than published.

Vehicles, homes, services and tickets

Add a kind column (GOODS, VEHICLE, PROPERTY, SERVICE or TICKET) and one detail_<field> column per detail, the field name written in snake case: detail_vehicle_type, detail_make, detail_model, detail_year, detail_mileage; detail_offering, detail_property_type, detail_bedrooms. In an XML feed they're elements of the same names. The fields and their allowed values are in Listing kinds; option values aren't case-sensitive, and a yes/no field takes true, yes or 1.

item_id,title,category,original_price,listing_type,kind,detail_vehicle_type,detail_make,detail_model,detail_year,detail_mileage,detail_mileage_unit
car-1042,2019 Toyota Corolla LE,Vehicles,14500.00 USD,BOTH,VEHICLE,Car,Toyota,Corolla,2019,48000,mi

A row with no kind keeps the kind its listing already has (GOODS for a new one). A row whose details are missing a required field, or carry a value that isn't allowed, isn't published and counts as failed in the sync result, like any other invalid row.