Top Results (0)

Hey there! I’m glad you found Cryptolinks—my personal go-to hub for everything crypto. If you're curious about Bitcoin, blockchain, or how this whole crypto thing works, you're exactly where you need to be. I've spent years exploring crypto and put together the absolute best resources, saving you tons of time. No jargon, no fluff—just handpicked, easy-to-follow links that'll help you learn, trade, or stay updated without the hassle. Trust me, I've been through the confusion myself, and that's why Cryptolinks exists: to make your crypto journey smooth, easy, and fun. So bookmark Cryptolinks, and let’s explore crypto together!

BTC: 116072.73
ETH: 4531.28
LTC: 115.48
Cryptolinks: 5000+ Best Crypto & Bitcoin Sites 2025 | Top Reviews & Trusted Resources

by Nate Urbas

Crypto Trader, Bitcoin Miner, Holder. To the moon!

review-photo

Binance Api

github.com

(1 reviews)
(1 reviews)
Site Rank: 1

Binance Spot REST API Review Guide: Everything You Need to Know (With FAQ)

Ever tried wiring your bot or app to Binance and thought, “Why is this so confusing?”

You’re not alone. The official Spot REST API docs are solid, but they assume you already know where the sharp edges are. In this guide, I explain the Binance Spot REST API in plain English so you can place orders, fetch prices, and keep your keys safe—without burning days on trial and error.

I’ll also clear up the stuff that trips people up most: signatures, timestamps, error codes, order rules, and rate limits. And yes, I’ll answer the big questions people keep asking in Google’s “People Also Ask,” like:

  • Is the Binance API free and how do I get API keys?
  • How do I fix “timestamp out of range” (-1021)?
  • What’s the rate limit and how do weights work?
  • REST vs WebSocket—when should I use each?
  • How do I place an order correctly (price, quantity, filters)?
  • How do I avoid duplicates and handle retries safely?

Why the Binance Spot REST API can feel harder than it should

Most traders and builders hit the same walls—some of them aren’t obvious until your bot is live and angry:

  • Auth and signatures: HMAC SHA256 sounds easy, until one missing parameter or wrong ordering triggers -1022 (Signature for this request is not valid).
  • Timestamp drift (-1021): If your server clock is off by a few hundred milliseconds, Timestamp for this request was 1000ms ahead of the server’s time will haunt you. Many teams only notice this after hours of flaky behavior.
  • Weird order errors (-1013): You’ll see Filter failure: PRICE or LOT_SIZE when your quantity/price doesn’t match stepSize or tickSize—rules you only discover if you check symbol filters first.
  • Rate limit surprises: Not all endpoints cost the same weight. Bursts that look harmless can push you over the edge and trigger 429s or even temporary bans (418).
  • REST vs WebSocket confusion: Polling account/order status is expensive and slow. You should place via REST, then track fills and balances via a user data stream—but that split workflow isn’t obvious at first.
  • Testnet vs production: Keys, base URLs, and sometimes behavior differ. Teams often test on prod by accident or assume testnet data mirrors mainnet liquidity (it doesn’t).
  • Error messages that lack context: A 400 with a Binance business code can be cryptic if you don’t log the full request, headers, and server time difference.

“Timestamp for this request was 1000ms ahead of the server’s time.” — a classic -1021 straight from the official docs. The fix is simple once you know it, but it blocks a lot of first attempts.

These aren’t random. They show up again and again in developer threads and support chats. The good news: every one of these has a clean, repeatable fix.

What you’ll get in this guide

Here’s my promise: I’ll explain how the Spot REST API actually works, show you the endpoints you’ll really use, break down signatures and timestamps, outline rate limits and order rules, and share battle‑tested tips to avoid bans and bugs.

  • Clear structure and quick references to the official docs
  • Real-world gotchas (with the exact error codes you’ll see)
  • Simple rules to prevent -1021, -1013, -2015, 429/418 before they happen
  • Fast debugging habits that cut issue time from hours to minutes
  • An FAQ that matches what people actually search for (People Also Ask topics)

Who this is for

  • Bot builders who want stable execution and predictable behavior
  • Analysts and data folks pulling candles, tickers, and trades
  • App developersadding crypto features without babysitting the API
  • Curious traders who want reliable automation without mystery errors

What you’ll walk away with

  • A mental model for when to use REST vs WebSocket
  • Safe authentication: keys, signatures, timestamps, and recvWindow that just work
  • Order placement that respects filters: minNotional, stepSize, tickSize
  • Rate limit awareness: weights, headers, and backoff that keep you out of trouble
  • A checklist and FAQ you can share with your team

If you’ve ever felt like the Binance API is a black box, you’re going to like how simple it becomes with the right guardrails. And I’ll point you to the exact sections of the official documentation each time so you can verify and go deeper fast.

Ready to make the API feel obvious? Let’s start by answering a simple question: what is the Binance Spot REST API, and when should you choose it over WebSocket in your workflow?

What the Binance Spot REST API is and when to use it

“Clarity beats complexity. If you can explain your stack in one sentence, you’ll build faster and break less.”

Quick definition

The Binance Spot REST API is a set of HTTP endpoints for market data, account info, and order execution on Binance Spot. It’s perfect for tasks that don’t need millisecond‑level streaming: placing orders, checking balances, pulling candles, and on‑demand reads. It’s stateless, predictable, and easy to test with tools like cURL or Postman.

Key endpoints you’ll actually use

