This page does not describe a real client project. It is an example scenario that shows how Fincode approaches this kind of work. Technical details are based on official documentation; scope, timeline and price are set for each project.
| Who it is for | Individual investor with accounts on several exchanges (example scenario) |
|---|---|
| Service | Exchange API integration |
| Platforms | Crypto exchanges that offer read-only API keys |
| Technologies | REST and WebSocket APIs, relational database, encrypted secrets vault, web dashboard |
| Deliverables | Connectors, key permission checks, reconciliation jobs, risk dashboard, alert rules, security documentation |
The need
The investor's balances and positions are spread across several exchanges. Each exchange shows only its own account, so total exposure to an asset, overall P&L and the riskiest position cannot be seen at a glance.
The dashboard's limits are fixed from the start: it uses read-only keys, places no orders, moves no funds and makes no investment recommendations. The derivatives module is enabled only where the user's jurisdiction and the exchange's terms allow those products. On platforms licensed in Türkiye, Article 14 of Communiqué III-35/B.2 prohibits leveraged and derivative trading in listed crypto assets, and under Article 99/A of Capital Markets Law No. 6362 foreign platforms may not serve residents of Türkiye. For a user resident in Türkiye, the dashboard is therefore limited to spot balances.
Architecture and data model
The system has three layers: exchange connectors, a normalized data store and a web dashboard.
Proving a key is read-only
When the user adds a key, the connector first queries its permissions from the exchange's own endpoint where one exists, and any key with more than read access is refused. Where permissions are set only on the key creation screen, the setup guide shows exactly which boxes to tick and the user confirms the choice.
| Exchange | Check | Accepted when |
|---|---|---|
| Binance | GET /sapi/v1/account/apiRestrictions | enableReading is true; every trading, margin, futures, options, withdrawal and transfer flag is false |
| OKX | GET /api/v5/account/config | perm is read_only only; bound IPs appear in ip |
| Bybit | GET /v5/user/query-api | readOnly is 1; ips and expiredAt are stored |
| Kraken | Key creation screen | Only Query Funds, Query Open Orders & Trades, Query Closed Orders & Trades and Query Ledger Entries, plus Access WebSockets API if private streams are used |
Data model
| Entity | Key fields |
|---|---|
| Account | Exchange, sub-account, key reference (never the key itself), last sync time |
| Balance snapshot | Asset, free and locked amounts, timestamp |
| Position | Instrument, side, size, entry price, mark price, liquidation price, margin mode, leverage |
| Activity | Fills, fees, funding payments, transfers |
| Reconciliation record | Check time, difference found, outcome |
Changes arrive through each exchange's private WebSocket streams: Binance's user data stream sends outboundAccountPosition when a balance changes and executionReport when an order updates, and OKX provides account and position channels. Regular REST snapshots run alongside the streams.
How the risk metrics are calculated
- Exposure: the signed sum of each asset's spot balances and derivatives positions across all exchanges, and its share of the total portfolio.
- P&L: realized P&L from activity records and average cost, unrealized P&L from current prices; for derivatives, the exchange-reported figure is shown as well.
- Liquidation distance: |mark price − liquidation price| ÷ mark price.
The dashboard does not recompute liquidation prices; it uses the value each exchange reports, because margin rules differ between exchanges. On OKX, liqPx is the estimated mark price at which the position would be forcibly liquidated, and mgnRatio gives the maintenance margin ratio. On Bybit, liqPrice is an estimate for cross positions in a unified account and is empty in portfolio margin mode, in which case the dashboard shows account-level margin data instead of a distance. Background: risk management for trading bots.
| Item | Value |
|---|---|
| Mark price | 50,000 |
| Exchange-reported liquidation price | 42,500 |
| Liquidation distance | (50,000 − 42,500) ÷ 50,000 = 15% |
If the user's threshold is 20%, this hypothetical position triggers an alert. Distance is measured from the mark price, not the last trade price; OKX's own definition expresses the liquidation level as a mark price.
Reconciliation and security controls
Reconciliation
- WebSocket events can be missed, so balances are compared with REST snapshots at set intervals; on Binance,
GET /api/v3/accountreturns free and locked balances. If they differ, the REST value wins and the event is logged. - Transfers that have left one exchange but not yet reached another are tracked as in transit, so the total does not appear to drop temporarily.
- An account whose sync has failed for longer than a set interval is flagged as stale.
- Rate limits are respected: Binance reports used weight in response headers, returns 429 when a limit is exceeded and temporarily bans IPs that continue with 418.
Security
- Keys are never stored in source code or as plaintext in the database; they live in an encrypted secrets vault, only the connector service can read them and every access is logged. The OWASP Secrets Management Cheat Sheet recommends least privilege, rotation, expiry and immediate revocation on exposure.
- Keys are restricted to the servers' IP addresses where the exchange supports it. Bybit returns an expiry date in
expiredAtfor keys with no IP bound, and the dashboard warns the user before that date. - Kraken advises treating API keys like a username and password and granting only the permissions a client needs.
- Dashboard login is protected with two-factor authentication, and keys never appear in logs. Fincode does not request withdrawal permission. See API key security for more.
Testing and go-live
- Demo environment: position and margin screens are tested with sample positions opened in OKX demo trading (with the
x-simulated-trading: 1header). - Side-by-side comparison: balances, positions, liquidation prices and margin values in the dashboard are compared with the exchange interface at the same moment.
- Failure scenarios: WebSocket disconnects, over-permissioned keys, expired keys, rate limit errors and exchange maintenance are simulated.
- Go-live: the user's live accounts are connected with read-only keys, and reconciliation reports are reviewed together regularly at first.
Deliverables
- Exchange connectors with key permission checks
- Normalized data model and reconciliation jobs
- Web dashboard for balances, positions, P&L, exposure and liquidation distance
- Alert rules with user-set thresholds: liquidation distance, margin ratio, asset concentration, stale data, key expiry
- Security documentation, test report and operations runbook
If the dashboard must plug into an existing app, the integration is built as an independent service; see exchange API integration and the guide to crypto exchange API integration.
How success is measured
Success is judged by how consistent the data is with the exchanges and how strictly the security principles hold; the dashboard makes no investment decisions. The criteria are:
- Balances and positions in test accounts match the exchange interface
- Every reconciliation difference is logged and explainable
- On exchanges whose key permissions can be queried via the API, no key with more than read access is ever accepted
- Stale or missing data is clearly shown to the user
- Alerts are tested to fire at the defined thresholds
Frequently asked questions
Can the dashboard place orders?
No. It works only with read-only API keys. Where the exchange supports it, permissions are checked via the API when a key is added, and keys with trading or withdrawal rights are refused.
Why might the liquidation price differ from the exchange screen?
The dashboard does not recompute it; it shows the value the exchange reports. Differences usually come from the time between fetching the data and refreshing the screen, and in some account modes the exchange gives only an estimate or no value at all.
Can users resident in Türkiye use the derivatives module?
Platforms licensed in Türkiye may not offer leveraged or derivative trading in listed crypto assets, and foreign platforms may not serve residents of Türkiye. For a user resident in Türkiye, the dashboard is therefore limited to spot balances.
Where are the API keys stored?
In an encrypted secrets vault. They never appear in source code, as plaintext in the database or in logs, and only the connector service can access them, with every access logged.
Sources
- Binance Wallet API: Get API Key Permission (opens in a new tab)
- Binance Spot API: User Data Streams (opens in a new tab)
- Binance Spot API: REST API (account information, rate limits) (opens in a new tab)
- OKX API v5 (account config, positions, liqPx, mgnRatio, demo trading) (opens in a new tab)
- Bybit V5: Get Position Info (liqPrice) (opens in a new tab)
- Bybit V5: Get API Key Information (opens in a new tab)
- Kraken Support: How to create an API key on Kraken Pro (opens in a new tab)
- OWASP Secrets Management Cheat Sheet (opens in a new tab)
- Capital Markets Law No. 6362, Article 99/A (Turkish) (opens in a new tab)
- Official Gazette: Communiqué III-35/B.2 on crypto-asset service providers, Article 14 (Turkish) (opens in a new tab)