Appearance
Fiat on/off-ramp API
Five providers, all under /api/defi. Blazpay charges nothing here; each provider's own spread applies and the UI compares them.
Product page: buy / sell.
Unified quote comparison
| Method | Path | Controller |
|---|---|---|
POST | /defi/on-off-ramp-quotes | services/buy.js → buyQuotes |
Queries every integrated ramp in parallel and returns the resulting crypto amount from each. Per-provider failures are caught and logged rather than failing the whole comparison — the user sees fewer options, not an error.
Chain and country maps live in bz-backend/utils/onRampConst.js (onRampChain, onrampCountries).
OnRamp.money
The India rail — INR via UPI, IMPS and bank transfer, with no international card needed.
| Method | Path | Purpose |
|---|---|---|
POST | /defi/onramp/quotes | Quote |
GET | /defi/onramp/save-crypto | Admin — refresh the crypto catalogue into onRampCrypto |
GET | /defi/onramp/save-fiat | Admin — refresh fiat types |
GET | /defi/onramp/assign | Assign a reference for webhook correlation |
POST | /defi/onramp/setWebhook | Register the webhook URL with OnRamp |
POST | /defi/onramp/webhook | Receive status callbacks |
SECRET_KEY_ONRAMP. Controller: onRampController.js.
Changelly (fiat)
| Method | Path | Purpose |
|---|---|---|
POST | /defi/changelly/quotes | Quote |
POST | /defi/changelly/crypto-list | Currency list |
POST | /defi/changelly/webhook-url | Register webhook |
GET | /defi/changelly/save-crypto | Admin — refresh changellyCrypto |
GET | /defi/changelly/save-fiat | Admin — refresh changellyFiat |
GET | /defi/changelly/assign | Assign a crypto reference |
GET | /defi/changelly/assign-fiat | Assign a fiat reference |
CHANGELLY_PRIVATE_KEY / PRIVATE_KEY_CHANGELLY for request signing. Controller: changellyFiat.js.
Changelly's instant crypto-to-crypto endpoints are separate (POST /defi/changelly, POST /defi/changelly/transaction) and documented under provider proxies.
AlchemyPay
| Method | Path | Purpose |
|---|---|---|
POST | /defi/alchemy/quotes | Quote |
POST | /defi/alchemy/sign | Sign a payload for AlchemyPay's checkout |
GET | /defi/alchemy/save-crypto | Admin — refresh alchemyCrypto |
GET | /defi/alchemy/save-fiat | Admin — refresh alchemyFiat |
GET | /defi/alchemy/assign | Assign a crypto reference |
GET | /defi/alchemy/assign-fiat | Assign a fiat reference |
GET | /defi/alchemy/webhook | Status callback |
SECRET_KEY_ALCHEMY. Controller: alchemyController.js.
Transak
| Method | Path | Purpose |
|---|---|---|
GET | /defi/transak | Currency list; also refreshes transacCrypto / transacFiat |
GET | /defi/transak/assign | Assign a reference (transaction.controller.js → assignTokensTransac) |
Controller: transak.js. The frontend also uses @transak/transak-sdk directly for the widget.
MoonPay
| Method | Path | Purpose |
|---|---|---|
GET | /defi/moonpay | Currency list |
Controller: moonPay.js.
Patterns worth knowing
Reference assignment
Every provider needs a reference so its webhook can be correlated back to a Blazpay order. Hence the assign* endpoint pairs above. Without one, a completed purchase cannot be attributed.
Catalogue caching
Provider catalogues (which tokens on which chains, which fiat currencies) are cached in Mongo rather than queried live:
| Collection | Refreshed by |
|---|---|
alchemyCrypto, alchemyFiat | GET /defi/alchemy/save-crypto, /save-fiat |
changellyCrypto, changellyFiat | GET /defi/changelly/save-crypto, /save-fiat |
onRampCrypto | GET /defi/onramp/save-crypto |
transacCrypto, transacFiat | GET /defi/transak |
There is no refresh cron
A newly listed token on a provider does not appear in Blazpay until someone calls the corresponding save-* endpoint. "Provider X supports token Y but Blazpay does not offer it" is almost always a stale catalogue, not a missing integration.
These are GET requests that mutate
GET /defi/alchemy/save-crypto writes to the database. They are administrative endpoints with no auth. Do not infer safety from the verb — see conventions.
Order records
Orders are persisted in models/buySellOrders.js. The Blazpay-side record is created through POST /defi/order/create or POST /defi/order, and read with GET /defi/order/:walletAddress.
Currency coverage
20+ fiat currencies:
INR USD EUR GBP AED TRY MXN VND NGN BRL
PEN COP CLP PHP IDR KES ZAR THB MYR ARSThe emerging-market entries — VND, NGN, KES, IDR, PHP, COP, PEN, CLP — are the differentiated ones. Off-ramp coverage is narrower than on-ramp for several of these corridors.
In BlazAI
The BUY intent returns action buy_sell, rendered by swapAI/buy/BuyQuoteContainer. So a user can say "buy 10000 rupees of bitcoin" and get the same provider comparison inline. See intent catalogue.
Failure modes
| Symptom | Cause |
|---|---|
| A provider missing from the comparison | Its quote call failed; errors are caught and logged per provider |
| A token the provider supports is not offered | Stale catalogue — call the relevant save-crypto endpoint |
| A completed purchase not reflected | Reference not assigned, or webhook not registered |
| KYC stuck | Provider-side. Blazpay holds no identity documents and cannot resolve it |
| Off-ramp unavailable for a currency | That provider does not support that direction for that corridor |