This page is the operational manual for integrating the RFQ API. Every rule here exists because a real maker has either de-prioritised, denylisted, or widened quotes for an integrator that violated it. Bebop’s liquidity providers are professional desks with their own risk systems. They observe per-source flow and reject patterns that look adversarial. If your integration follows these six rules, you’ll have stable access to the full liquidity surface. If it doesn’t, you’ll see degrading fill rates, sporadicDocumentation Index
Fetch the complete documentation index at: https://docs.bebop.xyz/llms.txt
Use this file to discover all available pages before exploring further.
InsufficientLiquidity errors, and eventually maker-level bans.
1. Don’t spam
Use the Price API stream for route estimation and sizing. Only call/quote once the stream tells you the trade is worth pursuing.
The stream gives you the full depth in real time, while the /quote endpoint is rate-limited per chain and per key precisely because it costs makers something to produce a firm quote.
2. Don’t cherry-pick quotes
A quote is valid for a specific moment in time. Caching a quote and re-evaluating it later, then executing only when the cached quote becomes more profitable than the live market, is toxic flow. Recommended pattern: request a quote at the moment you intend to execute. Use the live Price API stream for everything earlier in your decision pipeline.3. Don’t slice, use partial fills
Slicing means breaking a single fill intent into multiple smaller RFQ requests. There are two flavours of this, both of which makers detect and react to:- Multiple quotes for the same fill: requesting 5 ×
1M USDC → WETHquotes when you intend to fill5M USDC → WETHonce. - Multiple quotes for the same execution: requesting two independent
10M USDC → WETHquotes at the same time and executing both - whether bundled into one transaction or split across consecutive blocks. Each quote was priced against the maker’s full inventory. The first fills; the second reverts on-chain once that inventory is drawn down. Blocks land seconds apart and the maker’s liquidity does not replenish in that window, so submitting across separate blocks doesn’t help. Requesting both quotes at once is slicing regardless of how you submit them.
amountOut isn’t known until the swap executes - slippage, MEV and pool state move it. Request a quote for the maximum you may need, then partial-fill down to what the AMM actually returned. You get the same firm price regardless of the fill amount, avoiding a second round trip on the critical path.
4. Don’t probe unsupported tokens
Requesting quotes for tokens that aren’t supported on a given chain costs maker compute and signals an unfiltered taker. Use the/tokens endpoint with the isAvailable flag as the canonical liquidity check before requesting a quote.
5. Firm quote means 0% slippage
A Bebop quote is executable at the price you get until expiry. This matters when comparing Bebop quotes to AMM quotes in a routing decision. Don’t apply an “expected slippage” adjustment to the Bebop quote that you’d normally apply to a Uniswap quote.| Source | Returned price | What you actually receive |
|---|---|---|
| Bebop RFQ | Firm | Same as returned price (pre-execution) |
| AMM (Uniswap, etc.) | Mid-price estimate | Returned price minus slippage cost |
6. Pass origin so we can identify legitimate flow
The following four fields tell us who is really behind a quote request. Send the ones that match your integration shape - they feed abuse-prevention and market-maker reputation, so accuracy matters.| Field | Send when | Value |
|---|---|---|
taker_address | Always (required) | The address that will sign the order. |
origin_address | Your taker is not the end-user’s own wallet | The real end-user’s EOA. |
origin_target | The swap is executed by a contract on the user’s side | The to address of the resulting transaction. |
origin_source | You aggregate flow from multiple upstream sources | A stable identifier for the sub-source the request came from. |
taker_address is a real user wallet and there is no contract of yours in between: you don’t need any of the origin_* fields.
If you route through your own contract - taker_address is your settlement/router contract, so Bebop can’t see the real user from it. Send origin_address = the end-user’s EOA. Depending on your integration profile, Bebop may require origin_address on every request; if that applies to you we’ll tell you, and requests without it will be rejected.
If a contract executes the swap on the user’s side - additionally send origin_target = the to address of the resulting transaction (the contract that executes the swap). This is specifically the transaction target, not just any intermediate in your call path. Bebop screens this contract before forwarding the request.
If you aggregate flow from multiple upstream sources - additionally send origin_source = a stable, consistent identifier for the specific sub-source a request came from (e.g. one value for your own UI, a distinct value per downstream partner). This lets Bebop and market makers manage reputation per sub-source rather than treating your entire integration as one bucket - so one bad downstream partner doesn’t taint your good flow. It’s a free-text string; keep the values stable over time.
Summary checklist
Before going live, confirm:- You connect to the Price API stream and use it as the pre-quote filter
- You never cache a quote between issuance and execution
- You request one quote per intended fill (use partial fills for flex sizing)
- You only execute one quote for the same fill (token pair) per transaction
- You only request quotes for tokens with
isAvailable=true - You compare Bebop’s firm quote to AMM quotes net of expected AMM slippage
- You pass the real end-user address