These are the endpoints I reach for in real projects. They cover discovery, pricing, candles, account state, and trading. I’ve added real uses plus minimal examples you can paste into a browser (for public endpoints) or wire into your code.

  • /api/v3/exchangeInfo — What symbols exist and what rules apply (filters, step sizes, min notional).
    Use it before you send orders to avoid quantity/price mistakes.
    Example (public): https://api.binance.com/api/v3/exchangeInfo?symbol=BTCUSDT

  • /api/v3/klines — Historical candles for backtests, signals, and dashboards.
    Example (public, last 500 one‑minute candles): https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1m&limit=500

  • /api/v3/ticker/price — Fast spot price reads for one or many symbols.
    Examples (public):
    • Single: https://api.binance.com/api/v3/ticker/price?symbol=ETHUSDT
    • All: https://api.binance.com/api/v3/ticker/price

  • /api/v3/account — Your balances, permissions, and maker/taker commission.
    Signed request (needs API key + signature).

  • /api/v3/order (POST) — Place orders (MARKET, LIMIT, etc.).
    Signed request. Returns server orderId and your client order ID.

  • /api/v3/order (GET/DELETE) — Query or cancel an order.
    Signed request. Useful for immediate checks right after submit.

  • /api/v3/allOrders — Your historical orders for a symbol.
    Signed request. Handy for reconciliation and building PnL views.

Bonus reads you’ll probably reach for:

  • /api/v3/ticker/bookTicker — Best bid/ask snapshot for spread‑aware bots.
  • /api/v3/avgPrice — Rolling average price; good for sanity checks.

REST vs WebSocket: who does what, and why it matters

Use REST for on‑demand reads and order placement. Use WebSocket for live updates without polling (order updates, fills, and balance changes). That split keeps your app clean, faster, and lighter on rate limits.

  • REST shines when:

    • You fetch symbol rules once and cache them.
    • You place or cancel orders on demand.
    • You grab snapshots: balances, open orders, recent candles.

  • WebSocket shines when:

    • You need immediate execution reports and balance updates.
    • You watch order book changes in real time.
    • You want less bandwidth and latency vs. constant polling. (As noted by Cloudflare’s engineering team, persistent connections cut repeated handshake overhead compared to HTTP polling.)

Common flow I recommend for reliability:

  • Place order via REST → record orderId and newClientOrderId.
  • Listen on the user data stream (WebSocket) for fills and balance updates.
  • Use REST only as a backstop (e.g., if your socket reconnects, resync open orders/balances once).

Base URLs and network notes

Getting the right host and network setup prevents a lot of “it works on my laptop” headaches.

  • Production (Global): https://api.binance.com
    Backup domains: https://api1.binance.com, https://api2.binance.com, https://api3.binance.com
  • Spot Testnet: https://testnet.binance.vision
    Great for practicing orders with fake balances. You’ll need separate testnet keys.
  • Regional differences:

    • Binance.US uses https://api.binance.us and has its own rules, listings, and docs. Some endpoints and filters differ.
    • Some regions may have network restrictions. If you see unusual HTTP errors, confirm you’re using the correct regional endpoint and that your IP is allowed.

  • Where the official docs live:
    REST docs: binance-spot-api-docs
  • Network tips that pay off:

    • Prefer HTTP/2 and keep‑alive to reduce setup latency.
    • Set sane timeouts and retries (network blips happen). Avoid aggressive polling; you’ll thank yourself later.
    • Cache static stuff (like exchangeInfo) and refresh only on symbol changes.

Real‑world examples to anchor your mental model

  • Portfolio watcher: REST every 30–60 seconds for prices using /ticker/price and your balances via /account. No WebSocket needed.
  • DCA bot: REST to fetch latest price and place a LIMIT/MARKET order at set intervals; use the user data stream to confirm fills without polling.
  • Backtest + live switch: Use /klines for historical data to train or test. When going live, keep the same REST reads for decisions but add WebSocket for instant order updates.

Simplicity scales: REST for snapshots and actions, WebSocket for reactions.

Want to place signed orders, avoid timestamp errors, and keep your keys safe while you build? In the next part, I’ll show you exactly how authentication, timestamps, and signatures work — including the one tweak that stops -1021 dead in its tracks. Ready to make your requests bulletproof?

Authentication, timestamps, and signatures made simple

I’ve lost count of how many messages I’ve received that start with “Why am I getting -1021 or -2015?” Good news: once you nail API keys, signatures, and time sync, the Binance Spot REST API stops feeling like a boss fight and starts behaving. As I like to say,

“Trust, but verify — and log everything.”

Here’s exactly how I set things up when I want a bot or app to just work, day after day.

API keys setup (the safe way you won’t regret later)

Creating a key is easy. Creating a key you can sleep with at night takes 3 minutes of discipline:

  • Create the key in your Binance profile. Label it clearly (e.g., bot-spot-prod-2025-01).
  • Restrict by IP. Add your static server IPs only. If you use a cloud provider with NAT, lock it to those egress IPs.
  • Disable withdrawal permissions for anything that trades. If a key leaks, the damage should be limited to trading.
  • Enable only what you need: “Spot & Margin Trading.” Leave anything else off unless you have a concrete reason.
  • Use sub-accounts for segmentation. One bot/strategy per sub-account makes permissions and risk isolation clean.
  • Never ship keys to a client app (web/mobile). Keep secrets on your server or use a vault (AWS KMS, GCP KMS, HashiCorp Vault).
  • Rotate on a schedule (quarterly is reasonable for most). Rotation process that doesn’t break trades:

    • Create a new key and add it to your config alongside the old one.
    • Deploy; test both keys work for a few minutes.
    • Switch traffic to the new key, then revoke the old one. Keep a short overlap window (I use 24 hours max).

Industry reports like the Verizon DBIR keep showing stolen credentials as a leading cause of breaches. Least privilege and IP restrictions aren’t optional — they’re your seatbelt.

Signing requests: what actually gets hashed

