openapi: 3.0.3
info:
title: Crypto.com Exchange API v1
version: 1.0.0
description: "## Welcome\n\nWelcome to the Crypto.com Exchange API v1 reference documentation.\n\nThe Crypto.com Exchange API v1 provides developers with a **REST** and **WebSocket** API. The majority of API calls are available across both mediums in the **same** request and response formats, allowing smooth transition and a reduced learning curve between the two platforms.\n\nThe majority of API calls are available across both mediums in the same request and response formats, allowing smooth transition and a reduced learning curve between the two platforms.\n\nWhere applicable, all API calls come with detailed information on both the request and response parameters, all in a simple JSON format, as well as sample requests and code snippets in JavaScript, Python which can be viewed on the right.\n\n### Notes on Exchange Upgrade and API Versions\n\n- Exchange v1 API is the latest version of API which can trade Spot / Derivatives / Margin.\n- Derivatives v1 API has been upgraded into Exchange v1 API with additional capabilities for Spot Trading / Margin Trading / Wallet Management. As Exchange v1 API is a superset of Derivatives v1 API, existing customer can continue using the same for trading.\n- For full details about the exchange upgrade, please refer to this (blog post)[https://crypto.com/product-news/introducing-the-gen-3-0-crypto-com-exchange] with FAQ documents.\n\n## Breaking Change Schedule\n\n- On 2025-12-17 8:00 UTC, \n The current trigger order creation/cancellation will be migrated to Advanced Order Management API.\n\n- On 2025-02-27 8:00 UTC, \n For `book.{instrument_name}.{depth}`, the full snapshot subscription (`book_subscription_type=SNAPSHOT`) `100ms` frequency is removed. \n Customers wishing to continue with the faster `100ms` frequency should switch to the delta subscription (`book_subscription_type=SNAPSHOT_AND_UPDATE`). \n This higher performing subscription benefits the user with reduced bandwidth/processing compared to the snapshot subscription. \n For a transition period, users subscribing to the removed `100ms` snapshot will receive the `500ms` subscription.\n\n The `book.{instrument_name}` subscription (default depth) will be removed. \n Customers should use the explicit `book.{instrument_name}.{depth}` subscription and specify the required depth.\n\n For a transition period, users subscribing to the removed subscription will receive the default `50` depth subscription.\n\n- These changes will take place around 17 December 2023 8:00 UTC.\n\n- Market Data wildcard ticker subscription will be removed. Users should use the instrument specific subscription.\n\n## Change Log\n\n- **2026-05-21**\n - `public/get-instruments` response updated, new field `product_type` was added\n - Trading Bot API section was added:\n `private/bot/create-trading-bot` (DCA, TWAP, GRID, FUNDING_ARBITRAGE)\n `private/bot/terminate-trading-bot`\n `private/bot/update-trading-bot`\n `private/bot/pause-trading-bot`\n `private/bot/resume-trading-bot`\n `private/bot/get-trading-bots`\n `private/bot/get-trading-bot-executions`\n- **2026-05-07**\n - Advanced Order Management API section was updated for DerivAttach\n - `private/advanced/create-oto` and `private/advanced/create-otoco` — contingency type is now resolved from instrument type: spot instruments create SPOT_ATTACH, derivative instruments create DERIV_ATTACH. DerivAttach supports `isolation_id`, `leverage`, `isolated_margin_amount` on the primary leg and `ISOLATED_MARGIN` in `exec_inst`. Trigger legs inherit isolation mode from the parent.\n - `private/advanced/create-order` — `attach_order_id` now applies to both SpotAttach and DerivAttach. New optional field `attach_isolation_id` for DerivAttach attach-to-position (derivatives only).\n - `private/advanced/cancel-oto` and `private/advanced/cancel-otoco` — updated to cover both SPOT_ATTACH and DERIV_ATTACH.\n - `private/advanced/cancel-all-orders` — new optional field `position_type` (CROSS_MARGIN, ISOLATED_MARGIN).\n - `private/advanced/get-open-orders`, `private/advanced/get-order-detail`, `private/advanced/get-order-history`, and `user.advance.order` — response attributes extended with `exchange_order_id`, `ref_price`, `ref_price_type`, `reject_reason`, `attach_isolation_id`, `isolation_id`, `isolation_type`, `leverage`, `isolated_margin_amount`. `contingency_type` now includes DERIV_ATTACH.\n - `private/advanced/amend-order` — corrected required/optional flags: `new_price` is Y, `new_quantity` is Y, `new_ref_price` is N.\n- **2026-04-29**\n - Fee Credits\n - `private/get-fee-credit-balances` was added\n - `private/get-trades` response updated, new field `fee_credits` was added\n - `user.trade.{instrument_name}` response updated, new field `fee_credits` was added\n- **2026-04-07**\n - `private/get-accounts` response updated, new field `hierarchy` was added\n- **2026-04-01**\n - `private/create-order` request updated, `REDUCE_ONLY` was added to `exec_inst`\n- **2026-01-08**\n - Add support for isolated position\n - `private/create-isolated-margin-transfer` was added\n - `private/change-isolated-margin-leverage` was added\n - `private/user-balance` response updated, new fields `total_isolated_cash_balance` and `isolated_positions` were added\n - `private/user-balance-history` response updated, new field `i` was added\n - `private/get-subaccount-balances` response updated, new fields `total_isolated_cash_balance` and `isolated_positions` were added\n - `private/get-positions` response updated, new fields `isolation_id` and `isolation_type` were added\n - `private/create-order` request updated, new optional fields `isolation_id`, `leverage`, `isolated_margin_amount` were added, `exec_inst` added support for `ISOALTED_MARGIN`\n - `private/close-position` request updated, new optional field `isolation_id` was added\n - `private/get-open-orders` response updated, new fields `isolation_id` and `isolation_type` were added\n - `private/get-order-detail` response updated, new fields `isolation_id` and `isolation_type` were added\n - `private/get-order-history` request updated, new optional field `isolation_id` was added, response updated, new fields `isolation_id` and `isolation_type` were added\n - `private/get-trades` request updated, new optional field `isolation_id` was added, response updated, new fields `isolation_id` and `isolation_type` were added\n - `private/get-transactions` request updated, new optional field `isolation_id` was added, response updated, new fields `isolation_id` and `isolation_type` were added\n - `user.order.{instrument_name}` response updated, new fields `isolation_id` and `isolation_type` were added\n - `user.trade.{instrument_name}` response updated, new fields `isolation_id` and `isolation_type` were added\n - `user.balance` response updated, new fields `total_isolated_cash_balance` and `isolated_positions` were added\n - `user.positions` response updated, new fields `isolation_id`, `leverage`, `isolation_type`, `liquidation_price` and `isolated_margin_balance` were added\n - `user.account_risk` response updated, new fields `total_isolated_cash_balance`, `isolated_positions` were added\n - `user.position_balance` response updated, new field `isolated_positions` was added\n- **2025-03-26**\n - `transaction_time` was added into `user.order.{instrument_name}`\n- **2025-11-18**\n - `public/get-risk-parameters` was added new columns\n- **2025-10-16**\n - `Advanced Order Management API` section was updated\n- **2025-07-17**\n - `private/fiat/fiat-deposit-info` was added\n - `private/fiat/fiat-deposit-history` was added\n - `private/fiat/fiat-withdraw-history` was added\n - `private/fiat/fiat-create-withdraw` was added\n - `private/fiat/fiat-get-bank-accounts` was added\n - `private/fiat/fiat-transaction-quota` was added\n - `private/fiat/fiat-transaction-limit` was added\n- **2025-07-04**\n - `private/create-order` exec_inst was added `SMART_POST_ONLY`\n - `private/create-order-list (LIST)` exec_inst was added `SMART_POST_ONLY`\n - `private/get-open-orders` exec_inst was added `SMART_POST_ONLY`\n - `private/get-order-detail` was added, exec_inst was added `SMART_POST_ONLY`\n - `private/get-order-history` exec_inst was added `SMART_POST_ONLY`\n- **2025-06-10**\n - `private/amend-order` was added\n - `public/get-announcements` was added\n- **2025-05-29**\n - transaction_time_ns field was added into `user.order.{instrument_name}` response\n- **2025-03-14**\n - Removed deprecated attributes system_label in `private/get-accounts`\n- **2025-03-06**\n - Removed deprecated `book.{instrument_name}` default book subscription\n - Removed deprecated 100ms interval from full snapshot `book.{instrument_name}.{depth}` book subscription\n- **2025-03-04**\n - Remove section: `Unified Wallet and System Label`\n- **2025-01-27**\n - `book.{instrument_name}.{depth}` - The following additional update frequencies are now supported: \n Full snapshot subscription (`book_subscription_type=SNAPSHOT`) `500ms` \n Delta subscription (`book_subscription_type=SNAPSHOT_AND_UPDATE`) `100ms`\n- **2024-12-11**\n - `private/create-order` fee_instrument_name was added\n- **2024-10-02**\n - `public/get-risk-parameters` was added\n- **2024-08-15**\n - `private/get-fee-rate` was added\n - `private/get-instrument-fee-rate` was added\n- **2024-07-12**\n - Staking API added: \n `private/staking/stake` \n `private/staking/unstake` \n `private/staking/get-staking-position` \n `private/staking/get-staking-instruments` \n `private/staking/get-open-stake` \n `private/staking/get-stake-history` \n `private/staking/get-reward-history` \n `private/staking/convert` \n `private/staking/get-open-convert` \n `private/staking/get-convert-history` \n `public/staking/get-conversion-rate`\n- **2024-06-27**\n - `private/create-order` self-trade prevent (STP) was added\n - `private/create-order-list (LIST)` self-trade prevent (STP) was added\n- **2024-02-12**\n - `public/get-trades`, `trade.{instrument_name}` subscription, clarification for the public trade side field\n - Side is the side of the taker order\n - `book.{instrument_name}.{depth}` clarifications for book delta sequence number handling and re-subscription\n- **2024-01-04**\n - Market data websocket subscription enhancements:\n - `book.{instrument_name}` - The `subscription` result value is now explicit \n e.g. previous `\"subscription\": \"book.BTC_USD\"` -> new `\"subscription\": \"book.BTC_USD.50\"`\n - `book.{instrument_name}.{depth}` - For delta updates, the fixed 500ms delta full book snapshot heartbeat is replaced with empty delta in the case of no book changes\n - `ticker` - Documented existing 'bs' and 'ks' fields (bid/ask size)\n - `settlement` - For wildcard subscription, the `subscription` result value is now explicit \n e.g. previous `\"subscription\": \"settlement\"` -> new `\"subscription\": \"settlement.BTCUSD-231124\"`\n - Applied consistent field ordering for all market data subscriptions (`book`, `ticker`, `trade`, `candlestick`, `index`, `mark`, `settlement`, `funding`, `estimatedfunding`). \n Result fields are always in the following order: \n `id, method, code, instrument_name, subscription, channel`\n - Market data REST `public/get-trades`\n - Added additional `tn` nanoseconds timestamp field to the trade response\n - Clarified timestamp pagination parameters\n- **2023-12-18**\n - Market Data wildcard ticker subscription removed. Users should use the instrument specific subscription.\n- **2023-12-11**\n - Introduced Market Data subscription limiting. Refer to Market Data Websocket Subscription Limits for more details\n- **2023-10-31**\n - `user.balance`, `private/user-balance` will be updated: \n 1. Existing field total_margin_balance will represent new margin balance calculation without haircut. \n 2. Existing field total_initial_margin previously is made up of position IM only. On effective date, this field will represent the total sum of total_position_im + total_haircut \n 3. New field total_position_im will be introduced to represent initial margin requirement to support open positions and orders \n 4. New field total_haircut will be introduced to represent the total haircut on eligible collateral token assets. Refer to [Smart Cross Margin Enhancement Guide](https://static2.crypto.com/exchange/assets/documents/Exchange%20Smart%20Cross%20Margin%20Enhancement%20Guide%202023.pdf) for details\n - `user.balance`, `user.account_risk`, `private/user-balance`, `private/get-subaccount-balances` will be updated: \n 1. New field collateral_eligible will be introduced to indicate if token is eligible Collateral \n 2. collateral_weight will be deprecated \n 3. New field haircut will be introduced to show haircut of eligible collateral token instead of collateral Weight. Refer to [Smart Cross Margin Enhancement Guide](https://static2.crypto.com/exchange/assets/documents/Exchange%20Smart%20Cross%20Margin%20Enhancement%20Guide%202023.pdf) for details\n- **2023-08-11**\n - `private/create-order-list (LIST)` for batch order creation added\n - `private/cancel-order-list (LIST)` for batch order cancel added\n- **2023-07-31**\n - Market Data Websocket Subscriptions is effective:\n - `funding.{instrument_name}` - channel will return the fixed hourly rate that will settle at the end of the hour.\n - `estimatedfunding.{instrument_name}` - channel will return the estimated hourly rate that will begin in the next interval.\n - Added new \"funding_rate\" and \"estimated_funding_rate\" valuation types for public/get-valuations\n- **2023-06-28**\n - `private/get-deposit-history` added\n - `private/get-withdrawal-history` added\n- **2022-11-30**\n - Support using `client_oid` to query in `private/get-order-detail` REST API\n- **2022-11-10**\n - `USD_Stable_Coin` (aka USD Bundle), will be renamed as `USD`. Customer can test the change in UAT from 2022-11-10 before the change is effective in PROD. Target date for PROD is TBD.\n - Customer can input both `USD` and `USD_Stable_Coin` to mean the same USD Bundle.\n - However, on response, `USD` will be used to mean USD Bundle, instead of `USD_Stable_Coin`.\n- **2022-10-31**\n - Added `private/create-order-list`, `private/create-subaccount-transfer` REST APIs\n - Added `user.account_risk` and `user.position_balance` WebSocket subscriptions\n - Added more `period` in `public/get-candlestick` `candlestick.{time_frame}.{instrument_name}` WebSocket subscription\n- **2022-09-21** - Added **Unified Wallet and System Label** section, to illustrate the transition from multiple wallets into unified wallet.\n- **2022-09-21** - Added new sub-account management endpoints: `private/get-accounts`, `private/create-subaccount-transfer`\n- **2022-09-21** - Added new exchange wallet management endpoints: `private/create-withdrawal`, `private/get-deposit-address`, `private/get-curency-networks`\n- **2022-09-21** - First publish, based on Derivative Exchange API v1.\n\n## Common API References\n\n### Naming Conventions\n\n- All **methods and URLs** in **dash-case**\n- All **parameters** in **snake_case**\n- **Enums** in full **UPPERCASE** and **snake_case**\n\n### Generating the API Key\n\nBefore sending any requests, generate a new API key on the Exchange website under **User Center** → **API**. Note down:\n\n- **API Key**\n- **Secret Key**\n\nDefault settings are \"Can Read\" only; you can add or remove permissions via the Web UI. You may optionally specify a whitelist of IP addresses; if set, the API can only be used from those IPs.\n\n### REST API Root Endpoints\n\nREST API requests must be sent with **Content-Type: application/json**.\n\n| Environment | REST API |\n|-------------|----------|\n| **UAT Sandbox** | `https://uat-api.3ona.co/exchange/v1/{method}` |\n| **Production** | `https://api.crypto.com/exchange/v1/{method}` |\n\n### Websocket Root Endpoints\n\n| Environment | Websocket (User API) |\n|-------------|----------|\n| **UAT Sandbox** | `wss://uat-stream.3ona.co/exchange/v1/user` |\n| **Production** | `wss://stream.crypto.com/exchange/v1/user` |\n\n| Environment | Websocket (Market Data) |\n|-------------|----------|\n| **UAT Sandbox** | `wss://uat-stream.3ona.co/exchange/v1/market` |\n| **Production** | `wss://stream.crypto.com/exchange/v1/market` |\n\n### Rate Limits\n\n#### REST API\n\nFor authenticated calls, rate limits are per API method, per API key:\n\n| Method | Limit |\n|--------|-------|\n| `private/create-order`, <br/>`private/cancel-order`, <br/>`private/cancel-all-orders` | 15 requests per 100ms each |\n| `private/get-order-detail` | 30 requests per 100ms |\n| `private/get-trades` | 1 request per second |\n| `private/get-order-history` | 1 request per second |\n| All others | 3 requests per 100ms each |\n\nFor public market data calls, rate limits are per API method, per IP address:\n\n| Method | Limit |\n|--------|-------|\n| All | 100 requests per second each |\n\n#### Staking\n\n| Method | Limit |\n|--------|-------|\n| All | 50 requests per second each |\n\n#### Websocket\n\n| Method | Limit |\n|--------|-------|\n| User API | 150 requests per second |\n| Market Data | 100 requests per second |\n\n### Request Format\n\nThe following information applies to both REST API and websockets commands:\n\n| Name | Type | Required | Description |\n|------|------|----------|-------------|\n| id | long | Y | Request identifier (0 to 9,223,372,036,854,775,807). Response echoes the same id. |\n| method | string | Y | The method to be invoked (e.g. `private/get-order-detail`). |\n| params | object | Y | Parameters for the method. Use `{}` when a method has no parameters. |\n| api_key | string | Depends | API key. Required for **private** methods (see Digital Signature). |\n| sig | string | Depends | Digital signature. Required for **private** methods. |\n| nonce | long | Y | Current timestamp in **milliseconds** since the Unix epoch. |\n\n**⚠️ All numbers must be strings, and must be wrapped in double quotes. e.g. \"12.34\", instead of 12.34.**\n\n### Digital Signature\n\nFor REST API, only private methods require a digital signature (as `sig`) and API key (as `api_key`) to be passed in. These private endpoints are only accessible by authenticated users.\n\nFor WebSocket (User API), the `public/auth` command has to be invoked once per session, with the digital signature (as `sig`) and API key (as `api_key`) as part of the request. Once authenticated, you will gain access to user-specific commands and no longer need to pass in the digital signature and API key for the duration of the session.\n\nThe authentication is based on the pairing of the API Key, along with the HMAC-SHA256 hash of the request parameters using the API Secret as the cryptographic key.\n\n**⚠️ You should NEVER explicitly include the API Secret Key in plain-text in your request**\n\nThe algorithm for generating the HMAC-SHA256 signature is as follows:\n\n1. If \"params\" exist in the request, sort the request parameter keys in ascending order.\n2. Combine all the ordered parameter keys as key + value (no spaces, no delimiters). Let's call this the parameter string\n3. Next, do the following: method + id + api_key + parameter string + nonce\n4. Use HMAC-SHA256 to hash the above using the API Secret as the cryptographic key\n5. Encode the output as a hex string -- this is your Digital Signature\n\nSince all parameters for calculating the HMAC-SHA256 hash are present in the request except the API Secret, the server-side will independently calculate the Digital Signature as well, and if done correctly, the computed hashes will match.\n\nBesides, for JavaScript client calling `private/get-order-detail` API, it is highly recommended to use STRING format of `order_id` in the JSON request payload, in order to guarantee the correctness of Digital Signature.\n\n#### JavaScript Example\n\n```javascript\nconst crypto = require(\"crypto-js\");\n\nconst signRequest = (request_body, api_key, secret) => {\n const { id, method, params, nonce } = request_body;\n\n function isObject(obj) { \n return obj !== undefined && obj !== null && obj.constructor == Object; \n }\n function isArray(obj) { \n return obj !== undefined && obj !== null && obj.constructor == Array; \n }\n function arrayToString(obj) { \n return obj.reduce((a,b) => { return a + (isObject(b) ? objectToString(b) : (isArray(b) ? arrayToString(b) : b)); }, \"\"); \n }\n function objectToString(obj) { \n return (obj == null ? \"\" : Object.keys(obj).sort().reduce((a, b) => { \n return a + b + (isArray(obj[b]) ? arrayToString(obj[b]) : (isObject(obj[b]) ? objectToString(obj[b]) : obj[b])); \n }, \"\")); \n }\n\n const paramsString = objectToString(params);\n\n const sigPayload = method + id + api_key + paramsString + nonce;\n request_body.sig = crypto.HmacSHA256(sigPayload, secret).toString(crypto.enc.Hex);\n\n return request_body;\n};\n\nconst apiKey = \"token\"; /* User API Key */\nconst apiSecret = \"secretKey\"; /* User API Secret */\n\nlet request = {\n id: \"11\",\n method: \"private/get-order-detail\",\n api_key: apiKey,\n params: {\n order_id: \"53287421324\"\n },\n nonce: \"1587846358253\",\n};\n\nconst requestBody = JSON.stringify(signRequest(request, apiKey, apiSecret));\n```\n\n#### Python Example\n\n```python\nimport hmac\nimport hashlib\nimport time\n\nAPI_KEY = \"API_KEY\"\nSECRET_KEY = \"SECRET_KEY\"\n\nreq = {\n \"id\": \"14\",\n \"method\": \"private/create-order-list\",\n \"api_key\": API_KEY,\n \"params\": {\n \"contingency_type\": \"LIST\",\n \"order_list\": [\n {\n \"instrument_name\": \"ONE_USDT\",\n \"side\": \"BUY\",\n \"type\": \"LIMIT\",\n \"price\": \"0.24\",\n \"quantity\": \"1.0\"\n },\n {\n \"instrument_name\": \"ONE_USDT\",\n \"side\": \"BUY\",\n \"type\": \"STOP_LIMIT\",\n \"price\": \"0.27\",\n \"quantity\": \"1.0\",\n \"trigger_price\": \"0.26\"\n }\n ]\n },\n \"nonce\": str(int(time.time() * 1000))\n}\n\n# First ensure the params are alphabetically sorted by key\nparam_str = \"\"\n\nMAX_LEVEL = 3\n\n\ndef params_to_str(obj, level):\n if level >= MAX_LEVEL:\n return str(obj)\n\n return_str = \"\"\n for key in sorted(obj):\n return_str += key\n if obj[key] is None:\n return_str += 'null'\n elif isinstance(obj[key], list):\n for subObj in obj[key]:\n return_str += params_to_str(subObj, level + 1)\n else:\n return_str += str(obj[key])\n return return_str\n\n\nif \"params\" in req:\n param_str = params_to_str(req['params'], 0)\n\npayload_str = req['method'] + str(req['id']) + req['api_key'] + param_str + str(req['nonce'])\n\nreq['sig'] = hmac.new(\n bytes(str(SECRET_KEY), 'utf-8'),\n msg=bytes(payload_str, 'utf-8'),\n digestmod=hashlib.sha256\n).hexdigest()\n```\n\n#### C# Example\n\n```csharp\nusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Security.Cryptography;\nusing System.Text;\n\nprivate const string API_KEY = \"YOUR_API_KEY\";\nprivate const string API_SECRET = \"YOUR_API_SECRET\";\n\nprivate static string GetSign(Dictionary<string, object> request)\n{\n var paramsDict = request[\"params\"] as Dictionary<string, object>;\n\n // Ensure the params are alphabetically sorted by key\n // Note: For nested objects or lists, implement recursive sorting similar to JS/Python examples\n string paramString = paramsDict != null\n ? string.Join(\"\", paramsDict.Keys.OrderBy(key => key).Select(key => key + paramsDict[key]))\n : \"\";\n\n string sigPayload = request[\"method\"].ToString()\n + request[\"id\"].ToString()\n + API_KEY\n + paramString\n + request[\"nonce\"].ToString();\n\n using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(API_SECRET)))\n {\n var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(sigPayload));\n return BitConverter.ToString(hash).Replace(\"-\", \"\").ToLowerInvariant();\n }\n}\n```\n\n#### Java Example\n\n```java\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport lombok.AllArgsConstructor;\nimport lombok.Builder;\nimport lombok.Data;\nimport lombok.NoArgsConstructor;\n\nimport java.util.Map;\n\n@Data\n@Builder\n@NoArgsConstructor\n@AllArgsConstructor\npublic class ApiRequestJson {\n private Long id;\n private String method;\n private Map<String, Object> params;\n private String sig;\n\n @JsonProperty(\"api_key\")\n private String apiKey;\n\n private Long nonce;\n}\n\n//------------\n\nimport java.math.BigDecimal;\nimport java.nio.charset.StandardCharsets;\nimport java.security.InvalidKeyException;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.TreeMap;\nimport javax.crypto.Mac;\nimport javax.crypto.spec.SecretKeySpec;\nimport org.apache.commons.codec.binary.Hex;\n\npublic class SigningUtil {\n\n private static final String HMAC_SHA256 = \"HmacSHA256\";\n private static final int MAX_LEVEL = 3;\n\n public static boolean verifySignature(ApiRequestJson apiRequestJson, String secret) {\n try {\n return genSignature(apiRequestJson, secret).equalsIgnoreCase(apiRequestJson.getSig());\n } catch (Exception e) {\n return false;\n }\n }\n\n @SuppressWarnings(\"unchecked\")\n public static String getParamString(final Object paramObject) {\n StringBuilder sb = new StringBuilder();\n appendParamString(sb, paramObject, 0);\n return sb.toString();\n }\n\n\n @SuppressWarnings(\"unchecked\")\n private static void appendParamString(final StringBuilder paramsStringBuilder, final Object paramObject, final int level) {\n if (level >= MAX_LEVEL) {\n paramsStringBuilder.append(paramObject.toString());\n return;\n }\n\n if (paramObject instanceof Map) {\n TreeMap<String, Object> params = new TreeMap<>((Map) paramObject);\n for (Map.Entry<String, Object> entry : params.entrySet()) {\n if (entry.getValue() instanceof Double) {\n paramsStringBuilder\n .append(entry.getKey())\n .append((new BigDecimal(entry.getValue().toString()))\n .stripTrailingZeros()\n .toPlainString());\n } else if (entry.getValue() instanceof List || entry.getValue() instanceof Map) {\n paramsStringBuilder\n .append(entry.getKey());\n appendParamString(paramsStringBuilder, entry.getValue(), level + 1);\n } else {\n paramsStringBuilder\n .append(entry.getKey())\n .append(entry.getValue());\n }\n }\n } else if (paramObject instanceof List) {\n List list = (List) paramObject;\n for (Object o : list) {\n appendParamString(paramsStringBuilder, o, level + 1);\n }\n } else {\n paramsStringBuilder.append(paramObject.toString());\n }\n }\n\n public static String genSignature(ApiRequestJson apiRequestJson, String secret)\n throws NoSuchAlgorithmException, InvalidKeyException {\n final byte[] byteKey = secret.getBytes(StandardCharsets.UTF_8);\n Mac mac = Mac.getInstance(HMAC_SHA256);\n SecretKeySpec keySpec = new SecretKeySpec(byteKey, HMAC_SHA256);\n mac.init(keySpec);\n\n String paramsString = \"\";\n\n if (apiRequestJson.getParams() != null) {\n paramsString += getParamString(apiRequestJson.getParams());\n }\n\n String sigPayload =\n apiRequestJson.getMethod()\n + apiRequestJson.getId()\n + apiRequestJson.getApiKey()\n + paramsString\n + (apiRequestJson.getNonce() == null ? \"\" : apiRequestJson.getNonce());\n\n byte[] macData = mac.doFinal(sigPayload.getBytes(StandardCharsets.UTF_8));\n\n return Hex.encodeHexString(macData);\n }\n\n public static ApiRequestJson sign(ApiRequestJson apiRequestJson, String secret)\n throws InvalidKeyException, NoSuchAlgorithmException {\n apiRequestJson.setSig(genSignature(apiRequestJson, secret));\n\n return apiRequestJson;\n }\n\n public static void main(String[] argv) throws InvalidKeyException, NoSuchAlgorithmException {\n ApiRequestJson apiRequestJson = ApiRequestJson.builder()\n .id(11L)\n .apiKey(\"token\")\n .method(\"public/auth\")\n .nonce(1589594102779L)\n .build();\n\n System.out.println(genSignature(apiRequestJson, \"secretKey\"));\n\n System.out.println(sign(apiRequestJson, \"secretKey\"));\n\n }\n}\n```\n\n### Response Format\n\n| Name | Type | Description |\n|------|------|-------------|\n| id | long | Original request identifier (or -1 if omitted in request). |\n| method | string | Method invoked. |\n| result | object | Result object (present on success). |\n| code | int | 0 for success; see Response and Reason Codes |\n| message | string | Optional; server or error message. |\n| original | string | Optional; original request as escaped string (for error cases). |\n\n### Response and Reason Codes\n\n#### 200 OK\n\n| HTTP Status | Code | Message Code / Description |\n|-------------|------|----------------------------|\n| 200 | 0 | --:<br/><br/>Success |\n| 200 | 40401 | NOT_FOUND:<br/><br/>Not found |\n| 200 | 43012 | SELF_TRADE_PREVENTION:<br/><br/>Canceled due to Self Trade Prevention |\n\n#### 400 Bad Request\n\n| HTTP Status | Code | Message Code / Description |\n|-------------|------|----------------------------|\n| 400 | 202 | ACCOUNT_IS_SUSPENDED:<br/><br/>Account is suspended |\n| 400 | 204 | DUPLICATE_CLORDID:<br/><br/>Duplicate client order id |\n| 400 | 207 | NO_MARK_PRICE:<br/><br/>No mark price |\n| 400 | 208 | INSTRUMENT_NOT_TRADABLE:<br/><br/>Instrument is not tradable |\n| 400 | 209 | INVALID_INSTRUMENT:<br/><br/>Instrument is invalid |\n| 400 | 213 | INVALID_ORDERQTY:<br/><br/>Invalid order quantity |\n| 400 | 218 | INVALID_ORDTYPE:<br/><br/>Invalid order_type |\n| 400 | 220 | INVALID_SIDE:<br/><br/>Invalid side |\n| 400 | 221 | INVALID_TIF:<br/><br/>Invalid time_in_force |\n| 400 | 222 | STALE_MARK_PRICE:<br/><br/>Stale mark price |\n| 400 | 223 | NO_CLORDID:<br/><br/>No client order id |\n| 400 | 224 | REJ_BY_MATCHING_ENGINE:<br/><br/>Rejected by matching engine |\n| 400 | 225 | EXCEED_MAXIMUM_ENTRY_LEVERAGE:<br/><br/>Exceeds maximum entry leverage |\n| 400 | 226 | INVALID_LEVERAGE:<br/><br/>Invalid leverage |\n| 400 | 227 | INVALID_SLIPPAGE:<br/><br/>Invalid slippage |\n| 400 | 228 | INVALID_FLOOR_PRICE:<br/><br/>Invalid floor price |\n| 400 | 229 | INVALID_REF_PRICE:<br/><br/>Invalid ref price |\n| 400 | 230 | INVALID_REF_PRICE_TYPE:<br/><br/>Invalid ref price type |\n| 400 | 308 | INVALID_PRICE:<br/><br/>Invalid price |\n| 400 | 314 | EXCEEDS_MAX_ORDER_SIZE:<br/><br/>Exceeds max order size |\n| 400 | 315 | FAR_AWAY_LIMIT_PRICE:<br/><br/>Far away limit price |\n| 400 | 318 | EXCEEDS_MAX_ALLOWED_ORDERS:<br/><br/>Exceeds max allowed orders |\n| 400 | 319 | EXCEEDS_MAX_POSITION_SIZE:<br/><br/>Exceeds max position size |\n| 400 | 401 | ACCOUNT_DOES_NOT_EXIST:<br/><br/>Account does not exist |\n| 400 | 408 | MARGIN_UNIT_IS_SUSPENDED:<br/><br/>Margin unit is suspended |\n| 400 | 30024 | MAX_AMOUNT_VIOLATED:<br/><br/>If create-withdrawal call quantity > max_withdrawal_balance in user-balance api |\n| 400 | 40001 | BAD_REQUEST:<br/><br/>Bad request |\n| 400 | 40002 | METHOD_NOT_FOUND:<br/><br/>Method not found |\n| 400 | 40003 | INVALID_REQUEST:<br/><br/>Invalid request |\n| 400 | 40004 | MISSING_OR_INVALID_ARGUMENT:<br/><br/>Required argument is blank or missing |\n| 400 | 40005 | INVALID_DATE:<br/><br/>Invalid date |\n| 400 | 40006 | DUPLICATE_REQUEST:<br/><br/>Duplicate request received |\n| 400 | 40102 | INVALID_NONCE:<br/><br/>Nonce value differs by more than 60 seconds |\n| 400 | 40107 | EXCEED_MAX_SUBSCRIPTIONS:<br/><br/>Session subscription limit has been exceeded |\n| 400 | 50001 | ERR_INTERNAL:<br/><br/>Internal error |\n| 400 | 50002 | DW_CREDIT_LINE_NOT_MAINTAINED:<br/><br/>If create-withdrawal call breaches credit line check |\n\n#### 401 Unauthorized\n\n| HTTP Status | Code | Message Code / Description |\n|-------------|------|----------------------------|\n| 401 | 40101 | UNAUTHORIZED:<br/><br/>Not authenticated, or key/signature incorrect |\n| 401 | 40103 | IP_ILLEGAL:<br/><br/>IP address not whitelisted |\n|
# --- truncated at 32 KB (594 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/crypto-com/refs/heads/main/openapi/crypto-com-exchange-openapi.yml