The py3cw
library likely follows this logic (based on community reports and reverse-engineering the source):
Send the POST /v2/smart_trades
request.
Receive 204 No Content
response.
Immediately fetch the latest trades using:
GET /v2/smart_trades?account_id=XXX&limit=1
or
GET /v2/smart_trades?account_id=XXX&pair=YYY
Optionally filter by status=created
or check timestamps to get the most recent.
The trade ID
is then extracted from that result.
Recommended Solution in Your Node.js Code
After receiving the 204
, immediately fetch the latest smart trades and extract the newest one:
const axios = require('axios');
const crypto = require('crypto');
class ThreeCommasClient {
constructor(apiKey, apiSecret) {
this.apiKey = apiKey;
this.apiSecret = apiSecret;
this.baseUrl = 'https://api.3commas.io/v2';
}
_generateSignature(timestamp, path, data = '') {
return crypto
.createHmac('sha256', this.apiSecret)
.update(timestamp + path + data)
.digest('hex');
}
_buildPath(entity, actionId = null, subId = null) {
let path = `/${entity}`;
if (actionId) path += `/${actionId}`;
if (subId) path += `/${subId}`;
return path;
}
async _sendRequest(method, path, payload = null, query = '') {
const timestamp = Date.now().toString();
const dataStr = payload ? JSON.stringify(payload) : '';
const fullPath = path + query;
const signature = this._generateSignature(timestamp, fullPath, dataStr);
try {
const response = await axios({
method,
url: `${this.baseUrl}${path}${query}`,
headers: {
'APIKEY': this.apiKey,
'Signature': signature,
'Nonce': timestamp,
'Content-Type': 'application/json'
},
...(payload && ['POST', 'PUT'].includes(method) && { data: dataStr }),
validateStatus: status => status === 204 || status < 400
});
return [null, response.status === 204 ? null : response.data];
} catch (error) {
const message = error.response?.data || error.message;
return [{ error: true, msg: message }, {}];
}
}
async request(entity, action, actionId = null, subId = null, payload = null) {
const path = this._buildPath(entity, actionId, subId);
// Special case: smart_trades new (204 response handling)
if (entity === 'smart_trades' && action === 'new') {
const [postErr] = await this._sendRequest('POST', path, payload);
if (postErr) return [postErr, {}];
// Immediately fetch the latest smart trade to get the ID
const query = `?account_id=${payload.account_id}&limit=1`;
const [getErr, getData] = await this._sendRequest('GET', '/smart_trades', null, query);
if (getErr) return [getErr, {}];
return getData?.length ? [null, getData[0]] : [null, { success: true, message: 'Trade created, but ID not retrieved' }];
}
// Generic handler
const methodMap = {
get: 'GET',
post: 'POST',
put: 'PUT',
delete: 'DELETE',
new: 'POST',
update: 'PUT'
};
const method = methodMap[action.toLowerCase()] || 'GET';
return this._sendRequest(method, path, payload);
}
}
// Usage Example
const client = new ThreeCommasClient('my_api_key', 'my_api_secret');
async function createSmartTrade() {
const payload = {
account_id: 12345678,
pair: 'ADA_USDT',
instant: true,
position: {
type: 'buy',
units: { value: '10' },
order_type: 'market'
},
take_profit: { enabled: false },
stop_loss: { enabled: false },
demo: true
};
const [error, data] = await client.request('smart_trades', 'new', null, null, payload);
if (error) {
console.error('❌ Failed to create smart trade:', error.msg);
} else {
console.log('✅ Smart trade created:', data);
}
}
Optional Improvement: Add Retry with Delay
Since the trade may take a few hundred milliseconds to appear, you can add a short retry delay loop (e.g., check up to 3 times with 500ms intervals) if your app needs better reliability.
Answers to Your Specific Questions
1. How does
py3cw
get the trade ID when the API returns a 204?
By immediately querying/v2/smart_trades
for the most recent trade.
2. Is there a way to get the trade ID immediately in Node.js?
Yes — use the same workaround: fetch latest smart trade after 204 response.
3. Are there special headers or parameters I should be including?
No extra headers required beyond what's already there. Just make the follow-up GET request.
4. Is there an alternative endpoint or approach?
Not really. 3Commas chose 204 for smart trade creation. The only workaround is fetching the most recent trade from/v2/smart_trades
.