Skip to content

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

MethodPathNotes
POST/defi/1inchBody { path, query }. Appends referrer = 0x5222…1D35. Authorization: Bearer ONE_INCH_KEY
POST/defi/1inch/getspenderMaps to https://api.1inch.dev/swap/v6.0/1/approve/spender

Controller: oneinch.js. Excluded from the default swap fan-out.

OpenOcean

MethodPath
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

MethodPath
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

MethodPath
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

MethodPath
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

MethodPath
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

MethodPath
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

MethodPath
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

MethodPath
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:

MethodPathStep
POST/defi/rhino/quote1. Quote
POST/defi/rhino/commit/:quoteId2. Commit to it
GET/defi/rhino/calldata/:commitmentId3. Fetch calldata
POST/defi/rhino/deposit-addressesDeposit-address flow
GET/defi/rhino/deposit-addresses/:depositAddress/:depositChainDeposit status

RHINO_API_KEY, RHINO_API_URL. Controller: rhino.js.

OKX

MethodPath
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

MethodPath
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

MethodPath
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)

MethodPath
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

  1. Create controllers/defi/<provider>.js.
  2. Wire routes in routes/defi.routes.js.
  3. Add the env var to the VM's .env manually — the deploy does not carry it.
  4. In services/swap.service.js, decide default-include or default-exclude.
  5. In the SDK aggregator, call ${baseUrl}/<provider>/... instead of the provider URL.

Full checklist: add a liquidity provider.

Internal + developer documentation. Usage figures are point-in-time snapshots — re-verify before publishing them.