{
  "schemaVersion": "1.0",
  "item": {
    "slug": "etoro-apps",
    "name": "eToro Apps",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/marian2js/etoro-apps",
    "canonicalUrl": "https://clawhub.ai/marian2js/etoro-apps",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/etoro-apps",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=etoro-apps",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/etoro-apps"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/etoro-apps",
    "agentPageUrl": "https://openagent3.xyz/skills/etoro-apps/agent",
    "manifestUrl": "https://openagent3.xyz/skills/etoro-apps/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/etoro-apps/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "eToro Public API",
        "body": "Base URL: https://public-api.etoro.com/api/v1"
      },
      {
        "title": "About",
        "body": "This skill allows to interact with the user's eToro account programatically, including executing trades."
      },
      {
        "title": "Authentication & Required Headers",
        "body": "The eToro API supports two authentication methods. Both use the same base URL and endpoints — only the auth headers differ."
      },
      {
        "title": "Method 1 — OAuth SSO (Bearer Token)",
        "body": "If the user authenticated via \"Login with eToro\" (SSO/OAuth), an access_token is available from the token exchange.\n\nHeaders (every request):\n\nx-request-id: unique UUID per request\nAuthorization: Bearer <access_token>\n\nWhere access_token comes from:\n\nUser clicks \"Login with eToro\" → redirects to https://www.etoro.com/sso/ with PKCE challenge.\nUser authenticates on eToro's side.\neToro redirects back with an authorization code.\nThe code is exchanged for tokens via POST https://www.etoro.com/sso/oidc/token:\n\ngrant_type=authorization_code\ncode=<auth_code>\nredirect_uri=<callback_url>\ncode_verifier=<pkce_verifier>\nPlus Authorization: Basic <base64(client_id:client_secret)> header\n\n\nResponse contains:\n\naccess_token — this is the Bearer token for API calls (~2130 chars, JWT)\nid_token — JWT with user identity (sub claim = 128-char encoded user ID)\ntoken_type: \"Bearer\"\nexpires_in: (varies)\n\nExample:\n\ncurl -X GET \"https://public-api.etoro.com/api/v1/watchlists\" \\\n  -H \"x-request-id: <UUID>\" \\\n  -H \"Authorization: Bearer <access_token>\""
      },
      {
        "title": "Method 2 — Manual API Keys",
        "body": "If the user provides API keys manually (no OAuth), use key-based auth.\n\nKeys (request from the user on install)\n\nPublic API Key: application\nUser Key: user account\nEnvironment: Real Portfolio or Virtual Portfolio (real/demo)\n\nKey generation (user-facing):\n\nLog in to eToro.\nSettings > Trading.\nCreate New Key.\nChoose Environment (Real or Virtual/Demo) and Permissions (Read or Write).\nVerify identity and copy the generated User Key.\n\nHeaders (every request):\n\nx-request-id: unique UUID per request\nx-api-key: Public API Key (<PUBLIC_KEY>)\nx-user-key: User Key (<USER_KEY>)\n\nExample:\n\ncurl -X GET \"https://public-api.etoro.com/api/v1/watchlists\" \\\n  -H \"x-request-id: <UUID>\" \\\n  -H \"x-api-key: <PUBLIC_KEY>\" \\\n  -H \"x-user-key: <USER_KEY>\""
      },
      {
        "title": "Choosing the Auth Method in Code",
        "body": "When making requests, check which credentials are available:\n\nif (ctx.accessToken) {\n  // SSO auth — Bearer token from OAuth token exchange\n  headers[\"Authorization\"] = `Bearer ${ctx.accessToken}`;\n} else {\n  // Manual API key auth\n  headers[\"x-api-key\"] = ctx.apiKey;\n  headers[\"x-user-key\"] = ctx.userKey;\n}"
      },
      {
        "title": "Request Conventions",
        "body": "All paths below are relative to the Base URL (which already includes /api/v1).\nExample: GET /watchlists means GET https://public-api.etoro.com/api/v1/watchlists.\nQuery params go in the URL, path params go in the URL path.\nFor query params that are documented as array, send them as comma-separated values (e.g., instrumentIds=1001,1002).\nPagination patterns vary by endpoint:\n\nSearch: pageNumber, pageSize\nPeople search & trade history: page, pageSize\nFeeds: take, offset\nWatchlist items listing: pageNumber, itemsPerPage\n\n\nCasing matters for request bodies:\n\nTrading execution uses PascalCase fields (e.g., InstrumentID, IsBuy, Leverage).\nMarket close body uses InstrumentId (capital I, lowercase d).\nWatchlist items use ItemId, ItemType, ItemRank.\nFeeds post body uses lower camel (owner, message, tags, mentions, attachments).\n\n\nSome responses may use different casing for similar concepts (e.g., instrumentId vs InstrumentID). When extracting IDs, handle both if present."
      },
      {
        "title": "Demo vs Real Trading",
        "body": "Use demo execution endpoints (contain /demo/) for testing and paper trading.\nUse non-demo execution endpoints for real trading.\nFor portfolio/PnL:\n\nDemo: /trading/info/demo/*\nReal: /trading/info/portfolio and /trading/info/real/pnl\n\n\nEnsure your key environment matches the endpoint (Virtual vs Real). Each User Key is associated with a specific environment."
      },
      {
        "title": "Use Defaults",
        "body": "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."
      },
      {
        "title": "Quick Start (Demo Trade)",
        "body": "Resolve instrumentId using search.\nfields is required on search requests.\n\ncurl -X GET \"https://public-api.etoro.com/api/v1/market-data/search?internalSymbolFull=BTC&fields=instrumentId,internalSymbolFull,displayname\" \\\n  -H \"Authorization: Bearer <access_token>\" \\\n  -H \"x-request-id: <UUID>\"\n\nPlace a demo market order by amount (PascalCase body):\n\ncurl -X POST \"https://public-api.etoro.com/api/v1/trading/execution/demo/market-open-orders/by-amount\" \\\n  -H \"Authorization: Bearer <access_token>\" \\\n  -H \"x-request-id: <UUID>\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"InstrumentID\": 100000,\n    \"IsBuy\": true,\n    \"Leverage\": 1,\n    \"Amount\": 100\n  }'\n\nNote: 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."
      },
      {
        "title": "Common IDs",
        "body": "instrumentId: from Search or Instruments metadata\npositionId: from Portfolio endpoints\norderId: from execution responses or Portfolio endpoints\nmarketId: used by instrument feed endpoints (typically available in instrument metadata/search fields)\nuserId: numeric eToro user ID (often referred to as CID in responses; discover via People endpoints/search)\nwatchlistId: from watchlists list/create endpoints"
      },
      {
        "title": "Market Data (Requests)",
        "body": "Search instruments\n\nGET /market-data/search\nRequired query: fields (comma-separated list of instrument fields to return)\nOptional: searchText, pageSize, pageNumber, sort\nThe Search endpoint supports filtering by fields returned in results; for exact symbol lookup, use internalSymbolFull as a query param and verify the exact match.\nRecommended 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).\n\nMetadata\n\nGET /market-data/instruments\nFilters: instrumentIds, exchangeIds, stocksIndustryIds, instrumentTypeIds.\n\nPrices & history\n\nGET /market-data/instruments/rates\nRequired: instrumentIds (comma-separated).\nGET /market-data/instruments/history/closing-price\nReturns historical closing prices for all instruments (bulk).\nGET /market-data/instruments/{instrumentId}/history/candles/{direction}/{interval}/{candlesCount}\ndirection: asc or desc. candlesCount max 1000.\nUse only supported interval values (confirm via docs if unsure).\n\nReference data\n\nGET /market-data/exchanges (optional exchangeIds)\nGET /market-data/instrument-types\nGET /market-data/stocks-industries (optional stocksIndustryIds)"
      },
      {
        "title": "Trading Execution (Requests)",
        "body": "Requires appropriate permissions (typically Write) and the correct environment (Demo vs Real)."
      },
      {
        "title": "Market Open Orders (by amount)",
        "body": "Endpoints:\n\nPOST /trading/execution/demo/market-open-orders/by-amount\nPOST /trading/execution/market-open-orders/by-amount\n\nBody (PascalCase, JSON):\n\nRequired: InstrumentID, IsBuy, Leverage, Amount\nOptional: StopLossRate, TakeProfitRate, IsTslEnabled, IsNoStopLoss, IsNoTakeProfit"
      },
      {
        "title": "Market Open Orders (by units)",
        "body": "Endpoints:\n\nPOST /trading/execution/demo/market-open-orders/by-units\nPOST /trading/execution/market-open-orders/by-units\n\nBody (PascalCase, JSON):\n\nRequired: InstrumentID, IsBuy, Leverage, AmountInUnits\nOptional: StopLossRate, TakeProfitRate, IsTslEnabled, IsNoStopLoss, IsNoTakeProfit"
      },
      {
        "title": "Cancel Market Open Orders",
        "body": "Endpoints:\n\nDELETE /trading/execution/demo/market-open-orders/{orderId}\nDELETE /trading/execution/market-open-orders/{orderId}"
      },
      {
        "title": "Market Close Orders",
        "body": "Endpoints:\n\nPOST /trading/execution/demo/market-close-orders/positions/{positionId}\nPOST /trading/execution/market-close-orders/positions/{positionId}\nDELETE /trading/execution/demo/market-close-orders/{orderId}\nDELETE /trading/execution/market-close-orders/{orderId}\n\nBody (JSON):\n\nRequired: InstrumentId\nOptional: UnitsToDeduct (number or null)\n\nPartial close: set UnitsToDeduct.\nFull close: set UnitsToDeduct to null.\nYou must close by positionId, not by symbol."
      },
      {
        "title": "Market-if-touched (Limit) Orders",
        "body": "Endpoints:\n\nPOST /trading/execution/demo/limit-orders\nDELETE /trading/execution/demo/limit-orders/{orderId}\nPOST /trading/execution/limit-orders\nDELETE /trading/execution/limit-orders/{orderId}\n\nBody (PascalCase, JSON):\n\nRequired: InstrumentID, IsBuy, Leverage, Rate, and one of Amount or AmountInUnits\nOptional: StopLossRate, TakeProfitRate, IsTslEnabled, IsNoStopLoss, IsNoTakeProfit\nDo not send: IsDiscounted, CID"
      },
      {
        "title": "Trading Info & Portfolio (Requests)",
        "body": "GET /trading/info/demo/pnl\nGET /trading/info/real/pnl\nGET /trading/info/demo/portfolio\nGET /trading/info/portfolio\nUse these to discover positionId and orderId for close/cancel flows.\nGET /trading/info/trade/history\nRequired: minDate (YYYY-MM-DD). Optional: page, pageSize."
      },
      {
        "title": "Watchlists (Requests)",
        "body": "User watchlists\n\nGET /watchlists\nOptional: itemsPerPageForSingle, ensureBuiltinWatchlists, addRelatedAssets.\nGET /watchlists/{watchlistId}\nOptional: pageNumber, itemsPerPage.\nPOST /watchlists\nQuery: name (required), type, dynamicQuery (optional). (Uses query params, not a JSON body.)\nPUT /watchlists/{watchlistId}\nQuery: newName (required). (Uses query params, not a JSON body.)\nDELETE /watchlists/{watchlistId}\n\nWatchlist items (body schema)\n\nWatchlistItemDto fields:\n\nItemId (required, int)\nItemType (required, string: Instrument or Person)\nItemRank (optional, int)\n\nEndpoints:\n\nPOST /watchlists/{watchlistId}/items\nPUT /watchlists/{watchlistId}/items\nDELETE /watchlists/{watchlistId}/items\n\nExample body:\n\n[\n  { \"ItemId\": 12345, \"ItemType\": \"Instrument\", \"ItemRank\": 1 },\n  { \"ItemId\": 67890, \"ItemType\": \"Instrument\", \"ItemRank\": 2 }\n]\n\nDefault watchlists\n\nPOST /watchlists/default-watchlist/selected-items\nGET /watchlists/default-watchlists/items\nOptional: itemsLimit, itemsPerPage.\nPOST /watchlists/newasdefault-watchlist\nQuery: name (required), type, dynamicQuery (optional).\nPUT /watchlists/setUserSelectedUserDefault/{watchlistId}\nPUT /watchlists/rank/{watchlistId}\nQuery: newRank (required).\n\nPublic watchlists\n\nGET /watchlists/public/{userId}\nGET /watchlists/public/{userId}/{watchlistId}"
      },
      {
        "title": "Feeds (Requests)",
        "body": "Read feeds\n\nGET /feeds/instrument/{marketId}\nOptional: requesterUserId, take, offset, badgesExperimentIsEnabled, reactionsPageSize.\nGET /feeds/user/{userId}\nOptional: requesterUserId, take, offset, badgesExperimentIsEnabled, reactionsPageSize.\n\nNotes:\n\nmarketId is associated with an instrument (typically available via instrument metadata/search if you include it in fields).\nuserId is a numeric user identifier (CID). If you only have a username, discover the numeric ID via People endpoints (see User Info & Analytics).\n\nCreate post\n\nPOST /feeds/post\nBody fields (lower camel, JSON):\n\nowner (int)\nmessage (string)\ntags: { \"tags\": [{ \"name\": \"...\", \"id\": \"...\" }] }\nmentions: { \"mentions\": [{ \"userName\": \"...\", \"id\": \"...\", \"isD irect\": true }] }\nattachments: array of objects with url, title, host, description, mediaType, and optional media.\n\nMinimal example:\n\n{ \"message\": \"Hello eToro feed!\" }"
      },
      {
        "title": "Curated Lists & Recommendations (Requests)",
        "body": "GET /curated-lists\nGET /market-recommendations/{itemsCount}"
      },
      {
        "title": "Popular Investors (Copiers)",
        "body": "GET /pi-data/copiers"
      },
      {
        "title": "User Info & Analytics (Requests)",
        "body": "GET /user-info/people\nOptional: usernames, cidList.\nUse this to map username ↔ CID (userId) when you need numeric userId for feeds/public watchlists.\nGET /user-info/people/search\nRequired: period. Optional: page, pageSize, sort, popularInvestor, gainMax, maxDailyRiskScoreMin, maxDailyRiskScoreMax, maxMonthlyRiskScoreMin, maxMonthlyRiskScoreMax, weeksSinceRegistrationMin, countryId, instrumentId, instrumentPctMin, instrumentPctMax, isTestAccount, and other filters.\nGET /user-info/people/{username}/gain\nGET /user-info/people/{username}/daily-gain\nRequired: minDate, maxDate, type (Daily or Period).\nGET /user-info/people/{username}/portfolio/live\nGET /user-info/people/{username}/tradeinfo\nRequired: period (e.g., LastTwoYears)."
      },
      {
        "title": "Responses & Schemas",
        "body": "For response schemas and full examples, refer to:\n\nhttps://api-portal.etoro.com/\nMCP server: https://api-portal.etoro.com/mcp"
      }
    ],
    "body": "eToro Public API\n\nBase URL: https://public-api.etoro.com/api/v1\n\nAbout\n\nThis skill allows to interact with the user's eToro account programatically, including executing trades.\n\nAuthentication & Required Headers\n\nThe eToro API supports two authentication methods. Both use the same base URL and endpoints — only the auth headers differ.\n\nMethod 1 — OAuth SSO (Bearer Token)\n\nIf the user authenticated via \"Login with eToro\" (SSO/OAuth), an access_token is available from the token exchange.\n\nHeaders (every request):\n\nx-request-id: unique UUID per request\nAuthorization: Bearer <access_token>\n\nWhere access_token comes from:\n\nUser clicks \"Login with eToro\" → redirects to https://www.etoro.com/sso/ with PKCE challenge.\nUser authenticates on eToro's side.\neToro redirects back with an authorization code.\nThe code is exchanged for tokens via POST https://www.etoro.com/sso/oidc/token:\ngrant_type=authorization_code\ncode=<auth_code>\nredirect_uri=<callback_url>\ncode_verifier=<pkce_verifier>\nPlus Authorization: Basic <base64(client_id:client_secret)> header\nResponse contains:\naccess_token — this is the Bearer token for API calls (~2130 chars, JWT)\nid_token — JWT with user identity (sub claim = 128-char encoded user ID)\ntoken_type: \"Bearer\"\nexpires_in: (varies)\n\nExample:\n\ncurl -X GET \"https://public-api.etoro.com/api/v1/watchlists\" \\\n  -H \"x-request-id: <UUID>\" \\\n  -H \"Authorization: Bearer <access_token>\"\n\nMethod 2 — Manual API Keys\n\nIf the user provides API keys manually (no OAuth), use key-based auth.\n\nKeys (request from the user on install)\n\nPublic API Key: application\nUser Key: user account\nEnvironment: Real Portfolio or Virtual Portfolio (real/demo)\n\nKey generation (user-facing):\n\nLog in to eToro.\nSettings > Trading.\nCreate New Key.\nChoose Environment (Real or Virtual/Demo) and Permissions (Read or Write).\nVerify identity and copy the generated User Key.\n\nHeaders (every request):\n\nx-request-id: unique UUID per request\nx-api-key: Public API Key (<PUBLIC_KEY>)\nx-user-key: User Key (<USER_KEY>)\n\nExample:\n\ncurl -X GET \"https://public-api.etoro.com/api/v1/watchlists\" \\\n  -H \"x-request-id: <UUID>\" \\\n  -H \"x-api-key: <PUBLIC_KEY>\" \\\n  -H \"x-user-key: <USER_KEY>\"\n\nChoosing the Auth Method in Code\n\nWhen making requests, check which credentials are available:\n\nif (ctx.accessToken) {\n  // SSO auth — Bearer token from OAuth token exchange\n  headers[\"Authorization\"] = `Bearer ${ctx.accessToken}`;\n} else {\n  // Manual API key auth\n  headers[\"x-api-key\"] = ctx.apiKey;\n  headers[\"x-user-key\"] = ctx.userKey;\n}\n\nRequest Conventions\nAll paths below are relative to the Base URL (which already includes /api/v1).\nExample: GET /watchlists means GET https://public-api.etoro.com/api/v1/watchlists.\nQuery params go in the URL, path params go in the URL path.\nFor query params that are documented as array, send them as comma-separated values (e.g., instrumentIds=1001,1002).\nPagination patterns vary by endpoint:\nSearch: pageNumber, pageSize\nPeople search & trade history: page, pageSize\nFeeds: take, offset\nWatchlist items listing: pageNumber, itemsPerPage\nCasing matters for request bodies:\nTrading execution uses PascalCase fields (e.g., InstrumentID, IsBuy, Leverage).\nMarket close body uses InstrumentId (capital I, lowercase d).\nWatchlist items use ItemId, ItemType, ItemRank.\nFeeds post body uses lower camel (owner, message, tags, mentions, attachments).\nSome responses may use different casing for similar concepts (e.g., instrumentId vs InstrumentID). When extracting IDs, handle both if present.\nDemo vs Real Trading\nUse demo execution endpoints (contain /demo/) for testing and paper trading.\nUse non-demo execution endpoints for real trading.\nFor portfolio/PnL:\nDemo: /trading/info/demo/*\nReal: /trading/info/portfolio and /trading/info/real/pnl\nEnsure your key environment matches the endpoint (Virtual vs Real). Each User Key is associated with a specific environment.\nUse Defaults\nImportant: 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.\nQuick Start (Demo Trade)\nResolve instrumentId using search.\nfields is required on search requests.\ncurl -X GET \"https://public-api.etoro.com/api/v1/market-data/search?internalSymbolFull=BTC&fields=instrumentId,internalSymbolFull,displayname\" \\\n  -H \"Authorization: Bearer <access_token>\" \\\n  -H \"x-request-id: <UUID>\"\n\nPlace a demo market order by amount (PascalCase body):\ncurl -X POST \"https://public-api.etoro.com/api/v1/trading/execution/demo/market-open-orders/by-amount\" \\\n  -H \"Authorization: Bearer <access_token>\" \\\n  -H \"x-request-id: <UUID>\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"InstrumentID\": 100000,\n    \"IsBuy\": true,\n    \"Leverage\": 1,\n    \"Amount\": 100\n  }'\n\n\nNote: 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.\n\nCommon IDs\ninstrumentId: from Search or Instruments metadata\npositionId: from Portfolio endpoints\norderId: from execution responses or Portfolio endpoints\nmarketId: used by instrument feed endpoints (typically available in instrument metadata/search fields)\nuserId: numeric eToro user ID (often referred to as CID in responses; discover via People endpoints/search)\nwatchlistId: from watchlists list/create endpoints\nMarket Data (Requests)\n\nSearch instruments\n\nGET /market-data/search\nRequired query: fields (comma-separated list of instrument fields to return)\nOptional: searchText, pageSize, pageNumber, sort\nThe Search endpoint supports filtering by fields returned in results; for exact symbol lookup, use internalSymbolFull as a query param and verify the exact match.\nRecommended 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).\n\nMetadata\n\nGET /market-data/instruments\nFilters: instrumentIds, exchangeIds, stocksIndustryIds, instrumentTypeIds.\n\nPrices & history\n\nGET /market-data/instruments/rates\nRequired: instrumentIds (comma-separated).\nGET /market-data/instruments/history/closing-price\nReturns historical closing prices for all instruments (bulk).\nGET /market-data/instruments/{instrumentId}/history/candles/{direction}/{interval}/{candlesCount}\ndirection: asc or desc. candlesCount max 1000.\nUse only supported interval values (confirm via docs if unsure).\n\nReference data\n\nGET /market-data/exchanges (optional exchangeIds)\nGET /market-data/instrument-types\nGET /market-data/stocks-industries (optional stocksIndustryIds)\nTrading Execution (Requests)\n\nRequires appropriate permissions (typically Write) and the correct environment (Demo vs Real).\n\nMarket Open Orders (by amount)\n\nEndpoints:\n\nPOST /trading/execution/demo/market-open-orders/by-amount\nPOST /trading/execution/market-open-orders/by-amount\n\nBody (PascalCase, JSON):\n\nRequired: InstrumentID, IsBuy, Leverage, Amount\nOptional: StopLossRate, TakeProfitRate, IsTslEnabled, IsNoStopLoss, IsNoTakeProfit\nMarket Open Orders (by units)\n\nEndpoints:\n\nPOST /trading/execution/demo/market-open-orders/by-units\nPOST /trading/execution/market-open-orders/by-units\n\nBody (PascalCase, JSON):\n\nRequired: InstrumentID, IsBuy, Leverage, AmountInUnits\nOptional: StopLossRate, TakeProfitRate, IsTslEnabled, IsNoStopLoss, IsNoTakeProfit\nCancel Market Open Orders\n\nEndpoints:\n\nDELETE /trading/execution/demo/market-open-orders/{orderId}\nDELETE /trading/execution/market-open-orders/{orderId}\nMarket Close Orders\n\nEndpoints:\n\nPOST /trading/execution/demo/market-close-orders/positions/{positionId}\nPOST /trading/execution/market-close-orders/positions/{positionId}\nDELETE /trading/execution/demo/market-close-orders/{orderId}\nDELETE /trading/execution/market-close-orders/{orderId}\n\nBody (JSON):\n\nRequired: InstrumentId\nOptional: UnitsToDeduct (number or null)\n\nPartial close: set UnitsToDeduct.\nFull close: set UnitsToDeduct to null.\nYou must close by positionId, not by symbol.\n\nMarket-if-touched (Limit) Orders\n\nEndpoints:\n\nPOST /trading/execution/demo/limit-orders\nDELETE /trading/execution/demo/limit-orders/{orderId}\nPOST /trading/execution/limit-orders\nDELETE /trading/execution/limit-orders/{orderId}\n\nBody (PascalCase, JSON):\n\nRequired: InstrumentID, IsBuy, Leverage, Rate, and one of Amount or AmountInUnits\nOptional: StopLossRate, TakeProfitRate, IsTslEnabled, IsNoStopLoss, IsNoTakeProfit\nDo not send: IsDiscounted, CID\nTrading Info & Portfolio (Requests)\nGET /trading/info/demo/pnl\nGET /trading/info/real/pnl\nGET /trading/info/demo/portfolio\nGET /trading/info/portfolio\nUse these to discover positionId and orderId for close/cancel flows.\nGET /trading/info/trade/history\nRequired: minDate (YYYY-MM-DD). Optional: page, pageSize.\nWatchlists (Requests)\n\nUser watchlists\n\nGET /watchlists\nOptional: itemsPerPageForSingle, ensureBuiltinWatchlists, addRelatedAssets.\nGET /watchlists/{watchlistId}\nOptional: pageNumber, itemsPerPage.\nPOST /watchlists\nQuery: name (required), type, dynamicQuery (optional). (Uses query params, not a JSON body.)\nPUT /watchlists/{watchlistId}\nQuery: newName (required). (Uses query params, not a JSON body.)\nDELETE /watchlists/{watchlistId}\n\nWatchlist items (body schema)\n\nWatchlistItemDto fields:\n\nItemId (required, int)\nItemType (required, string: Instrument or Person)\nItemRank (optional, int)\n\nEndpoints:\n\nPOST /watchlists/{watchlistId}/items\nPUT /watchlists/{watchlistId}/items\nDELETE /watchlists/{watchlistId}/items\n\nExample body:\n\n[\n  { \"ItemId\": 12345, \"ItemType\": \"Instrument\", \"ItemRank\": 1 },\n  { \"ItemId\": 67890, \"ItemType\": \"Instrument\", \"ItemRank\": 2 }\n]\n\n\nDefault watchlists\n\nPOST /watchlists/default-watchlist/selected-items\nGET /watchlists/default-watchlists/items\nOptional: itemsLimit, itemsPerPage.\nPOST /watchlists/newasdefault-watchlist\nQuery: name (required), type, dynamicQuery (optional).\nPUT /watchlists/setUserSelectedUserDefault/{watchlistId}\nPUT /watchlists/rank/{watchlistId}\nQuery: newRank (required).\n\nPublic watchlists\n\nGET /watchlists/public/{userId}\nGET /watchlists/public/{userId}/{watchlistId}\nFeeds (Requests)\n\nRead feeds\n\nGET /feeds/instrument/{marketId}\nOptional: requesterUserId, take, offset, badgesExperimentIsEnabled, reactionsPageSize.\nGET /feeds/user/{userId}\nOptional: requesterUserId, take, offset, badgesExperimentIsEnabled, reactionsPageSize.\n\nNotes:\n\nmarketId is associated with an instrument (typically available via instrument metadata/search if you include it in fields).\nuserId is a numeric user identifier (CID). If you only have a username, discover the numeric ID via People endpoints (see User Info & Analytics).\n\nCreate post\n\nPOST /feeds/post\nBody fields (lower camel, JSON):\nowner (int)\nmessage (string)\ntags: { \"tags\": [{ \"name\": \"...\", \"id\": \"...\" }] }\nmentions: { \"mentions\": [{ \"userName\": \"...\", \"id\": \"...\", \"isD irect\": true }] }\nattachments: array of objects with url, title, host, description, mediaType, and optional media.\n\nMinimal example:\n\n{ \"message\": \"Hello eToro feed!\" }\n\nCurated Lists & Recommendations (Requests)\nGET /curated-lists\nGET /market-recommendations/{itemsCount}\nPopular Investors (Copiers)\nGET /pi-data/copiers\nUser Info & Analytics (Requests)\nGET /user-info/people\nOptional: usernames, cidList.\nUse this to map username ↔ CID (userId) when you need numeric userId for feeds/public watchlists.\nGET /user-info/people/search\nRequired: period. Optional: page, pageSize, sort, popularInvestor, gainMax, maxDailyRiskScoreMin, maxDailyRiskScoreMax, maxMonthlyRiskScoreMin, maxMonthlyRiskScoreMax, weeksSinceRegistrationMin, countryId, instrumentId, instrumentPctMin, instrumentPctMax, isTestAccount, and other filters.\nGET /user-info/people/{username}/gain\nGET /user-info/people/{username}/daily-gain\nRequired: minDate, maxDate, type (Daily or Period).\nGET /user-info/people/{username}/portfolio/live\nGET /user-info/people/{username}/tradeinfo\nRequired: period (e.g., LastTwoYears).\nResponses & Schemas\n\nFor response schemas and full examples, refer to:\n\nhttps://api-portal.etoro.com/\nMCP server: https://api-portal.etoro.com/mcp"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/marian2js/etoro-apps",
    "publisherUrl": "https://clawhub.ai/marian2js/etoro-apps",
    "owner": "marian2js",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/etoro-apps",
    "downloadUrl": "https://openagent3.xyz/downloads/etoro-apps",
    "agentUrl": "https://openagent3.xyz/skills/etoro-apps/agent",
    "manifestUrl": "https://openagent3.xyz/skills/etoro-apps/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/etoro-apps/agent.md"
  }
}