Binance’s SIGNED endpoints require HMAC SHA256. You compute the HMAC over the exact string of parameters you send (in the same order), then add it as signature. Also include your key with the X-MBX-APIKEY header.

For example, placing a LIMIT order on /api/v3/order:

symbol=BTCUSDT&side=BUY&type=LIMIT&timeInForce=GTC&quantity=0.001&price=25000 

&recvWindow=5000&timestamp=1680000000000

Compute HMAC SHA256 of that string using your secret key. Hex-encode the result (lowercase) and append it:

...&signature=9f5f1a...c3e

Send with header:

  • X-MBX-APIKEY: your-public-api-key
  • Content-Type: application/x-www-form-urlencoded (for POST)

Quick rules that save hours:

  • Sign exactly what you send. If you URL-encode anything, sign the encoded form.
  • Do not include “signature” itself in the string you hash.
  • Use hex digest, not base64.
  • For POST, you can put params in the body as form data; for GET, they live in the query string. Either way, hash the same string you transmit.

Minimal examples that work:

cURL

curl -X POST 'https://api.binance.com/api/v3/order' \ 

-H 'X-MBX-APIKEY: <yourKey>' \

-H 'Content-Type: application/x-www-form-urlencoded' \

--data-raw 'symbol=BTCUSDT&side=BUY&type=LIMIT&timeInForce=GTC&quantity=0.001&price=25000&recvWindow=5000&timestamp=1680000000000&signature=<hexSignature>'

Python

import hmac, hashlib, time, urllib.parse, requests 

api_key = 'YOUR_KEY'

secret = 'YOUR_SECRET'.encode()

params = {

'symbol': 'BTCUSDT',

'side': 'BUY',

'type': 'LIMIT',

'timeInForce': 'GTC',

'quantity': '0.001',

'price': '25000',

'recvWindow': '5000',

'timestamp': str(int(time.time()*1000))

}

query = urllib.parse.urlencode(params, safe=':')

sig = hmac.new(secret, query.encode(), hashlib.sha256).hexdigest()

r = requests.post(

'https://api.binance.com/api/v3/order',

headers={'X-MBX-APIKEY': api_key},

data=query + '&signature=' + sig

)

print(r.status_code, r.text)

Official docs for security and signing are here: Endpoint security.

Timestamps and recvWindow: stop -1021 before it starts

Every SIGNED call needs timestamp in milliseconds and usually a recvWindow (the maximum accepted age of the request on Binance’s side). If your system clock drifts, you’ll see -1021 (timestamp out of range).

How I keep it tight:

  • Sync with NTP at the OS level.
  • On app start (and every few minutes), call /api/v3/time and compute an offset.
  • When sending requests, use SystemTime + offset for timestamp.
  • Set recvWindow to 5000–10000 ms to absorb network jitter without being sloppy.

Offset sample:

# pseudo-code 

server_time = GET https://api.binance.com/api/v3/time

local_time = now_ms()

offset = server_time - local_time

# later for each request

timestamp = now_ms() + offset

Gotchas I see often:

  • recvWindow too small for your latency spikes — increase to 10000 ms and retest.
  • Using local time without offset on VMs/containers where NTP isn’t reliable.
  • Calling /time too rarely; re-check every few minutes or after network incidents.

Common auth errors and quick fixes

When something fails, check the HTTP status, response JSON, and headers. These four errors cover 90% of auth problems:

  • -2015: Invalid API-key, IP, or permissions

    • Did you enable “Spot & Margin Trading” on the key?
    • Is your server IP in the allowed list?
    • Are you mixing up testnet and mainnet keys/URLs?
    • Is the key expired or deleted? Rotate and try again.

  • -1022: Signature for this request is not valid

    • Signed the wrong string (or different order than what you sent)? Sign the exact encoded string you transmit.
    • Used base64 instead of hex? Must be hex.
    • Included signature in the string you hashed? Don’t.
    • Used JSON body instead of form-encoded? Use application/x-www-form-urlencoded.

  • -1021: Timestamp for this request was 1000ms ahead/behind

    • Sync time with /api/v3/time and NTP.
    • Use recvWindow 5000–10000 ms.
    • Recompute offset periodically.

  • -1102: Mandatory parameter was not sent

    • Check you included timestamp for SIGNED calls.
    • Confirm required order fields for the type (e.g., LIMIT needs price and timeInForce).
    • Beware typos or wrong casing (Binance params are case-sensitive).

Sniff it fast with clean request logs

When a request fails, I want the answer in one glance. Here’s the minimal log line that pays for itself:

[POST] /api/v3/order 

query= symbol=BTCUSDT&side=BUY&type=LIMIT&timeInForce=GTC&quantity=0.001&price=25000&recvWindow=5000&timestamp=1680000000000

toSign= <exact string above>

signature= 9f5f1a...c3e

headers= X-MBX-APIKEY=****1234

status= 400 body= {"code":-1022,"msg":"Signature for this request is not valid."}

latency_ms= 212

With that, you can instantly see if you hashed the wrong string, forgot a param, or had clock drift. Fix takes minutes, not hours.

Mini checklist before any SIGNED call

  • Key has only the permissions you need; withdrawals off; IPs locked.
  • Time offset computed from /api/v3/time; recvWindow set to 5000–10000.
  • Params form-encoded and signed in the exact order sent.
  • Signature hex-encoded; header X-MBX-APIKEY set.
  • Logs include method, path, params, toSign, signature, status, and body.

You can now authenticate cleanly and stop those mystery errors. Next up: what happens after you’re authenticated — can you stay under Binance’s weight limits, avoid 429/418, and pass symbol filters without tripping -1013? I’ll show you the rate limit math and the order rules I check before every trade. Ready to stop accidental bans?

