Skip to main content
Back to Learn
intermediatetradingdemopositions

Demo Trading Guide

Open and close positions on the eToro demo account — a production-grade sandbox for testing your trading logic.

3 min readBy eToro Developer Relations

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

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/history for trade history

Rate Limits

Trading endpoints (POST/PUT/DELETE) are limited to 20 requests per minute. Plan your order logic accordingly.

Next Steps

We use cookies to improve your experience. By using this site, you agree to our use of cookies. Privacy Policy (opens in new tab)