etoro-apps
使代理能够与 eToro API 交互,以访问市场数据、投资组合和社交功能,并以编程方式执行交易。支持 OAuth SSO 和手动 API 密钥身份验证。
安装 / 下载方式
TotalClaw CLI推荐
totalclaw install totalclaw:totalclaw~marian2js-etoro-appscURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/totalclaw%3Atotalclaw~marian2js-etoro-apps/file -o marian2js-etoro-apps.md## 概述(中文)
使代理能够与 eToro API 交互,以访问市场数据、投资组合和社交功能,并以编程方式执行交易。支持 OAuth SSO 和手动 API 密钥身份验证。
## 原文
# eToro Public API
Base URL: `https://public-api.etoro.com/api/v1`
## About
This skill allows to interact with the user's eToro account programatically, including executing trades.
## Authentication & Required Headers
The eToro API supports **two** authentication methods. Both use the same base URL and endpoints — only the auth headers differ.
### Method 1 — OAuth SSO (Bearer Token)
If the user authenticated via **"Login with eToro"** (SSO/OAuth), an `access_token` is available from the token exchange.
**Headers (every request):**
- `x-request-id`: unique UUID per request
- `Authorization`: `Bearer <access_token>`
Where `access_token` comes from:
1. User clicks "Login with eToro" → redirects to `https://www.etoro.com/sso/` with PKCE challenge.
2. User authenticates on eToro's side.
3. eToro redirects back with an authorization `code`.
4. The code is exchanged for tokens via `POST https://www.etoro.com/sso/oidc/token`:
- `grant_type=authorization_code`
- `code=<auth_code>`
- `redirect_uri=<callback_url>`
- `code_verifier=<pkce_verifier>`
- Plus `Authorization: Basic <base64(client_id:client_secret)>` header
5. Response contains:
- `access_token` — **this is the Bearer token for API calls** (~2130 chars, JWT)
- `id_token` — JWT with user identity (`sub` claim = 128-char encoded user ID)
- `token_type`: `"Bearer"`
- `expires_in`: (varies)
Example:
```bash
curl -X GET "https://public-api.etoro.com/api/v1/watchlists" \
-H "x-request-id: <UUID>" \
-H "Authorization: Bearer <access_token>"
```
### Method 2 — Manual API Keys
If the user provides API keys manually (no OAuth), use key-based auth.
**Keys (request from the user on install)**
- **Public API Key**: application
- **User Key**: user account
- **Environment**: Real Portfolio or Virtual Portfolio (real/demo)
**Key generation (user-facing):**
1. Log in to eToro.
2. Settings > Trading.
3. Create New Key.
4. Choose **Environment** (Real or Virtual/Demo) and **Permissions** (Read or Write).
5. Verify identity and copy the generated User Key.
**Headers (every request):**
- `x-request-id`: unique UUID per request
- `x-api-key`: Public API Key (`<PUBLIC_KEY>`)
- `x-user-key`: User Key (`<USER_KEY>`)
Example:
```bash
curl -X GET "https://public-api.etoro.com/api/v1/watchlists" \
-H "x-request-id: <UUID>" \
-H "x-api-key: <PUBLIC_KEY>" \
-H "x-user-key: <USER_KEY>"
```
### Choosing the Auth Method in Code
When making requests, check which credentials are available:
```typescript
if (ctx.accessToken) {
// SSO auth — Bearer token from OAuth token exchange
headers["Authorization"] = `Bearer ${ctx.accessToken}`;
} else {
// Manual API key auth
headers["x-api-key"] = ctx.apiKey;
headers["x-user-key"] = ctx.userKey;
}
```
## Request Conventions
- **All paths below are relative to the Base URL** (which already includes `/api/v1`).
Example: `GET /watchlists` means `GET https://public-api.etoro.com/api/v1/watchlists`.
- Query params go in the URL, path params go in the URL path.
- For query params that are documented as `array`, send them as **comma-separated values** (e.g., `instrumentIds=1001,1002`).
- Pagination patterns vary by endpoint:
- Search: `pageNumber`, `pageSize`
- People search & trade history: `page`, `pageSize`
- Feeds: `take`, `offset`
- Watchlist items listing: `pageNumber`, `itemsPerPage`
- **Casing matters** for request bodies:
- Trading execution uses **PascalCase** fields (e.g., `InstrumentID`, `IsBuy`, `Leverage`).
- Market close body uses `InstrumentId` (capital I, lowercase d).
- Watchlist items use `ItemId`, `ItemType`, `ItemRank`.
- Feeds post body uses lower camel (`owner`, `message`, `tags`, `mentions`, `attachments`).
- Some responses may use different casing for similar concepts (e.g., `instrumentId` vs `InstrumentID`). When extracting IDs, handle both if present.
## Demo vs Real Trading
- Use **demo execution endpoints** (contain `/demo/`) for testing and paper trading.
- Use **non-demo execution endpoints** for real trading.
- For portfolio/PnL:
- Demo: `/trading/info/demo/*`
- Real: `/trading/info/portfolio` and `/trading/info/real/pnl`
- Ensure your key environment matches the endpoint (Virtual vs Real). Each User Key is associated with a specific environment.
## Use Defaults
- Important: You don't need to specify all parameters. If the user doesn't specify leverage for example, don't send it on the API request.
## Quick Start (Demo Trade)
1. **Resolve `instrumentId`** using search.
`fields` is required on search requests.
```bash
curl -X GET "https://public-api.etoro.com/api/v1/market-data/search?internalSymbolFull=BTC&fields=instrumentId,internalSymbolFull,displayname" \
-H "Authorization: Bearer <access_token>" \
-H "x-request-id: <UUID>"
```
2. **Place a demo market order by amount** (PascalCase body):
```bash
curl -X POST "https://public-api.etoro.com/api/v1/trading/execution/demo/market-open-orders/by-amount" \
-H "Authorization: Bearer <access_token>" \
-H "x-request-id: <UUID>" \
-H "Content-Type: application/json" \
-d '{
"InstrumentID": 100000,
"IsBuy": true,
"Leverage": 1,
"Amount": 100
}'
```
> **Note:** The examples above use OAuth (Bearer token). For API key auth, replace the `Authorization` header with `x-api-key` and `x-user-key` headers instead.
## Common IDs
- `instrumentId`: from Search or Instruments metadata
- `positionId`: from Portfolio endpoints
- `orderId`: from execution responses or Portfolio endpoints
- `marketId`: used by instrument feed endpoints (typically available in instrument metadata/search fields)
- `userId`: numeric eToro user ID (often referred to as **CID** in responses; discover via People endpoints/search)
- `watchlistId`: from watchlists list/create endpoints
## Market Data (Requests)
**Search instruments**
- `GET /market-data/search`
- Required query: `fields` (comma-separated list of instrument fields to return)
- Optional: `searchText`, `pageSize`, `pageNumber`, `sort`
- The Search endpoint supports filtering by fields returned in results; for exact symbol lookup, use `internalSymbolFull` as a query param and verify the exact match.
- Recommended minimal `fields` when you need IDs: include the instrument identifier (may appear as `instrumentId` or `InstrumentID`), plus `internalSymbolFull` and `displayname` (and `marketId` if you plan to use Feeds).
**Metadata**
- `GET /market-data/instruments`
Filters: `instrumentIds`, `exchangeIds`, `stocksIndustryIds`, `instrumentTypeIds`.
**Prices & history**
- `GET /market-data/instruments/rates`
Required: `instrumentIds` (comma-separated).
- `GET /market-data/instruments/history/closing-price`
Returns historical closing prices for all instruments (bulk).
- `GET /market-data/instruments/{instrumentId}/history/candles/{direction}/{interval}/{candlesCount}`
`direction`: `asc` or `desc`. `candlesCount` max 1000.
Use only supported `interval` values (confirm via docs if unsure).
**Reference data**
- `GET /market-data/exchanges` (optional `exchangeIds`)
- `GET /market-data/instrument-types`
- `GET /market-data/stocks-industries` (optional `stocksIndustryIds`)
## Trading Execution (Requests)
> Requires appropriate permissions (typically **Write**) and the correct environment (Demo vs Real).
### Market Open Orders (by amount)
Endpoints:
- `POST /trading/execution/demo/market-open-orders/by-amount`
- `POST /trading/execution/market-open-orders/by-amount`
Body (PascalCase, JSON):
- **Required:** `InstrumentID`, `IsBuy`, `Leverage`, `Amount`
- **Optional:** `StopLossRate`, `TakeProfitRate`, `IsTslEnabled`, `IsNoStopLoss`, `IsNoTakeProfit`
### Market Open Orders (by units)
Endpoints:
- `POST /trading/execution/demo/market-open-orders/by-units`
- `POST /trading/execution/market-open-orders/by-units`
Body (PascalCase, JSON):
- **Requ