Rate limits, order rules, and staying out of trouble

Nothing kills a trading bot faster than a silent ban or a stream of “Filter failure” errors at 2 a.m. If you’ve ever woken up to HTTP 418 or watched your orders bounce with -1013, you know the pain. The good news: this is predictable and preventable when you understand weights, filters, and sane retry patterns.

“Slow is smooth. Smooth is fast.” — the mantra of every bot that’s still alive after a market spike

Understanding weight: endpoint costs, minute buckets, and headers you must watch

Binance Spot REST doesn’t just limit requests per minute; it limits weight. Each endpoint costs weight, and you get a per‑minute budget (commonly 1200, but always treat it as dynamic and account-specific). Heavy “all symbols” endpoints cost more than single‑symbol calls.

  • Typical pattern: single‑symbol market data ~1 weight; “all symbols” variants can be 2–40+; account/trade endpoints vary. The official docs list the current weights, and Binance can change them.
  • Real-time hints: every response includes headers like X-MBX-USED-WEIGHT-1m (and sometimes X-MBX-USED-WEIGHT) that show your usage in the current 1‑minute window.
  • Bursts hurt: even if your total/minute is under the cap, short spikes can trigger 429 and, if repeated, 418 (temporary ban). Smooth your traffic.

Practical example (how to burn or save weight):

  • Bad: loop through 200 symbols and call /api/v3/ticker/price?symbol=XYZUSDT 200 times. If each is weight 1, that’s ~200 weight in one burst and fragmented latency.
  • Better: fetch /api/v3/ticker/price (all symbols) once. Yes, it’s heavier per call, but you perform far fewer calls and avoid bursty usage.
  • Best for live updates: use a WebSocket stream for prices and reserve REST for on‑demand reads and order placement.

Read your headers (from a real flow):

X-MBX-USED-WEIGHT-1m: 764
X-MBX-ORDER-COUNT-1m: 7

If you see 1100+ used weight with 8–10 seconds left in the minute, throttle immediately. Don’t wait for 429 to slap you.

Order and symbol rules: stepSize, tickSize, minNotional—most “filter failure” errors are self-inflicted

Every symbol has filters you must respect. Pull them from /api/v3/exchangeInfo and cache them. The big ones:

  • PRICE_FILTER: minPrice, maxPrice, and tickSize (price granularity)
  • LOT_SIZE: minQty, maxQty, and stepSize (quantity granularity for limit orders)
  • MARKET_LOT_SIZE: min/max/step for market orders (often different from LOT_SIZE)
  • MIN_NOTIONAL: minimum notional value (price × qty) your order must meet
  • PERCENT_PRICE: limits how far your limit price can be from a reference price

How to format orders so they pass first try (use decimal math, not floats):

  • Round price to tickSize: price = round(price / tickSize) × tickSize
  • Truncate quantity to stepSize: qty = floor(qty / stepSize) × stepSize
  • Check notional: price × qty ≥ minNotional (for MARKET BUY, Binance may use quoteQty; still validate your intent)

Example (values are illustrations—always read the live filters):

  • Say ETHUSDT has tickSize = 0.01, stepSize = 0.0001, minNotional = 5
  • You want to place a LIMIT BUY at $2,345.678 → price must be 2345.68 (rounded to 0.01)
  • You want ~0.003456 ETH → stepSize 0.0001 forces 0.0034 (truncate; don’t round up)
  • Notional check: 2345.68 × 0.0034 = 7.965312 ≥ 5 → good to go

Common mistakes that trigger -1013:

  • Rounding up a quantity to meet stepSize—must truncate to avoid exceeding balance or violating min/max.
  • Forgetting MARKET_LOT_SIZE differs from LOT_SIZE (market order passes LOT_SIZE but fails MARKET_LOT_SIZE).
  • Assuming minNotional is “always 10 USDT.” It changes. Read filters.

Backoff and retries: survive 429/418 and avoid duplicate orders

When you see 429 (rate limit), slow down; repeat too many times and you’ll hit 418 (IP banned temporarily). There’s no glory in “retry storms.” Use a backoff strategy with jitter and, for POSTs, make retries idempotent.

  • Exponential backoff with jitter: e.g., 250ms, 500ms, 1s, 2s, 4s, each ±random 20–40%. This prevents synchronized spikes (a well-documented SRE pattern from AWS and Google).

    • Recommended read: AWS: Exponential Backoff and Jitter
    • Also see: Google SRE: Handling Overload

  • Throttle proactively when X-MBX-USED-WEIGHT-1m approaches your budget; don’t wait for 429.
  • Idempotency for POST /api/v3/order: set newClientOrderId so if your HTTP client times out, you can safely retry without creating duplicate orders. On retry, re‑use the same ID and check for an existing order with it.
  • Know when to stop: abort retries on business logic errors (e.g., -1013 filter failure, -2010 insufficient balance). Only retry transient network errors, gateway 5xx, and 429/418 after waiting.
  • Cool‑off after 418: back off for several minutes and reduce your concurrency/burst size before resuming.

Sample retry policy that actually works in production:

  • GETs: up to 6 retries over ~10–15 seconds total with full jitter; bail if headers show weight is exhausted (sleep until next minute).
  • POST orders: 2–3 retries max over 3–5 seconds total, with the same newClientOrderId. After that, switch to a “query by clientOrderId” check rather than hammering create again.

