Integrating the Binance API with Lovable uses Edge Functions to proxy authenticated REST requests with HMAC-SHA256 signed parameters, keeping your API key and secret in Cloud Secrets. Public market data endpoints (prices, order books) can be called from the frontend without authentication. For account data and trading, all requests run server-side through Edge Functions. Real-time price feeds use a WebSocket proxy pattern through the Edge Function layer.
Why integrate Binance API with Lovable?
Binance is the world's largest cryptocurrency exchange by trading volume, processing over $50 billion in daily trades as of 2026. Its REST API and WebSocket streams provide comprehensive access to real-time price data for 500+ trading pairs, historical OHLCV candlestick data, order book depth, and — for authenticated users — portfolio balances and trade history. If you're building a crypto dashboard, portfolio tracker, trading analytics tool, or any app that needs reliable cryptocurrency market data, the Binance API is the most comprehensive free source available.
From a Lovable developer's perspective, Binance's API has two distinct access tiers. Public endpoints (market data, prices, order books, candlesticks) require only an API key in the request header and can technically be called from the frontend — however, routing through Edge Functions is still best practice to avoid CORS issues and rate limit management. Authenticated endpoints that access account-specific data (balances, orders, trade history) require HMAC-SHA256 request signing with a timestamp and a secret key that must never be exposed in browser code.
The HMAC signing requirement is what makes Edge Functions essential for account-level Binance integration. The signature is computed from the query parameters plus the current timestamp using your API secret — this calculation must happen server-side. Building a crypto dashboard that shows live prices is relatively straightforward; adding portfolio tracking tied to a real Binance account requires careful implementation of the signing logic covered in this tutorial.
Integration method
The Binance API has no native Lovable connector. Public market data endpoints can be called directly from the frontend since they require no authentication. All authenticated endpoints — account balances, trade history, and order placement — require HMAC-SHA256 request signing using your API secret, which must be done in a server-side Edge Function with credentials stored in Cloud Secrets. WebSocket price streams are proxied through Edge Functions to avoid CORS and key exposure.
Prerequisites
- A Lovable project with Cloud enabled
- A Binance account — sign up at binance.com (full registration not required for public market data)
- A Binance API key and secret (required for account data access) — create at binance.com → Account → API Management
- API key permissions: for a read-only portfolio tracker, enable 'Read Info' only. Never enable 'Enable Trading' or 'Enable Withdrawals' unless your app genuinely needs those capabilities.
- Understanding that Binance API access may be restricted in some jurisdictions — check local regulations before building trading features
Step-by-step guide
Create a Binance API key with appropriate permissions
Create a Binance API key with appropriate permissions
Log in to binance.com. In the top-right area, click your profile icon, then select 'API Management'. Click 'Create API'. Binance offers two API types: 'System Generated' (standard HMAC authentication) and 'Self-Generated' (for ED25519 keys). Select 'System Generated' for this tutorial — it's the most compatible with standard HMAC implementations. Give your API key a memorable label like 'Lovable Portfolio App'. Binance may require 2FA verification. After creation, you'll see both the API Key and Secret Key — critically, the Secret Key is shown only once. Copy it immediately and store it somewhere safe before closing the page. On the API key settings page, configure the permissions carefully based on what your app needs. For a read-only portfolio tracker or price dashboard, enable only 'Enable Reading' — this allows fetching account balances and trade history but cannot place orders or withdraw funds. Do not enable 'Enable Spot & Margin Trading' or 'Enable Withdrawals' unless your app specifically needs them, as these permissions represent significant financial risk if the API key is ever compromised. For an extra layer of security, restrict the API key to specific IP addresses. Your Lovable app's Edge Functions run from Supabase's infrastructure — you can find the IP ranges in your Supabase project settings under 'Database → Connection' or 'Project Settings'. IP restriction means the key is useless even if stolen.
Pro tip: Never enable withdrawal permissions on an API key used in any application. Even a read-only compromise is serious, but a key with withdrawal permissions is catastrophic. Use the minimum permissions necessary for your use case.
Expected result: You have a Binance API Key and Secret Key saved. The key has only 'Enable Reading' permission enabled. The Secret Key is stored securely before closing the Binance page.
Store Binance credentials in Lovable Cloud Secrets
Store Binance credentials in Lovable Cloud Secrets
Open your Lovable project and click the '+' button in the top-right editor area to access panels. Select 'Cloud', then expand the 'Secrets' section. Add your credentials as encrypted environment variables. Add BINANCE_API_KEY with your API Key value (the non-secret identifier). Add BINANCE_API_SECRET with your Secret Key value. Add BINANCE_BASE_URL with value 'https://api.binance.com' — this lets you switch to testnet (https://testnet.binance.vision) for testing order placement without using real funds. For public market data, you could optionally use 'https://api1.binance.com' or 'https://api2.binance.com' as alternative endpoints if the primary is slow. Binance's API secret is used to compute HMAC-SHA256 signatures for authenticated requests. This computation must happen in your Edge Function, never in the browser. The API key itself is sent as an X-MBX-APIKEY header in every authenticated request, which is also handled in the Edge Function. Note: for public market data endpoints (price tickers, order books, candlesticks), no API key or secret is required. These can be called directly from the frontend or through an Edge Function without any secrets. The credentials are only needed for the authenticated account endpoints covered in Step 4.
Pro tip: Binance rate limits are per API key. The standard weight limit is 1,200 request weight per minute. Each endpoint has a different weight (most basic endpoints are weight 1, but account info is weight 20). Monitor your usage in Cloud Logs to avoid hitting limits that could block all requests for several minutes.
Expected result: BINANCE_API_KEY, BINANCE_API_SECRET, and BINANCE_BASE_URL appear in Cloud Secrets. No credentials appear in any source code file.
Create the public market data Edge Function
Create the public market data Edge Function
Public Binance market data endpoints don't require authentication, but routing through an Edge Function avoids CORS issues and lets you cache results, rate limit calls from multiple users, and add your own data transformation logic. Create an Edge Function for common market data queries. The most useful public endpoints are: /api/v3/ticker/24hr for 24-hour price statistics (price, change, volume, high, low), /api/v3/ticker/price for simple current price by symbol, /api/v3/klines for candlestick data (OHLCV) with configurable intervals (1m, 5m, 1h, 1d, etc.), and /api/v3/depth for order book data showing bids and asks. Design the Edge Function to accept a symbol parameter and an action parameter so one function handles multiple data types. For example, action='ticker' fetches the 24hr ticker for a given symbol, action='price' fetches just the current price, and action='klines' fetches candlestick data with a specified interval and limit. For displaying multiple symbols (like a price watchlist), the /api/v3/ticker/24hr endpoint accepts either no symbol (returns all tickers, ~500+ entries) or a symbols parameter with a JSON-encoded array. Fetch only the symbols you need to minimize bandwidth and processing.
Create a Supabase Edge Function at supabase/functions/binance-market/index.ts. Use BINANCE_BASE_URL from Deno.env. Support these actions via POST body: action='ticker' fetches /api/v3/ticker/24hr for a given symbol and returns price, priceChangePercent, volume, highPrice, lowPrice; action='prices' fetches current prices for an array of symbols using /api/v3/ticker/price with the symbols parameter; action='klines' fetches candlestick data for a symbol, interval (e.g. '1h'), and limit (e.g. 100) from /api/v3/klines. Add CORS headers. No authentication required for these endpoints.
Paste this in Lovable chat
1// supabase/functions/binance-market/index.ts2import { serve } from "https://deno.land/std@0.168.0/http/server.ts";34const BASE_URL = Deno.env.get("BINANCE_BASE_URL") ?? "https://api.binance.com";5const corsHeaders = {6 "Access-Control-Allow-Origin": "*",7 "Access-Control-Allow-Methods": "POST, OPTIONS",8 "Access-Control-Allow-Headers": "Content-Type, Authorization",9};1011serve(async (req) => {12 if (req.method === "OPTIONS") return new Response(null, { headers: corsHeaders });1314 try {15 const { action, symbol, symbols, interval, limit } = await req.json();1617 let url = "";18 if (action === "ticker") {19 url = `${BASE_URL}/api/v3/ticker/24hr?symbol=${symbol}`;20 } else if (action === "prices") {21 const encoded = encodeURIComponent(JSON.stringify(symbols));22 url = `${BASE_URL}/api/v3/ticker/price?symbols=${encoded}`;23 } else if (action === "klines") {24 url = `${BASE_URL}/api/v3/klines?symbol=${symbol}&interval=${interval ?? "1h"}&limit=${limit ?? 100}`;25 } else {26 return new Response(JSON.stringify({ error: "Unknown action" }), { status: 400, headers: corsHeaders });27 }2829 const res = await fetch(url);30 if (!res.ok) {31 const err = await res.json();32 return new Response(JSON.stringify(err), { status: res.status, headers: { ...corsHeaders, "Content-Type": "application/json" } });33 }34 const data = await res.json();35 return new Response(JSON.stringify(data), { headers: { ...corsHeaders, "Content-Type": "application/json" } });36 } catch (err) {37 return new Response(JSON.stringify({ error: err.message }), {38 status: 500,39 headers: { ...corsHeaders, "Content-Type": "application/json" },40 });41 }42});Pro tip: The Binance /api/v3/klines endpoint returns data as arrays rather than objects. Each element is [openTime, open, high, low, close, volume, closeTime, quoteVolume, numTrades, takerBuyBaseVolume, takerBuyQuoteVolume, ignore]. Map these to named properties in your Edge Function or frontend component for readability.
Expected result: The binance-market Edge Function is deployed. Calling it with action='prices' and symbols=['BTCUSDT','ETHUSDT'] returns current prices for both pairs. Calling action='klines' with symbol='BTCUSDT', interval='1h', limit=24 returns 24 hours of hourly candlestick data.
Create the authenticated account data Edge Function
Create the authenticated account data Edge Function
For account balances and trade history, Binance requires HMAC-SHA256 signed requests. The signing process works as follows: construct the query parameters string (including a timestamp parameter set to the current UTC time in milliseconds), compute an HMAC-SHA256 hash of this string using your API secret as the key, append the resulting signature to the query string, and include your API key in the X-MBX-APIKEY header. Deno has built-in Web Crypto API support that handles HMAC-SHA256 without any external dependencies. The key steps in the Edge Function are: get the current timestamp, build the parameter string, sign it with your secret, and make the authenticated request. The main authenticated endpoints for a portfolio tracker are: GET /api/v3/account (returns all balances including non-zero assets), GET /api/v3/myTrades (trade history for a specific symbol, requires symbol parameter), and GET /api/v3/openOrders (currently open orders). Store only the aggregated portfolio data in Supabase (total value, asset allocations by percentage) rather than raw account data. The access tokens pattern from Plaid doesn't apply here — each user of your Binance-connected app would need to provide their own API key and secret, which you'd store encrypted in their user profile. For a personal portfolio tracker (single user), your own API key in Cloud Secrets is sufficient.
Create a Supabase Edge Function at supabase/functions/binance-account/index.ts. It should read BINANCE_API_KEY, BINANCE_API_SECRET, and BINANCE_BASE_URL from Deno.env. Support two actions: action='balances' calls GET /api/v3/account with HMAC-SHA256 signature and returns non-zero asset balances as an array of {asset, free, locked}; action='trades' calls GET /api/v3/myTrades with a required symbol parameter and returns recent trades. Use Deno's built-in crypto.subtle for HMAC-SHA256 signing. Include the X-MBX-APIKEY header and sign the timestamp parameter.
Paste this in Lovable chat
1// supabase/functions/binance-account/index.ts2import { serve } from "https://deno.land/std@0.168.0/http/server.ts";34const BASE_URL = Deno.env.get("BINANCE_BASE_URL") ?? "https://api.binance.com";5const API_KEY = Deno.env.get("BINANCE_API_KEY") ?? "";6const API_SECRET = Deno.env.get("BINANCE_API_SECRET") ?? "";7const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "POST, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization" };89async function sign(queryString: string): Promise<string> {10 const key = await crypto.subtle.importKey(11 "raw",12 new TextEncoder().encode(API_SECRET),13 { name: "HMAC", hash: "SHA-256" },14 false,15 ["sign"]16 );17 const sig = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(queryString));18 return Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, "0")).join("");19}2021serve(async (req) => {22 if (req.method === "OPTIONS") return new Response(null, { headers: corsHeaders });23 try {24 const { action, symbol } = await req.json();25 const timestamp = Date.now();2627 if (action === "balances") {28 const qs = `timestamp=${timestamp}`;29 const signature = await sign(qs);30 const res = await fetch(`${BASE_URL}/api/v3/account?${qs}&signature=${signature}`, {31 headers: { "X-MBX-APIKEY": API_KEY },32 });33 const data = await res.json();34 if (data.code) throw new Error(data.msg);35 const nonZero = (data.balances ?? []).filter((b: any) => parseFloat(b.free) > 0 || parseFloat(b.locked) > 0);36 return new Response(JSON.stringify({ balances: nonZero }), { headers: { ...corsHeaders, "Content-Type": "application/json" } });37 }3839 if (action === "trades") {40 const qs = `symbol=${symbol}×tamp=${timestamp}&limit=50`;41 const signature = await sign(qs);42 const res = await fetch(`${BASE_URL}/api/v3/myTrades?${qs}&signature=${signature}`, {43 headers: { "X-MBX-APIKEY": API_KEY },44 });45 const data = await res.json();46 if (data.code) throw new Error(data.msg);47 return new Response(JSON.stringify({ trades: data }), { headers: { ...corsHeaders, "Content-Type": "application/json" } });48 }4950 return new Response(JSON.stringify({ error: "Unknown action" }), { status: 400, headers: corsHeaders });51 } catch (err) {52 return new Response(JSON.stringify({ error: err.message }), { status: 500, headers: { ...corsHeaders, "Content-Type": "application/json" } });53 }54});Pro tip: The Binance API requires the timestamp parameter to be within 5,000 milliseconds of the server time (configurable via recvWindow parameter, max 60,000ms). If your Edge Function environment clock drifts, requests will fail with error code -1021 'Timestamp for this request is outside of the recvWindow'. Call GET /api/v3/time to check Binance's server time if you suspect clock drift.
Expected result: The binance-account Edge Function is deployed. Calling it with action='balances' returns your Binance account's non-zero asset balances as structured JSON.
Build the portfolio dashboard frontend
Build the portfolio dashboard frontend
With both Edge Functions deployed, build the portfolio tracker UI in Lovable. The dashboard should combine account balance data from the binance-account function with current prices from the binance-market function to calculate USD values for each holding. Design the component to load on mount by calling both functions in parallel — account balances and current prices for the held assets. Map each balance to its current price to calculate position values. Sort by position value descending. Display in a table with columns: Asset, Holdings, Current Price, USD Value. Add a pie chart component showing portfolio allocation percentages. For the price data, batch the symbol requests efficiently. If you hold BTC, ETH, and SOL, fetch BTCUSDT, ETHUSDT, and SOLUSDT prices in a single /api/v3/ticker/price request with the symbols array rather than making separate calls for each. This reduces API calls and stays within Binance's rate limits more efficiently. Add a manual refresh button and display the last-updated timestamp. For a production app, you might refresh prices every 30 seconds and balances every 5 minutes (account data is less time-sensitive and has higher weight costs).
Build a cryptocurrency portfolio dashboard that loads on the /portfolio page. On load: 1) call the binance-account Edge Function with action='balances' to get held assets, 2) call the binance-market Edge Function with action='prices' and the symbols array (e.g. BTCUSDT, ETHUSDT) to get current prices, 3) calculate USD value for each holding by multiplying quantity by price, 4) display in a sortable table: Asset name, Holdings (quantity), Current Price (USD), USD Value. Show total portfolio value at the top. Add a pie chart showing allocation percentages. Add a Refresh button that re-fetches both data sources.
Paste this in Lovable chat
Pro tip: Many Binance assets have both USDT and BUSD pairs. Use USDT pairs (e.g., BTCUSDT) for USD value calculations as BUSD is being phased out. Stablecoins like USDT and USDC can be priced at $1.00 directly without an API call.
Expected result: The portfolio dashboard displays your Binance holdings with current prices and USD values. A pie chart shows allocation. Clicking Refresh re-fetches both balances and prices.
Common use cases
Cryptocurrency price dashboard with real-time updates
A founder building a crypto analysis tool wants to display live prices, 24-hour price changes, and trading volume for a watchlist of cryptocurrencies. The Binance Ticker API provides all this data for hundreds of trading pairs in a single request. An Edge Function fetches updated ticker data on a polling interval and the frontend displays it in a sortable table with color-coded price movements.
Build a cryptocurrency price dashboard. Create an Edge Function that fetches 24hr ticker data from the Binance API for BTC, ETH, SOL, BNB, and MATIC against USD. Return price, price_change_percent, volume, and high/low for each. Display the data in a table with green/red color coding based on price change. Auto-refresh every 10 seconds. Save the current prices to a price_history table in Supabase every minute.
Copy this prompt to try it in Lovable
Personal portfolio tracker connected to Binance account
A developer wants a custom portfolio view showing their Binance spot holdings with current USD values, weighted average buy prices, and P&L calculations. The Edge Function fetches the user's account balances via the authenticated Binance API, multiplies each asset quantity by the current market price, and returns a structured portfolio summary that the frontend renders as charts and tables.
Create a portfolio tracker that connects to my Binance account. The Edge Function should use my Binance API key and secret to fetch my spot account balances, filter out assets with zero balance, fetch current prices for each held asset from Binance, calculate USD value for each position, and return a sorted list by value. Display a pie chart of portfolio allocation and a table showing asset, quantity, current price, and total value.
Copy this prompt to try it in Lovable
Trading signal alerts with Binance candlestick data
A quantitative trader wants to set up automated alerts when specific technical conditions are met — for example, when the RSI for BTC drops below 30 or when price crosses a moving average. Edge Functions fetch candlestick data from the Binance Klines endpoint, run the indicator calculations, and store alert triggers in Supabase. A Supabase Edge Function scheduled job checks conditions and sends alerts via Resend email.
Create a trading alert system using Binance kline data. Build an Edge Function that fetches 1-hour BTCUSDT candlestick data for the last 14 periods from Binance, calculates the RSI, and saves the result to a signals table in Supabase. Add a UI page where I can set an alert threshold (e.g., RSI below 30) and an email address. Use Supabase Edge Functions scheduled triggers to run the check every hour and send an email via Resend when the threshold is crossed.
Copy this prompt to try it in Lovable
Troubleshooting
Authenticated API calls fail with error code -1022 'Signature for this request is not valid'
Cause: The HMAC-SHA256 signature is being computed incorrectly. Common causes are: signing the URL with query parameters that don't match exactly what's being sent, including the signature parameter itself in the signed string, or using the wrong encoding (hex required, not base64).
Solution: Ensure the query string being signed contains only the parameters you're sending, without the signature itself, in the exact same order and encoding as they appear in the request URL. The signature should be the final parameter appended after the signed string. Use lowercase hex encoding for the signature bytes.
1// Correct: sign the query string WITHOUT the signature parameter2const qs = `timestamp=${Date.now()}`;3const signature = await sign(qs); // Returns lowercase hex string4const url = `${BASE_URL}/api/v3/account?${qs}&signature=${signature}`;Error -1021 'Timestamp for this request is outside of the recvWindow'
Cause: The timestamp sent to Binance's API differs from Binance's server time by more than 5,000ms (the default recvWindow). This can happen if your Edge Function environment has clock drift, or if there is significant latency between timestamp generation and the API call reaching Binance's servers.
Solution: First check Binance's server time by calling GET /api/v3/time and compare it to Date.now() in your Edge Function. If there's a large discrepancy, add a recvWindow parameter (up to 60000ms) to your signed query string to give more tolerance. Alternatively, fetch Binance's server time first and use it as the timestamp.
1// Add recvWindow for more timestamp tolerance2const qs = `timestamp=${Date.now()}&recvWindow=10000`;3const signature = await sign(qs);CORS error when calling Binance public endpoints directly from the frontend
Cause: Binance's API does not include CORS headers that allow browser requests from arbitrary origins. Direct fetch calls to api.binance.com from your React frontend will be blocked by the browser's same-origin policy.
Solution: Route all Binance API calls through your Edge Function, even for public endpoints that don't require authentication. The Edge Function adds the necessary CORS headers to its response, allowing the browser to receive the data. Never call the Binance API directly from frontend code.
API returns code -1003 'Too many requests; current limit is X requests per minute'
Cause: Your Edge Function is hitting Binance's IP-based rate limits. Each Binance API endpoint has a request weight, and the total weight from your IP must stay below 1,200 per minute. If multiple users are triggering your Edge Function simultaneously, the shared Supabase IP pool may hit limits.
Solution: Implement response caching in your Edge Function or in Supabase using a cached_prices table. For price data that doesn't need to be real-time (e.g., portfolio valuation), cache results for 10-30 seconds. Use the batch endpoint /api/v3/ticker/price?symbols=[...] instead of individual symbol requests to consolidate multiple price fetches into one API call.
Best practices
- Never enable trading or withdrawal permissions on Binance API keys used in Lovable applications unless those features are explicitly part of your app's function. Read-only keys limit financial exposure if a key is ever compromised.
- Restrict your Binance API key to specific IP addresses where possible. Note that Supabase Edge Functions share IP pools, so check whether your Supabase project provides static IPs (available on paid plans) before setting IP restrictions.
- Cache market data responses for 5-30 seconds in Supabase to reduce Binance API calls and stay within rate limits, especially when multiple users request the same data simultaneously.
- Use Deno's built-in crypto.subtle for HMAC-SHA256 signing rather than importing an external HMAC library — it's faster, more secure, and has no dependency version concerns.
- Fetch multiple symbols in a single /api/v3/ticker/price?symbols=[...] call rather than making separate requests per symbol. The weight cost is the same regardless of how many symbols you include.
- Store user-facing data (portfolio snapshots, price history) in Supabase rather than calling Binance on every page load. Snapshot account data every few minutes and serve it from the database for better performance and lower API costs.
- Be aware of Binance API geo-restrictions — some features and endpoints are restricted in certain jurisdictions. Test from your target market's IP range before building features that depend on restricted endpoints.
Alternatives
Plaid connects to traditional bank accounts for fiat financial data; choose Plaid when your users' finances are in banks rather than crypto exchanges.
Coinbase API is better suited for US-focused crypto apps or those building on Coinbase's Base blockchain, with a simpler authentication model than Binance's HMAC signing.
PayPal handles fiat payment processing rather than crypto market data — use PayPal when you need consumer payment buttons, not exchange data.
Frequently asked questions
Can I build a crypto trading app with Binance API in Lovable?
Technically yes — Binance's API supports order placement and management. However, building trading functionality requires 'Enable Trading' permission on your API key, which represents significant financial risk. Any bug in your Edge Function or frontend could result in unintended orders. Trading features also face heavy regulatory scrutiny in many jurisdictions. This tutorial covers read-only market data and portfolio tracking, which are significantly safer use cases.
What's the difference between Binance's REST API and WebSocket streams?
The REST API is request-response: you call an endpoint and receive current data. WebSocket streams push data continuously: you connect once and Binance sends updates as they happen (real-time price changes, trade executions, etc.). For a polling interval of 10+ seconds, REST is sufficient. For live order book updates or sub-second price feeds, WebSocket streams are more efficient. Lovable Edge Functions support one-time REST calls natively; persistent WebSocket connections require a dedicated server or a separate proxy service.
Does Binance have a testnet for development?
Yes. The Binance Spot Testnet is at testnet.binance.vision. You can create separate API keys for the testnet from the testnet site itself (not from binance.com). Testnet uses the same API structure as production but with fake funds. Update BINANCE_BASE_URL to https://testnet.binance.vision to test order placement and account operations without real money. Note: testnet data is separate from your real Binance account.
How do I handle users who want to connect their own Binance accounts?
This requires a multi-tenant approach where each user's API key and secret are stored encrypted in Supabase under their user profile. Your Edge Function reads the requesting user's credentials (verified via Supabase Auth JWT) rather than a global API key from Cloud Secrets. Ensure the API key and secret columns have RLS policies that prevent any user from reading another user's credentials, and use the service role key in the Edge Function to fetch them.
Are Binance API keys free?
Yes, Binance API keys are free to create. There are no charges for API access itself. Rate limits apply — the standard limit is 1,200 request weight per minute for most endpoints. Binance may apply additional restrictions based on account verification level, trading volume, or if your account triggers their automated abuse detection. Enterprise API access with higher limits is available for institutional clients.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation