Offers and breakdowns
An offer is a merchant’s executable terms for a trade. A breakdown is Sinbad’s priced, time-limited quote for one offer, and it carries the prepared transaction that funds the trade. A breakdown saves the terms but does not create a trade: a trade exists only after funding is confirmed on chain.
Find matching offers
Call POST /v1/offers/best with the customer’s side (BUY or SELL), the token, the fiat currency, an amount and the catalog payment method. The amount has a mode and a value:
- With
mode: "FIAT",valueis the market value of the token in the selected fiat currency, before merchant margin and fees. Sinbad converts it to USDT at the current market rate, rounded down to six decimals. The final fiat payment includes merchant pricing and fees, so it can differ from the amount entered. - With
mode: "USDT",valueis an exact token quantity.
paymentMethodId is required. On a SELL, always send savedPaymentMethodId to choose the receiving account. If you omit it, Sinbad selects the customer’s first active matching account.
The response contains one instant offer or up to three alternatives. Each offer includes pricing, display data and a breakdownInput. New fiat searches return a canonical USDT amount in breakdownInput, so the token quantity stays the same through checkout. A closest-amount suggestion can change that quantity.
If no inventory matches, or the amount is outside every listing’s limits, the call returns 200 with empty results. If the only match is a listing that uses the customer’s own wallet, it fails with 400 VALIDATION_ERROR and details.reason: "SELF_TRADE_NOT_ALLOWED".
How offers are chosen
- Trading hours. Sinbad checks a merchant’s hours only when you send
scheduled_at. SettingignoreTradingHourstotruebypasses that check for exact and alternative offers. A merchant’s online status is checked independently. - Merchant preference. Exact offers prefer merchants who are not busy and whose effective margin is at most 2%. If no such merchant exists, Sinbad can fall back to busy merchants or higher margins. Alternatives keep the 2% cap and the workload exclusions.
- Merchant details. Offers, alternatives and breakdowns include the merchant’s
fullName,avatarUrl,username,ratingPercent,tradeCount,isSuperMerchantandexperienceYears. A breakdown snapshots these values when it is created. Trade history keeps its existing name and avatar display. - Display amounts.
displayCalculationModeisDUMMYby default, which shows the Card and Sheet values for a fixed 10 USD example. ChooseREALto show the actual requested or suggested amount. Keep the returnedbreakdownInputunchanged either way, because pricing, breakdowns and transactions always use the actual amount.
Create the breakdown
Call POST /v1/trade-breakdowns with the chosen offer’s breakdownInput, unchanged, and an Idempotency-Key header. Sinbad rechecks the current price, fees, availability and eligibility, then returns the exact terms in tradeDetails and the prepared escrowTransaction. Show tradeDetails to the customer before they sign.
Repeating the call with the same key and body returns the same breakdown and the same deadline. A different body with the same key returns 409 CONFLICT.
A breakdown has a fixed signing window of 300 seconds (5 minutes) from creation. Reading it does not extend the window.
Review before signing
Read the breakdown again with GET /v1/trade-breakdowns/{breakdownId} to check its status. If a SELL needs a token approval, call POST /v1/trade-breakdowns/{breakdownId}/approval and confirm each approval before the customer signs the escrow transaction. See Sell walkthrough.
One open trade per side
Each customer can have one open BUY and one open SELL at a time, scoped to your partner and that customer. Creating a breakdown holds the customer’s place on its side without creating a funded trade. Funding then carries that place into the trade.
Refresh a price by replacing the breakdown
To get a fresh price, create another breakdown on the same side with a new Idempotency-Key. If no escrow transaction has been reported for the earlier breakdown, Sinbad replaces it and returns a new escrowTransaction in the same response. Always sign from the latest response.
After a breakdown is replaced:
- Reading it, or repeating its original
Idempotency-Key, returns409 CONFLICT. - Repeating the key of the current breakdown, with the same body, returns that breakdown with its original deadline.
When creating a breakdown fails
If the earlier breakdown’s escrow transaction was already submitted, funded or put under review (REVIEW_REQUIRED), the new request fails with 409 CONFLICT and details.reason: "ACTIVE_TRADE_EXISTS". Show the customer their existing trade instead of asking again.
When the customer’s place is released
Sinbad releases the customer’s place on a side when:
- the trade reaches a final status (
RELEASEDorCANCELED), - the customer opens a dispute, or
- the breakdown expires without being funded.
A dispute that the merchant opens does not release it. If an escrow transaction was reported for the breakdown, Sinbad releases the place only after it confirms on chain that the breakdown expired. That can happen shortly after the 300-second deadline.
Replacing a breakdown does not cancel an escrow transaction that the customer’s wallet has already sent. That transaction can still fund a trade until its original deadline, and it creates its own trade with its original pricing. Keep reporting the hash of every transaction you sent to POST /v1/transactions. Never request a replacement while a wallet send is pending or its outcome is unknown, including before you have reported its hash.
If a replaced breakdown is funded anyway, reading it returns CONFIRMED with its original pricing. It has no new escrowTransaction or approval transactions to sign.
Related
- Buy walkthrough and Sell walkthrough for the full flows.
- Limits and limitations for the shared offer and breakdown rate limit.
- Errors and recovery for every error code.