Best practices for bots: less noise, fewer calls, zero bans

  • Cache static data: store /exchangeInfo and refresh on a timer (e.g., every 30–60 minutes) or when you detect symbol status changes. Do not fetch it on every order.
  • Batch your reads: prefer “all symbols” endpoints sparingly over 100 tiny calls; better yet, stream with WebSocket user data and market feeds, and use REST for snapshots.
  • Token bucket your requests: shape traffic with a simple bucket (e.g., 20–30 weight/sec) to avoid bursts. It keeps latency smoother and reduces 429s to near zero.
  • Monitor the right metrics: log X-MBX-USED-WEIGHT-1m, X-MBX-ORDER-COUNT-10s, error rates by endpoint, and p95 latency. Alert if your used weight sits above 80% for two consecutive minutes.
  • Use decimal math end‑to‑end (BigDecimal/decimal.js). Float drift = random -1013s.
  • Pre‑validate orders against cached filters
  • Separate concerns: one worker for market data, one for orders, one for account reads — each with its own rate limiter. Cross‑talk creates bursty patterns that are hard to reason about.
  • Have a “rain mode”: during extreme volatility, tighten concurrency and increase backoff. Stability beats speed when everyone else is flooding the API.

Last thing — the emotional one. Nobody likes the pit in the stomach that comes with a 418 ban during a fast move. If you smooth your request patterns, round your orders to the exchange’s filters, and make retries idempotent, you’ll feel calm when the market goes wild. That’s when good systems quietly print.

Ready to place orders that pass on the first try, stay idempotent, and show up instantly in your app? Up next, I’ll show exactly how I structure MARKET, LIMIT, STOP_LOSS_LIMIT, TAKE_PROFIT_LIMIT, and even OCO — with logs that tell you the truth. Want me to share the clientOrderId strategy I use to make retries safe?

Placing orders the right way (and tracking them)

“In trading, precision beats speed. Every extra click, round-trip, or guesswork is a leak in your P&L.”

I’m going to show you how I actually place and track orders on the Binance Spot REST API without getting tangled in partial fills, ghost cancels, or duplicate submissions. This is the playbook I use in production when real money and uptime are on the line.

Order types that actually matter (and when I use them)

Use the simplest order that enforces your risk and execution intent. Here’s the short list that covers 99% of use cases:

  • MARKET — When I need in now. I use this for urgent exits or small-size entries. To control spend, I set quoteOrderQty:
    POST /api/v3/order type=MARKET&side=BUY&symbol=BTCUSDT&quoteOrderQty=100
    That buys ~100 USDT worth of BTC without me calculating quantity. I never send both quantity and quoteOrderQty; choose one.
  • LIMIT (GTC/IOC/FOK) — For price control and fee optimization. GTC for resting orders (often maker), IOC if I’m okay with partial immediate fills, FOK if I want all-or-nothing right now.
    POST /api/v3/order type=LIMIT&side=SELL&symbol=ETHUSDT&price=3500&quantity=0.5&timeInForce=GTC
  • STOP_LOSS_LIMIT — My preferred stop on Spot because it avoids slippage surprise.
    POST /api/v3/order type=STOP_LOSS_LIMIT&side=SELL&symbol=BTCUSDT&quantity=0.02&stopPrice=62800&price=62750&timeInForce=GTC
    When last price hits stopPrice, Binance places your limit at price. If price gaps down, it might not fill—by design.
  • TAKE_PROFIT_LIMIT — Same mechanics as above, for profit targets with protection against bad prints.
  • OCO (One‑Cancels‑the‑Other) — My “set it and breathe” bracket: one limit take-profit and one stop. If one fills, the other cancels automatically.
    POST /api/v3/order/oco side=SELL&symbol=BTCUSDT&quantity=0.02&price=65500&stopPrice=62900&stopLimitPrice=62850&stopLimitTimeInForce=GTC
  • LIMIT_MAKER — Maker‑only. If it would take liquidity, it rejects. I use this when I absolutely want maker fees only.

Two quick, practical notes:

  • Fees and slippage are real edge killers. Market orders pay spread and taker fees. Limit/Maker can reduce both. See Binance’s fee tiers: binance.com/en/fee/schedule.
  • For filled‑data in one shot, send newOrderRespType=FULL. DEFAULT/RESULT is fine for most cases; FULL helps when you need immediate fill breakdowns for MARKET orders.

Idempotency and client order IDs (no accidental doubles)

Retransmits happen. Networks blip. If you don’t control idempotency, you’ll double‑order and hate yourself.

  • Always set newClientOrderId on every order. I use a sortable, unique key like STRAT42_BTCUSDT_20240918T101530Z_7QJX.
  • If a retry hits the server, Binance will reject a duplicate newClientOrderId. That’s good. When I get a “clientOrderId not unique” error, I immediately GET /api/v3/order with origClientOrderId to reconcile the outcome in my DB.
  • For edits, don’t race cancel then re‑submit. Use cancelReplace (atomic) if your symbol supports it:
    POST /api/v3/order/cancelReplace with cancelOrigClientOrderId and the new price/qty in one request.

Pro tip: log the client ID everywhere — request, response, WebSocket events — so you can stitch the entire lifecycle in one search.

Order lifecycle that scales (without wasteful polling)

This is the flow I rely on for reliability and speed:

  • Place via REST with a unique newClientOrderId and the correct filters applied (tickSize/stepSize/minNotional).
  • Immediately subscribe (or already be subscribed) to the User Data Stream. Watch for executionReport and balanceUpdate/outboundAccountPosition events for fills and balance changes in real time.
  • Avoid heavy polling. If you must query, use GET /api/v3/order for a single order, and GET /api/v3/openOrders sparingly.
  • Cancel with DELETE /api/v3/order using orderId or origClientOrderId. For OCO, use DELETE /api/v3/orderList.
  • Statuses you’ll see: NEW, PARTIALLY_FILLED, FILLED, CANCELED, REJECTED, EXPIRED. Only treat FILLED as final; partially filled orders can still execute or be canceled.

