Appearance
Provider proxy API
Passthrough endpoints for providers that need a secret key or a registered referrer. They exist so nothing key-bearing ships in a browser bundle.
All under /api/defi. Controllers in bz-backend/controllers/defi/.
These are called by swap-sdk, not by the frontend directly
An aggregator class in the SDK hits ${baseUrl}/1inch (etc.) rather than the provider's own API. baseUrl is https://api.blazpay.com/api/defi by default. That means the same SDK code runs in the browser and on the server without leaking keys.
1inch
| Method | Path | Notes |
|---|---|---|
POST | /defi/1inch | Body { path, query }. Appends referrer = 0x5222…1D35. Authorization: Bearer ONE_INCH_KEY |
POST | /defi/1inch/getspender | Maps to https://api.1inch.dev/swap/v6.0/1/approve/spender |
Controller: oneinch.js. Excluded from the default swap fan-out.
OpenOcean
| Method | Path |
|---|---|
POST | /defi/openocean |
Proxies https://open-api-pro.openocean.finance/v3/:chain/swap_quote with apikey (OPEN_OCEAN_API_KEY) and OPEN_OCEAN_REFERRER.
OpenOcean also supplies gas prices
Base.getGasPrice(chainId) in the SDK calls OpenOcean's v4 gasPrice endpoint, sending apikey when openOceanApiKey is configured. So OpenOcean matters even though it is excluded from the default fan-out.
Unizen
| Method | Path |
|---|---|
POST | /defi/unizen/quotes |
POST | /defi/unizen/swap |
POST | /defi/unizen/spender |
Proxies https://api.zcx.com/trade/v1/:chain/{quote|swap}/{single|cross} and /approval/spender with X-Api-Key: UNIZEN_API_KEY. Controller: unizen.controller.js.
Unizen supports a narrower chain set than Blazpay — ChainIdUnizen in the SDK constants: 1, 10, 56, 137, 250, 8453, 42161, 43114.
Squid Router
| Method | Path |
|---|---|
POST | /defi/squidrouter |
GET | /defi/squidrouter/status |
Proxies https://apiplus.squidrouter.com/v2/route with x-integrator-id: blazpay-db534a27-fefd-4504-b5bd-a7e6407bd656 (hardcoded, not an env var). Controller: squidRouter.js.
Odos
| Method | Path |
|---|---|
POST | /defi/odos/quote |
POST | /defi/odos/assemble |
Two-step: quote, then assemble calldata. ODOS_API_KEY. Controller: odos.js.
Odos' assemble endpoint 500s intermittently
This is the main reason the execution engine tries the top five quotes rather than only the best one.
Across
| Method | Path |
|---|---|
GET | /defi/across/quote |
GET | /defi/across/status |
ACROSS_API_KEY, ACROSS_INTEGRATOR_ID. Controller: across.js. Bridge only, usually the fastest for supported pairs.
Near 1Click
| Method | Path |
|---|---|
GET | /defi/near-1click/tokens |
POST | /defi/near-1click/quote |
GET | /defi/near-1click/status |
NEAR_1CLICK_API_KEY. Controller: near1click.js. NEAR intents; bridge only.
Relay
| Method | Path |
|---|---|
POST | /defi/relay/quote |
GET | /defi/relay/status |
RELAY_API_KEY. Controller: relay.js.
Relay is an intent solver — unusable for automation
It returns token-transfer calldata and a solver fills the order afterwards, so zero output arrives inside the transaction. The DCA and Autopilot vaults measure the balance delta and revert with OutputBelowMinimum. The route probe filters it out. Fine for interactive bridging where the user watches a status poll.
GasZip
| Method | Path |
|---|---|
GET | /defi/gas-zip/quote |
GET | /defi/gas-zip/status |
GASZIP_API_URL. Controller: gaszip.js. Purpose-built for small native top-ups when a user arrives on a chain with no gas.
RhinoFi
Multi-step, unlike every other provider:
| Method | Path | Step |
|---|---|---|
POST | /defi/rhino/quote | 1. Quote |
POST | /defi/rhino/commit/:quoteId | 2. Commit to it |
GET | /defi/rhino/calldata/:commitmentId | 3. Fetch calldata |
POST | /defi/rhino/deposit-addresses | Deposit-address flow |
GET | /defi/rhino/deposit-addresses/:depositAddress/:depositChain | Deposit status |
RHINO_API_KEY, RHINO_API_URL. Controller: rhino.js.
OKX
| Method | Path |
|---|---|
GET | /defi/okx/quote |
GET | /defi/okx/swap |
GET | /defi/okx/approve-transaction |
OKX_API_KEY, OKX_SECRET_KEY, OKX_PASSPHRASE, OKX_PROJECT_ID, OKX_API_URL — OKX requires a signed request, hence four values. Controller: okx.js.
OKX reports usdAmount: 0
Which makes the platform-fee display read $0 unless the price enrichment in swap.service.js succeeds. Nordstern has the same behaviour.
Uniswap
| Method | Path |
|---|---|
POST | /defi/uniswap/quote |
POST | /defi/uniswap/swap |
UNISWAP_API_KEY, UNISWAP_API_URL. Controller: uniswap.js.
UNISWAP_API_KEY had to be added to the VM manually
.env is excluded from the rsync deploy, so a new provider key does not travel with the code. This is the canonical example of that trap. See deploy backend.
ChangeNow
| Method | Path |
|---|---|
POST | /defi/change-now/quotes |
POST | /defi/change-now/swap |
CHANGE_NOW_API_KEY. Controller: changeNow.js. Currently not registered in the SDK's TradeManager.
Changelly (instant swap)
| Method | Path |
|---|---|
POST | /defi/changelly |
POST | /defi/changelly/transaction |
Requires request signing with CHANGELLY_PRIVATE_KEY. Controller: changelly.js. Changelly's fiat endpoints are separate — see fiat API.
Direct-call providers
No proxy needed; the SDK calls them straight:
LiFi · Butter Network · KyberSwap · Symbiosis · Nordstern · SushiSwap · Rango · deBridge · XY Finance · Houdini
Some still take a key, injected via configure() rather than proxied: RANGO_API_KEY, HOUDINI_API_KEY.
SDK configuration
services/swap.service.js calls configure() at module load:
js
configure({
openOceanApiKey: process.env.OPEN_OCEAN_API_KEY,
unizenApiKey: process.env.UNIZEN_API_KEY,
baseApiUrl: process.env.SWAP_SDK_BASE_URL,
rangoApiKey: process.env.RANGO_API_KEY,
houdiniApiKey: process.env.HOUDINI_API_KEY,
})Server-side, the SDK is configured with keys directly
Which means server-side quoting can hit Rango and Houdini without a proxy hop. In the browser those two work only because their APIs accept a public/referrer-style key. Anything that must stay secret gets a proxy endpoint.
Adding a proxy
- Create
controllers/defi/<provider>.js. - Wire routes in
routes/defi.routes.js. - Add the env var to the VM's
.envmanually — the deploy does not carry it. - In
services/swap.service.js, decide default-include or default-exclude. - In the SDK aggregator, call
${baseUrl}/<provider>/...instead of the provider URL.
Full checklist: add a liquidity provider.