Demo Trading Guide
Open and close positions on the eToro demo account — a production-grade sandbox for testing your trading logic.
Overview
The eToro Demo Trading API is a full clone of the real trading environment. You can open and close positions, place limit orders, and manage your portfolio — all with virtual money. When your logic works in demo, switch /demo/ to /real/ in your endpoint paths to go live.
Prerequisites
- API keys with Write permissions (see Getting Started)
- An instrument ID (see Market Data Deep Dive)
Opening a Position by Amount
Place a market order specifying a cash amount:
curl -X POST https://public-api.etoro.com/api/v1/trading/execution/demo/market-open-orders/by-amount \
-H "x-api-key: $ETORO_API_KEY" \
-H "x-user-key: $ETORO_USER_KEY" \
-H "x-request-id: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"InstrumentId": 100000,
"Amount": 1000,
"Leverage": 1,
"IsBuy": true
}'
Note the PascalCase field names — InstrumentId, Amount, Leverage, IsBuy. This is required by the API.
Using JavaScript
const crypto = require('crypto');
const headers = {
'x-api-key': process.env.ETORO_API_KEY,
'x-user-key': process.env.ETORO_USER_KEY,
'x-request-id': crypto.randomUUID(),
'Content-Type': 'application/json',
};
const res = await fetch(
'https://public-api.etoro.com/api/v1/trading/execution/demo/market-open-orders/by-amount',
{
method: 'POST',
headers,
body: JSON.stringify({
InstrumentId: 100000,
Amount: 1000,
Leverage: 1,
IsBuy: true,
}),
}
);
const order = await res.json();
console.log('Order placed:', order);
Opening a Position by Units
Alternatively, specify the number of units instead of a cash amount:
curl -X POST https://public-api.etoro.com/api/v1/trading/execution/demo/market-open-orders/by-units \
-H "x-api-key: $ETORO_API_KEY" \
-H "x-user-key: $ETORO_USER_KEY" \
-H "x-request-id: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"InstrumentId": 100000,
"Amount": 1000,
"Leverage": 1,
"IsBuy": true
}'
Placing a Limit Order
Set a price target and the order executes when the market reaches it:
curl -X POST https://public-api.etoro.com/api/v1/trading/execution/demo/market-if-touched-orders \
-H "x-api-key: $ETORO_API_KEY" \
-H "x-user-key: $ETORO_USER_KEY" \
-H "x-request-id: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"InstrumentId": 100000,
"Amount": 1000,
"Leverage": 1,
"IsBuy": true
}'
Closing a Position
Close an open position using its position ID:
curl -X POST https://public-api.etoro.com/api/v1/trading/execution/demo/market-close-orders/positions/{positionId} \
-H "x-api-key: $ETORO_API_KEY" \
-H "x-user-key: $ETORO_USER_KEY" \
-H "x-request-id: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"UnitsToDeduct": null
}'
Set UnitsToDeduct to null for a full close, or pass a number for a partial close.
Checking Your Portfolio
View all open positions and P&L:
curl https://public-api.etoro.com/api/v1/trading/demo/portfolio \
-H "x-api-key: $ETORO_API_KEY" \
-H "x-user-key: $ETORO_USER_KEY" \
-H "x-request-id: $(uuidgen)"
Cancelling Orders
Cancel pending orders before they execute:
# Cancel an open order
curl -X DELETE https://public-api.etoro.com/api/v1/trading/execution/demo/market-open-orders/{orderId} \
-H "x-api-key: $ETORO_API_KEY" \
-H "x-user-key: $ETORO_USER_KEY" \
-H "x-request-id: $(uuidgen)"
# Cancel a limit order
curl -X DELETE https://public-api.etoro.com/api/v1/trading/execution/demo/market-if-touched-orders/{orderId} \
-H "x-api-key: $ETORO_API_KEY" \
-H "x-user-key: $ETORO_USER_KEY" \
-H "x-request-id: $(uuidgen)"
Going Live
When you're confident your logic works correctly in demo, switch from demo to real:
- Change
/demo/to/real/in all endpoint paths - Ensure your API key has Real environment permissions
- The real trading API also includes
GET /api/v1/trading/real/historyfor trade history
Rate Limits
Trading endpoints (POST/PUT/DELETE) are limited to 20 requests per minute. Plan your order logic accordingly.
Next Steps
- API Reference — full endpoint documentation
- Getting Started — key setup and first API call