The goal: REST to command, WebSocket to know. That’s how you stay under rate limits and still get instant feedback.

Quick, copy‑and‑ship workflows

Create a LIMIT, verify, cancel if needed

  • POST /api/v3/order:
    symbol=BTCUSDT&side=BUY&type=LIMIT&timeInForce=GTC&price=63000&quantity=0.015&newClientOrderId=BUY_BTCUSDT_63000_001
  • Watch WebSocket for executionReport with status=NEW → order acknowledged.
  • If market runs away, tweak price using cancelReplace or:
    DELETE /api/v3/order with origClientOrderId=BUY_BTCUSDT_63000_001.
  • Confirm cancellation via WebSocket (status=CANCELED). If the cancel ACK is delayed, I do a single GET /api/v3/order as a backstop.

Place a MARKET buy by quote

  • POST /api/v3/order:
    symbol=ETHUSDT&side=BUY&type=MARKET&quoteOrderQty=250&newOrderRespType=FULL
  • Persist fills from response if FULL, then reconcile with WebSocket fills to ensure perfect accounting.

Set an OCO bracket after entry

  • POST /api/v3/order/oco:
    symbol=ETHUSDT&side=SELL&quantity=0.8&price=3550&stopPrice=3290&stopLimitPrice=3285&stopLimitTimeInForce=GTC&listClientOrderId=BRACKET_ETH_001
  • Track both legs via WebSocket. When one fills, the paired leg will auto‑cancel; confirm the orderList status to keep your UI/DB clean.

Make partial fills your friend

  • Don’t treat partials as noise. In my books, every partial updates exposure and risk — I recalc stops and targets on each EXECUTION_REPORT with lastExecutedQty and cummulativeQuoteQty.
  • For reporting, store both executedQty and fills[].commission/commissionAsset when available.

What “good logs” look like (so you can fix issues in minutes)

  • On submit: timestamp, symbol, side, type, price, quantity or quoteOrderQty, timeInForce, newClientOrderId, recvWindow, a hash of the pre‑signature query string (to reproduce).
  • On response: HTTP status, Binance code/msg if any, orderId, clientOrderId, transactTime, status, executedQty, cummulativeQuoteQty, fills if FULL.
  • On WebSocket events: eventTime, executionReport fields (orderStatus, lastExecutedQty, lastQuoteTransacted, commission), and link via clientOrderId.
  • On cancel/replace: both the cancel target IDs and the replacement newClientOrderId.

When something goes wrong, these fields let me reconstruct the exact intent and server outcome in seconds — and that’s usually the difference between a small paper cut and a big loss.

Little details that add up to real money

  • Respect filters from /api/v3/exchangeInfo: tickSize for price, stepSize for quantity, and minNotional. I round client‑side to avoid rejects and pre‑validate before every submit.
  • Use IOC/FOK when speed matters: IOC fills what it can now and cancels the rest; FOK gives certainty — either fully filled or nothing.
  • Throttle yourself on read endpoints: for order tracking, WebSocket beats any GET loop. Your rate limit budget belongs to real work, not polls.

If you’ve ever fat‑fingered a STOP or chased a runaway cancel, you know the stress. The right structure removes it. Slow is smooth, smooth is fast.

Now, if an order gets rejected or a cancel comes back strange, how do you tell whether it’s your filters, your timestamp, or the exchange throttling you? Ready to spot the exact cause in one read and fix it fast? Let’s look at the errors, responses, and debug tricks next.

Errors, responses, and fast debugging

If you can read Binance responses like a mechanic reads an engine, you’ll fix issues in minutes, not hours. Here’s how I parse HTTP vs business errors, spot the root cause fast, and ship a fix without guessing.

HTTP vs Binance error codes: who’s talking to you?

Two layers of signals come back from the API:

  • HTTP status codes (from the gateway): 2xx success, 4xx client issues, 5xx server trouble, and the special 429/418 rate-limit family.
  • Binance business codes (in the JSON body): negative integers like -1013, -2015, -1021 that tell you exactly what failed in trading logic or auth.

Always log both. A 400 can hide very different causes depending on the business code.

Example error body
{ "code": -1013, "msg": "Filter failure: LOT_SIZE" }

Keep an eye on response headers too—they’re your rate-limit dashboard and tracing breadcrumbs in production.

Top headaches solved (quick fixes that actually work)

-1013: bad quantity/price or filter failure

  • What it means: Your order violates a symbol filter: LOT_SIZE (quantity step), PRICE_FILTER (price tick), MIN_NOTIONAL (too small order), or PERCENT_PRICE_BY_SIDE constraints.
  • How I fix it:

    • Fetch /api/v3/exchangeInfo and cache filters per symbol.
    • Round quantitydown to stepSize and round pricetotickSize before sending.
    • For MARKET orders, ensure quantity × lastPrice ≥ minNotional or use quoteOrderQty to spend an exact quote amount.

  • Pro tip: Run a pre-check function that returns the exact corrected price/qty you’ll send. No more trial and error.

-2015: invalid API-key, IP, or permissions

  • What it means: The key is bad, disabled, out of scope, or the request hit from a non-whitelisted IP.
  • How I fix it:

    • Confirm you enabled Spot & Margin Trading on that key (and not just reading).
    • Check IP restrictions—your server’s egress IP must match exactly.
    • Use the right environment: testnet keys won’t work on mainnet and vice versa.
    • Rotate keys if they were created long ago or permissions recently changed.

  • Pro tip: Log key last 6 chars and env (mainnet/testnet) with each request. You’ll spot cross-environment mistakes instantly.

