Merchant Integration Guide (narrative walkthrough)
This is the story a merchant engineer reads once, end to end, before touching the API reference.
Full endpoint details live in docs-site (generated from packages/openapi-spec); this is the
mental model.
1. Create a Business, then get approved
Every Merchant must link to a Business profile first (Phase 22 — see
docs/business/conflict-resolution-log.md item 18): register a Marketplace account and create a
Business at business.tbbnetwork.com, then pass its id as businessId when you apply. Your
business rep gets a temporary account link by email (POST /v1/merchants triggers this
internally after your onboarding form, now requiring that businessId). It lasts 7 days and lets
you upload documents, track review status, and resubmit if something's missing. Once TBBN
approves you, that temporary account becomes your permanent Merchant Dashboard login — same
email, same OTP-gated login, now persistent. (Note: "Merchant Dashboard" here is
apps/merchant-dashboard — a different app from apps/business-dashboard, which manages the
Business profile itself, not a specific Merchant's integration.) Invite developers and account
managers from the dashboard; they get scoped roles (DEVELOPER for API/integration work,
ACCOUNT_MANAGER for seller/billing management).
2. Get your keys
From the dashboard, generate a sandbox API key first — free, unlimited (rate-limited) usage, no
production data. Build your integration against sandbox. When ready, generate a production key
(sk_live_...) — this is what starts counting against your plan's included usage (see
docs/business/pricing.md).
3. Link your sellers — or trade for them directly
TBBN accounts can now only be created by the person themself, on tbbnetwork.com — merchants can
no longer create one on a seller's behalf (see docs/business/conflict-resolution-log.md item
21). You have two options for a seller who trades through your store:
Option A — link their existing TBBN account. Have them approve a link via the OAuth
account-linking handshake: redirect their browser to
account.tbbnetwork.com/link/authorize?client_id=...&redirect_uri=...&scope=link:seller&merchant_seller_ref=...
(register an OAuth client first via POST /v1/oauth-clients), and once they approve, your
backend exchanges the resulting code for a link via POST /v1/link/oauth/token —
server-to-server, never a password. POST /merchant/sellers/verify still exists for reporting a
match by email/phone ({name, verified_email, verified_phone, merchant_seller_ref}), but a
cross-merchant match now only ever returns requires_confirmation: true — completing that link
requires the OAuth handshake above, not an OTP code relayed through you.
Option B — no account needed. If your plan tier allows it (Growth/Enterprise), call
POST /merchant/sellers/headless with {merchantId, merchantSellerRef, name} to create a
"headless" Seller — a trade participant tracked entirely by you, with no linked TBBN account at
all. It's your responsibility to build a system around this that works with TBBN's
infrastructure; TBBN's responsibility is providing the guidance, endpoints, and technology for
it to succeed (see docs/business/conflict-resolution-log.md item 21 for what this can't do,
e.g. accumulate a cross-merchant reputation history).
4. Sync your listings
POST/PUT/DELETE /merchant/listings — you own listing content, TBBN just mirrors it. Set
visibility per your plan tier: PRIVATE (internal only), GLOBAL (TBBN Exchange + other
global merchants), BOTH, or ENTERPRISE (only your hand-picked enterprise trading merchants —
Enterprise tier only). Set listingType (SALE/TRADE/BOTH) — a SALE listing is discovery
only, never offer-able; TBBN redirects visitors to merchantItemUrl (set it, or visitors see a
plain "not available for TBBN checkout" message) instead of orchestrating a trade for it. Include
wants if you want your sellers' listings to show up in match recommendations, not just search.
If you'd rather not write API-calling code — e.g. you already export a Google Merchant Center or
Meta Commerce Manager-style feed for your own catalog — see merchant-catalog-feed.md for the
scheduled feed-pull alternative to this section. It's specified but not yet built; this direct
API path is the only one that works today.
5. Handle offers and trade sessions
Offers and trade sessions happen on TBBN's side (or your embedded widget, or TBBN Exchange) —
you don't build negotiation UI unless you want full API control instead of the widget. You'll
receive webhooks (offer.created, offer.accepted, trade.accepted) as things progress.
6. Handle checkout — this is the part you must build
When a trade session reaches RESERVED, you'll receive a checkout.started webhook for your
side of the session whenever one of your sellers needs to pay the other seller's merchant. Wait
— re-read that: you receive checkout redirects for trades where your seller owes money to the
other side's item, and your checkout endpoint (which you registered in merchant_settings)
must accept {tradeSessionId, originalPrice, tradeAmount, currency} and compute your own taxes/
commissions/fees on top, exactly as you would for any other sale. After payment, call back with
payment.completed or payment.failed. Do not wait for the other side to pay first — both
sides' checkouts are live simultaneously the moment the session is RESERVED.
7. Fulfill
Once TBBN sees both sides report payment.completed, you'll get a trade.completed /
fulfillment.started-eligible signal. Fulfillment, shipping, tracking, returns — all yours, same
as any other order.
See docs/architecture/trade-session-state-machine.md for the exact state machine and
docs/architecture/event-webhook-catalog.md for every webhook payload shape.