API Reference
TBBN Platform API — v0.1.0
Trade By Barter Network infrastructure API. This document fully specifies the Phase 0-13 working surface: Auth, Merchants, API Keys, Sellers/Identity, Listings, Catalog, Media, Directory, Search, Trade Engine (settlement), Currency, Localization, Matching, Recommendations, Offers, Reservations, Trade Sessions, Checkout, Billing, Notifications, Webhooks, Audit, Moderation, Fraud, Reputation, Analytics, Feature Flags, and Sandbox — see docs/api/openapi-workflow.md.
Live resources
Fully implemented — see the matching service's README for how it's tested.
Auth
WORKING12 endpoints
Businesses
WORKING20 endpoints
Reputation
WORKING5 endpoints
Merchants
WORKING8 endpoints
ApiKeys
WORKING4 endpoints
Sellers
WORKING11 endpoints
Listings
WORKING9 endpoints
Catalog
WORKING3 endpoints
Media
WORKING1 endpoint
Directory
WORKING2 endpoints
Search
WORKING1 endpoint
TradeEngine
WORKING1 endpoint
Currency
WORKING2 endpoints
Localization
WORKING3 endpoints
Matching
WORKING2 endpoints
Recommendations
WORKING1 endpoint
Offers
WORKING7 endpoints
Reservations
WORKING3 endpoints
TradeSessions
WORKING5 endpoints
Checkout
WORKING4 endpoints
Billing
WORKING7 endpoints
Notifications
WORKING2 endpoints
Webhooks
WORKING10 endpoints
AuditLogs
WORKING1 endpoint
Moderation
WORKING3 endpoints
Fraud
WORKING1 endpoint
Analytics
WORKING1 endpoint
FeatureFlags
WORKING3 endpoints
Sandbox
WORKING2 endpoints
All live endpoints
/v1/auth/merchant/loginMerchant rep login (password or OTP)/v1/auth/merchant/otp/requestRequest email OTP for merchant rep login/v1/auth/merchant/otp/verifyVerify merchant rep OTP and issue a session/v1/auth/member/registerDirect self-registration for a Marketplace profile (Phase 22) — the primary way anyone joins TBBN now. See docs/business/conflict-resolution-log.md item 18.
/v1/auth/member/otp/verifyComplete self-registration and issue a session/v1/auth/seller/otp/requestRequest OTP for a marketplace member's direct TBBN Exchange login/v1/auth/seller/otp/verifyVerify marketplace member OTP and issue a session/v1/auth/seller/magic-link/requestRequest a passwordless magic link for a marketplace member/v1/auth/seller/magic-link/consumeConsume a magic link token, issuing a session/v1/auth/refreshRotate a refresh token for a new access token/v1/auth/logoutRevoke the current session/v1/auth/meResolve the current principal from the bearer token/v1/businessesCreate a Business, owned by the authenticated Marketplace member/v1/businessesList the authenticated Marketplace member's own Businesses/v1/businesses/{id}Get a Business/v1/businesses/{id}Update a Business (owner only)/v1/businesses/{id}Soft-delete a Business (owner only)/v1/businesses/pending-verificationOps-only in practice (Phase 34, fronted by apps/ops-console); no RBAC guard yet — see docs/security/rbac-strategy.md.
/v1/businesses/{id}/verificationUnauthenticated by design (Phase 34) — interim ops-console review action; see BusinessesService.setVerification's doc comment.
/v1/businesses/{businessId}/business-usersInvite a team member with a role (ADMIN+, Phase 34)/v1/businesses/{businessId}/business-usersList a Business's team (ADMIN+)/v1/businesses/{businessId}/business-users/{userId}Change a team member's role (ADMIN+)/v1/businesses/{businessId}/business-users/{userId}Remove a team member (ADMIN+; cannot remove the owner)/v1/businesses/{businessId}/branchesAdd a Branch (location) to a Business (owner only)/v1/businesses/{businessId}/branchesList a Business's Branches/v1/branches/{id}Update a Branch (owner only)/v1/branches/{id}Remove a Branch (owner only)/v1/branches/{id}/space-statusToggle a Branch's Space eligibility flag (owner only). Phase 23 hook only — no Space product logic exists yet.
/v1/businesses/{businessId}/merchant-linksLink a Merchant account to a Business (owner only, many-to-many)/v1/businesses/{businessId}/merchant-linksList a Business's linked Merchant accounts/v1/businesses/{businessId}/merchant-links/{linkId}/revokeRevoke a Business<->Merchant link (owner only)/v1/business-merchant-linksReverse lookup — a Merchant's linked Businesses. Deliberately not nested under /v1/merchants/* — that prefix is routed to merchant-service by api-gateway's ROUTES table (prefix match), so a route nested there would never reach business-service.
/v1/reputation/reviewsSubmit a 1-5 star review of a Merchant or a Space Branch — must be tied to a real completed trade session or Space booking the reviewer was actually a party to.
/v1/reputation/merchants/{id}/reviewsA Merchant's reviews plus aggregate rating/v1/reputation/branches/{id}/reviewsA Space Branch's reviews plus aggregate rating/v1/reputation/businesses/{id}/reviews-summaryAggregate rating rolled up across every Merchant/Branch linked to a Business (direct Postgres read, no live cross-service call).
/v1/merchantsSubmit a merchant onboarding application (creates a 7-day temp account)/v1/merchants/{id}Get merchant/v1/merchants/{id}Update merchant settings (ADMIN/OWNER only)/v1/merchants/{id}/submit-applicationSubmit or resubmit onboarding documents during the 7-day temp window/v1/merchants/{id}/application-statusTrack onboarding application status/v1/merchants/{id}/users/inviteInvite a developer or account-manager sub-user (ADMIN/OWNER only)/v1/merchants/{id}/usersList merchant org users/v1/merchants/{id}/users/{userId}/roleChange a sub-user's role (OWNER only)/v1/api-keysCreate an API key (ADMIN/OWNER only; production keys require ADMIN+ approval)/v1/api-keysList API keys (never returns the full key, only the prefix)/v1/api-keys/{id}/rotateRotate a key (old key marked ROTATED, still valid for a grace window)/v1/api-keys/{id}Revoke a key immediately/merchant/sellers/verifyMerchant-facing: register or match a seller after the MERCHANT has verified them. See docs/business/glossary.md "Identity federation" — sellers never call this directly.
/merchant/sellers/headlessMerchant-facing: create a headless Seller (Phase 27) — a trade participant with no linked TBBN account, gated by the calling Merchant's plan tier.
/v1/oauth-clientsRegister a Merchant's account-linking OAuth client (Phase 28)/v1/oauth-clientsList a Merchant's OAuth clients/v1/oauth-clients/{id}/rotate-secretRotate an OAuth client's secret — the clientId is unchanged/v1/oauth-clients/{id}Revoke an OAuth client/v1/link/oauth/clients/{clientId}Public client metadata — used by apps/account-dashboard's consent screen to validate redirect_uri and render "Merchant X wants to link your TBBN profile" before showing Approve/Deny.
/v1/link/oauth/consentStep 1 of the OAuth account-linking handshake (Phase 28) — the logged-in member approves. Creates a short-lived, single-use authorization code; the caller (the consent page) performs the actual redirect.
/v1/link/oauth/tokenStep 2 of the OAuth account-linking handshake — the Merchant's backend exchanges the code for a link. No access/refresh token is issued; this only ever establishes a seller_merchant_links row. See docs/business/conflict-resolution-log.md item 22.
/v1/sellers/{id}Resolve a marketplace member with all linked merchant accounts (internal/ops use)/v1/sellers/{id}/unlinkOps-only unlink of a merchant link (fraud/dispute remediation)/merchant/listingsCreate or sync a listing. Upserts on (merchantId, merchantListingRef) — a repeat call with the same ref updates the existing listing rather than creating a duplicate. See docs/api/merchant-integration-guide.md "Sync your listings".
/merchant/listings/{id}Update a listing by id (partial — only supplied fields change)/merchant/listings/{id}Soft-delete a listing/merchant/listings/{id}/availabilityReport an availability change. reservation-service is the primary caller for RESERVED during a trade session; merchants call this directly for SOLD/UNAVAILABLE from their own inventory changes outside of TBBN trades.
/merchant/listings/{id}/wantsReplace a listing's wants array (full replace, not merge) — see docs/business/glossary.md "Wants"/v1/listings/{id}/wantsRead a listing's wants array/v1/listings/{id}Get a listing/v1/listingsDirectory-lite listing read across all visibilities the caller is entitled to — full ranked search lives in Search/Matching/v1/listings/individualSelf-service individual (non-Merchant) listing (Phase 26) — sellerId is resolved from the caller's own marketplace-member session, never the request body.
/v1/catalog/categoriesList all top-level categories in the taxonomy/v1/catalog/categories/{category}/subcategoriesList subcategories under a category/v1/catalog/brandsList brands, optionally scoped to a category and/or subcategory/v1/media/ingestIngest listing images from https:// source URLs (jpg/jpeg/png/webp only, max 10 per call) into TBBN-hosted canonical URLs suitable for a listing's images array.
/v1/directory/listingsPublic global-directory listing read. Only GLOBAL/BOTH-visibility listings ever appear here — PRIVATE and ENTERPRISE never do. See docs/business/glossary.md "Global vs Private vs Both vs Enterprise".
/v1/directory/listings/{id}Get a single listing from the public global directory/v1/search/listingsPlain filtered/keyword listing search, no compatibility scoring (compatibility scoring lives in Matching). query does a case-insensitive contains match across title, brand, subcategory, and model; minTradeValue/maxTradeValue filter on the computed TradeValue = OriginalPrice + RequestedAmount - WillingToPay.
/v1/trade-engine/settlementThe authoritative TradeValue/settlement computation — offer-service and trade-session-service call this rather than reimplementing the formula (TradeValue = OriginalPrice + RequestedAmount - WillingToPay per listing). All listings in a trade must share one currency; cross-currency settlement-of-record is not yet supported and is rejected outright.
/v1/currency/supportedList supported currency codes/v1/currency/convertConvert an amount between supported currencies using static reference rates. Estimate only — never authoritative for settlement (see TradeEngine, which rejects cross-currency trades outright rather than trusting these rates).
/v1/localization/countriesList supported countries/v1/localization/languagesList supported languages/v1/localization/normalize-phoneNormalize a phone number to a canonical format/v1/matching/candidatesBulk candidate ranking for a single listing — scores the network's candidate pool (subject to the same PRIVATE/GLOBAL/BOTH visibility boundary directory-service enforces) against the source listing and returns the top N by Trade Compatibility Score. See docs/architecture/matching-algorithm-spec.md.
/v1/matching/scoreDirect pairwise Trade Compatibility Score for two known listings — used to preview compatibility before sending an offer/v1/recommendations/sellers/{sellerId}Personalized "for you" feed for a seller — scores the network's candidate pool against every active listing the seller owns and keeps each candidate's best score, so a candidate that's a great match for any one of the seller's listings surfaces once. See docs/architecture/matching-algorithm-spec.md.
/v1/offersCreate an offer. listingIdsA is the existing listing(s) being offered ON, owned by toSellerId; listingIdsB is the listing(s) offered IN EXCHANGE, owned by fromSellerId — see docs/business/conflict-resolution-log.md item 3.
/v1/offersList offers for a seller/v1/offers/{id}Get an offer. A PENDING offer past its expiresAt is lazily transitioned to EXPIRED on read./v1/offers/{id}/acceptAccept a PENDING offer — only the recipient (toSellerId) may accept. Does not create a trade session directly; trade-session-service reacts to the resulting offer.accepted event.
/v1/offers/{id}/rejectReject a PENDING offer — only the recipient (toSellerId) may reject/v1/offers/{id}/cancelCancel a DRAFT or PENDING offer — only the sender (fromSellerId) may cancel/v1/offers/{id}/counterCounter a PENDING offer — only the recipient may counter. Creates a brand-new offer with sender/recipient roles swapped and moves the original offer to COUNTERED; the two are linked only via the offer.countered event, not a foreign key.
/v1/reservationsAll-or-nothing lock across every listing on both sides of a trade session — a side is not RESERVED until every listing in its set is locked; one unavailable listing fails the whole side. Called by trade-session-service when advancing ACCEPTED -> RESERVING. See docs/architecture/trade-session-state-machine.md "Multi-item trades".
/v1/reservationsList reservations for a trade session/v1/reservations/releaseRelease every RESERVED reservation for a session back to ACTIVE — used on cancellation, expiry, or reservation/checkout failure. Only touches listings still RESERVED.
/v1/trade-sessionsList trade sessions for a seller (as either sellerA or sellerB). Trade sessions are always system-generated from an accepted offer, never created directly via this API.
/v1/trade-sessions/{id}Get a trade session/v1/trade-sessions/{id}/cancelCancel a trade session — only a party to the trade (sellerA or sellerB) may cancel, and only while the session is before LOCKED/FULFILLMENT/FULFILLED/COMPLETED/CANCELLED/ RETURNED/REFUNDED. Releases any RESERVED reservations as a side effect.
/v1/trade-sessions/{id}/scheduling/confirmPeer-to-peer trade completion (Phase 26) — either party confirms the exchange happened on their side. Once both sides have confirmed, the session moves to COMPLETED.
/v1/trade-sessions/{id}/scheduling/failEither party reports the peer-to-peer exchange failed (no-show, item mismatch)/v1/checkout/webhooks/paymentMerchant-facing payment status callback (mirrors the payment.completed/payment.failed webhook catalog entries). Reported completion of both sides' payments drives the trade session to LOCKED.
/v1/checkout/webhooks/fulfillmentMerchant-facing fulfillment status callback — started requires the session be LOCKED, completed requires FULFILLMENT/v1/checkout/trade-sessions/{id}/completeOps-triggered final completion once a trade session is FULFILLED — no automated signal exists yet for "both merchants confirm no open disputes/returns window", so this is the explicit manual interface for that step.
/v1/checkout/paymentsGet both sides' payment records for a trade session/v1/billing/subscriptionsCreate a Business's SaaS subscription/v1/billing/subscriptions/{businessId}Get a Business's current active SaaS subscription/v1/billing/subscriptions/{businessId}/change-tierChange a Business's subscription tier/v1/billing/subscriptions/{businessId}/cancelCancel a Business's subscription/v1/billing/usageRecord a metered usage event for a merchant (internal — called by other services, not typically by merchants directly)/v1/billing/usage/{businessId}A Business's current (or specified) billing-period metered usage, aggregated across every Merchant linked to it, including the cross-merchant multiplier breakdown and priced overage per event type. See docs/business/pricing.md.
/v1/billing/statements/{businessId}Consolidated Business billing statement — merchantPlan (owed) and spaceEarnings (already paid out, net of commission) as two separate sections, never merged into one number. See docs/business/conflict-resolution-log.md item 20.
/v1/notificationsList a marketplace member's in-app notifications. Every Seller has a User from creation (Phase 22), so this reaches every seller directly, in addition to their merchant notifying them through the merchant's own systems via Webhooks. See docs/business/glossary.md "Identity federation".
/v1/notifications/{id}/readMark a notification read/v1/webhooks/subscriptionsSubscribe to events. events is an array of event-type strings (e.g. offer.accepted) or ["*"] for every event. See docs/architecture/event-webhook-catalog.md for the full event/webhook catalog. The signing secret is returned once, at creation time.
/v1/webhooks/subscriptionsList a merchant's webhook subscriptions/v1/webhooks/subscriptions/{id}/disableDisable a webhook subscription (must be owned by the calling merchant)/v1/webhooks/deliveriesList delivery attempts, optionally scoped to one subscription/v1/webhooks/deliveries/{id}/replayReplay a delivery — must be idempotent on the merchant's receiving end, since the original attempt(s) may also have succeeded after all retries appeared exhausted.
/v1/webhooks/business-subscriptionsRegister a Business-rooted webhook subscription (Phase 34) — fires on Space booking lifecycle events (space_booking.created/consent_required/consented/paid/cancelled/completed).
/v1/webhooks/business-subscriptionsList a Business's webhook subscriptions/v1/webhooks/business-subscriptions/{id}/disableDisable a Business webhook subscription/v1/webhooks/business-deliveriesList Business webhook deliveries, optionally scoped to a subscription/v1/webhooks/business-deliveries/{id}/replayReplay a Business webhook delivery/v1/audit-logsList audit log entries, optionally scoped to a target/v1/moderation/flagsList moderation flags. listing-service's synchronous scanner already blocks a flagged write at the moment of sync — a flagged listing never reaches Postgres. These rows are a record of rejected attempts, useful for tuning the pattern list and handling merchant appeals.
/v1/moderation/flags/{id}Get a moderation flag/v1/moderation/flags/{id}/reviewOps review of a FLAGGED entry. Reviewing does not retroactively publish a listing — a confirmed false positive still requires the merchant to resubmit through Listings.
/v1/fraud/signalsList fraud signals (ops/internal read). Signals are detected automatically from windowed event counts (e.g. rapid offer creation, repeated moderation violations) — there is no endpoint to create one directly.
/v1/reputation/sellers/{id}Get a seller's reputation score (0-100). New sellers start at the neutral baseline of 50 — the same default @tbbn/core-matching's reputationMatch factor uses when reputation data is absent, so Matching and Reputation never disagree about what "no track record yet" means.
/v1/analytics/overviewGMV, trade volume, offer-acceptance match rate, and completion rate over a date range (default: trailing 30 days), optionally scoped to one merchant via its listings' involvement in offers/trade sessions.
/v1/featuresCreate or update a feature flag. Omit merchantId for a global (network-wide) flag; set it for a per-merchant override, which wins over the global value when both exist.
/v1/featuresList feature flags — global flags merged with a merchant's overrides when merchantId is supplied/v1/features/{key}/checkCheck whether a single flag is enabled, resolving a merchant override over the global default/v1/sandbox/merchantsSelf-serve sandbox provisioning — no manual application/approval flow, unlike a real merchant. Every call creates a brand-new isolated sandbox merchant + seller + API key, so trying the API never touches another developer's sandbox data. The API key is shown once.
/v1/sandbox/fixturesCanned example request payloads (listing sync, offer create, matching candidates) for docs-site's live "try it" widgets — real shapes matching each service's actual DTOsPlanned resources
Documented ahead of implementation so the target surface is visible — not yet live. See the OpenAPI workflow guide for how a resource graduates from here into the live spec above.