-1021: timestamp out of range

  • What it means: Your timestamp is too far from Binance server time.
  • How I fix it:

    • Sync clock at startup using /api/v3/time. Store offset = serverTime - localTime. Apply it to every signed request.
    • Set a sane recvWindow (e.g., 5000–10,000 ms) while keeping accurate time.
    • Run NTP on your host (e.g., chrony on Linux). Cloud VMs can still drift under load.

  • Sanity check: If round-trip latency spikes, re-fetch /time and refresh the offset.

429/418: rate limited or banned

  • What it means: You exceeded weight limits (429) or hit hard penalties (418) for aggressive behavior.
  • How I fix it:

    • Read headers X-MBX-USED-WEIGHT and, where present, X-MBX-USED-WEIGHT-1M to see current load.
    • Throttle by endpoint weight, not request count. Cache and batch reads. Avoid polling; prefer user streams for updates.
    • Use exponential backoff with jitter. On 418, stop and wait out the penalty window.

  • Pro tip: Centralize all REST calls through one rate limiter so parallel services can’t trip each other.

Useful headers and tracing that save hours

  • X-MBX-USED-WEIGHT (and sometimes X-MBX-USED-WEIGHT-1M): How much of your current weight budget you’ve used.
  • X-MBX-ORDER-COUNT-10S / X-MBX-ORDER-COUNT-1M: Orders sent in the last window—great for pacing order bursts.
  • Correlation IDs:

    • newClientOrderId: Your idempotent key. Include it in logs with symbol, side, type, qty, price.
    • orderId: Binance’s server-side ID. Log it on every response and carry it into cancels or queries.

  • Time breadcrumbs:

    • Log timestamp, recvWindow, and applied offset alongside the response’s status.
    • Store the exact raw JSON. Error messages can be nuanced (“Filter failure” variants) and useful for post-mortem.

My “60‑second RCA” playbook
1) Read HTTP code → 2xx/4xx/5xx?
2) Parse JSON → business code + msg.
3) Check headers → weight/order counters.
4) Compare request vs /exchangeInfo (filters) and /time (offset).
5) Fix the top mismatch → retry with idempotency.

Real-world debugging examples

Example: LIMIT order keeps failing with -1013

  • Pull filters from /api/v3/exchangeInfo for the symbol.
  • Round price to tickSize (e.g., 2371.127 → 2371.12 if tickSize is 0.01).
  • Round quantity down to stepSize (e.g., 0.123456 → 0.1234 if stepSize is 0.0001).
  • Check MIN_NOTIONAL (price × qty). If too small, increase quantity or price appropriately.
  • Re-submit with a fresh newClientOrderId that matches your DB record.

Example: sudden burst of 429s during daily sync

  • Stagger heavy endpoints like /allOrders and /klines with a token bucket limiter.
  • Cache static data and widen Kline intervals (don’t pull 1m candles if 5m will do).
  • Move to WebSocket user streams for fills/balances so you stop polling /account.
  • Track X-MBX-USED-WEIGHT in metrics. Alert before you hit the ceiling.

Fast fixes for signature and timestamp mishaps

  • -1022 (signature): Ensure you sign the exact query string (same param order, URL-encoded where required), using HMAC SHA256 with your secret, and append &signature=....
  • -1021 (timestamp): Compute and cache server offset from /api/v3/time. Apply it to every signed request and keep recvWindow reasonable (start with 5000 ms).
  • -1102 (missing params): Compare your payload to the docs and log the final URL you sent. You’ll spot typos or missing mandatory fields quickly.

Extra tools and resources that actually help

  • Official Spot REST docs: the source of truth for errors, filters, and limits — Binance Spot REST API
  • Official connectors (handy for signing, retries, and examples):

    • Python: binance-connector-python
    • Node.js: binance-connector-node
    • Java: binance-connector-java
    • Go: binance-connector-go

  • API explorers: Use Postman or Insomnia to mirror your production request (same query string, headers, timestamp) and validate the exact response.
  • Observability: Log newClientOrderId, orderId, symbol, side, type, price, qty, timestamp/recvWindow, HTTP code, business code, and headers. Those seven lines solve 90% of tickets.

I’ve shown you how I untangle errors and turn them into quick fixes. Want the cheat-sheet answers to the questions everyone asks—like which errors you can safely retry, which ones you should never retry, and the exact recvWindow I use in production? I’ll share that next. Ready?

FAQ, best practices, and next steps

Rapid‑fire FAQ

  • Is the Binance Spot REST API free?

    Yes. There’s no API access fee. You pay normal trading fees if you place orders. Your only constraint is rate limits enforced via request weights. Details are in the official docs: REST API Reference and the fee schedule.

  • How do I get an API key and keep it safe?

    Create a key in your Binance account settings, restrict by IP, and disable withdrawals for anything that trades. Never put keys in frontend code. Store them in a secrets manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) and rotate regularly. Quick start guidance lives in the Endpoint Security section.

  • What’s recvWindow and what should I use?

    It’s the max allowed difference (in ms) between your timestamp and Binance’s clock for a signed request. I use 5000–10000 ms in production. If your clock is synced, you’ll never see -1021. See Timestamp and recvWindow.

  • How do I fix -1021 (timestamp out of range)?

    Sync your server with NTP (e.g., chrony on Linux) and set recvWindow to a sane value. If you run containers across regions, check drift between nodes. NIST recommends reliable NTP sync for security-sensitive systems—see their timing guidance: NIST Time Distribution.

  • How do I fix -2015 (invalid API-key, IP, or permissions)?

    Common causes: wrong base URL (e.g., using global keys on a regional endpoint), key lacks trading permission, IP not whitelisted, or your request isn’t signed correctly. Recreate the key, recheck IP/permissions, and verify you sign the exact query string in order. See Signed endpoints.

  • Why am I getting -1013 (bad price/quantity)?

    You’re violating symbol filters (stepSize, tickSize, minNotional). Fetch /api/v3/exchangeInfo, round price to tickSize, round quantity to stepSize, and ensure price * quantity ≥ minNotional. If BTCUSDT has tickSize 0.10, a price like 27123.07 will be rejected—use 27123.10 or 27123.00.

  • What’s the best way to avoid rate limit bans?

    Cache static responses (exchangeInfo), consolidate reads, and watch the X‑MBX‑USED‑WEIGHT headers. Use exponential backoff with jitter on 429. If you hit 418, pause for the full cooldown. The Limits section explains weights.

  • REST vs WebSocket: which should I use for order updates?

    Place orders with REST and track fills/balances with the user data stream (listenKey). Keep the listenKey alive every ~30 minutes. This cuts 80–95% of polling traffic on most bots. See User Data Streams.

  • How do I place OCO orders?

    Use the OCO endpoints in the Spot API to create a profit target and a stop in one shot. Read the OCO section in the docs for required params and limits. Start here: OCO Orders.

  • Can I cancel all open orders?

    Yes—per symbol. Use the “Cancel All Open Orders on a Symbol” endpoint. It’s safer than trying to loop and cancel one-by-one under load. See the cancel-all section.

  • What’s the difference between Testnet and Production?

    Testnet simulates trading with fake balances and your own API keys for that environment. Perfect for CI pipelines and sandboxing without risking funds. Find endpoints and docs here: Binance Testnet and the main REST API docs.

  • How do I keep orders idempotent on retries?

    Set newClientOrderId yourself. If a network hiccup happens after placement, retrying with the same ID won’t double-place. You’ll get the same order back or a clear error you can reconcile.

  • Do I need sub-accounts or can I trade everything from one key?

    You can trade from one key, but teams often use sub-accounts to isolate strategies, permissions, and reporting. It reduces blast radius if one key is compromised. Check your account type for availability and limits.

  • Where do I find historical data for backtesting?

    /api/v3/klines is great for recent candles. For deeper history and bulk data, use the Binance Data Portal to download full market archives (trades, klines, book snapshots).

  • How long does a listenKey last?

    60 minutes. Call keepalive periodically (I do it every 30 minutes) to extend it. If it expires, you’ll miss events—recreate and resubscribe.

“If it’s not in your logs, it didn’t happen.” — Treat every request/response pair as evidence. Log the full query params (without secrets), response code, and the X‑MBX headers so you can reconstruct issues fast.

Security checklist

  • Lock down keys: IP‑restrict, disable withdrawals for trading apps, and use least privilege. Separate keys per environment (dev, staging, prod).
  • Never expose secrets client-side: No keys in mobile/desktop/web apps. Route through a backend you control.
  • Use a secrets manager: AWS/GCP/Azure secret stores or Vault. Encrypt at rest and in transit. Rotate keys at a fixed cadence (30–90 days).
  • Clock hygiene: Run NTP (chrony/ntpd). Time drift breaks signatures and can trigger bans. See NIST timing resources: NIST.
  • Validate inputs server-side: Enforce symbol filters (tickSize, stepSize, minNotional) and sanitize all external input. OWASP’s API Security Top 10 is a solid reference.
  • Protect build pipelines: No secrets in repos or CI logs. Use OIDC or short‑lived credentials for deploys.
  • Redact logs: Don’t log signatures, keys, or full auth headers. Keep request IDs, order IDs, and weights.
  • Watch for anomalies: Alert on unusual weights, bursts of 4xx/5xx, sudden -2015 errors, or unknown IPs hitting your service.
  • DDoS and rate shaping: If you expose public endpoints (e.g., for your UI), put a WAF or CDN in front. Keep your Binance-facing bot behind a stable egress IP that’s whitelisted.

Bonus: monitoring quick-start

  • Latency and drift: Track request latency and server time difference from /api/v3/time. Alert if drift > 2s.
  • Rate headroom: Capture X‑MBX‑USED‑WEIGHT headers and alert when you cross 70% of your budget.
  • Order health: Count rejects by code (-1013, -2015). Anything above a tiny baseline is a fire to put out.
  • Backoff stats: Log 429/418 occurrences and the retry interval you applied. Use exponential backoff with full jitter (Google SRE recommends jitter to avoid thundering herds—see the SRE chapter on overload).
  • Idempotency coverage: Measure percent of orders with newClientOrderId. Aim for 100%.
  • Stream continuity: Track listenKey refresh success and WebSocket reconnect counts. Alert if refresh fails or reconnects spike.

Wrap‑up and where to go next

You’ve got what you need to ship with confidence: how to keep signatures valid, place clean orders, stay inside rate limits, and troubleshoot fast when something breaks. The official docs are your source of truth—bookmark them: Binance Spot REST API and User Data Streams.

Next steps I recommend:

  • Spin up Testnet and run a short end‑to‑end: place a LIMIT, watch fills via the user stream, cancel, and verify balances.
  • Add a guardrail: exchangeInfo cache + filter validation before every order.
  • Wire up basic monitoring: time drift, weight headroom, error codes.
  • Ship a tiny slice to production with read‑only first, then enable trading with tight notional limits.

If you want me to review your setup or share templates (Postman, env files, backoff helpers), leave a note on cryptolinks.com. I’m happy to help you get it right the first time.

Pros & Cons
  • One of the most popular exchanges and has thorough documentation on GitHub relating to the API
  • Straightforward process for users to create an API
  • Telegram group available to support users
  • API is still under development and in beta stage
  • Users have noted that infrastructure developed for multiple exchanges may face issues when applied to Binance