{"openapi": "3.1.0", "info": {"title": "TradesViz Read API", "version": "0.3.0", "description": "Read journal data for eligible Pro and Platinum users. Create an API key in Account Settings \u2192 API & MCP and select the accounts and permissions it needs. These endpoints only read data; journal changes use the separate Journal API. Live keyset pages are not frozen exports. MCP uses browser-based OAuth authorization."}, "servers": [{"url": "https://www.tradesviz.com"}], "paths": {"/api/v2/context": {"get": {"operationId": "getUserContext", "tags": ["Read-only journal"], "parameters": [], "security": [{"testBearer": []}], "x-tradesviz-required-scopes": ["trades.read"], "responses": {"200": {"description": "Journal data limited to this credential's current account grants.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ContextResponse"}}}}, "400": {"description": "Invalid query, cursor, host, or request body.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired, or revoked API key.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Required credential scope missing.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Endpoint or account unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "405": {"description": "Only GET is allowed.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "422": {"description": "Query exceeds account or page limits.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Request, continuation, response-byte or concurrency quota reached. Quotas are shared by user across REST and MCP; honor Retry-After.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"description": "Seconds to wait before retrying.", "schema": {"type": "integer", "minimum": 1}}}}, "500": {"description": "Unexpected internal failure.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "503": {"description": "Database or service unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}}}, "/api/v2/accounts": {"get": {"operationId": "listAccounts", "tags": ["Read-only journal"], "parameters": [{"name": "page_size", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 4096}, "description": "Pass next_cursor unchanged with the same request parameters."}], "security": [{"testBearer": []}], "x-tradesviz-required-scopes": ["trades.read"], "responses": {"200": {"description": "Journal data limited to this credential's current account grants.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AccountResponse"}}}}, "400": {"description": "Invalid query, cursor, host, or request body.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired, or revoked API key.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Required credential scope missing.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Endpoint or account unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "405": {"description": "Only GET is allowed.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "422": {"description": "Query exceeds account or page limits.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Request, continuation, response-byte or concurrency quota reached. Quotas are shared by user across REST and MCP; honor Retry-After.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"description": "Seconds to wait before retrying.", "schema": {"type": "integer", "minimum": 1}}}}, "500": {"description": "Unexpected internal failure.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "503": {"description": "Database or service unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}}}, "/api/v2/trades": {"get": {"operationId": "listTrades", "tags": ["Read-only journal"], "parameters": [{"name": "page_size", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 4096}, "description": "Pass next_cursor unchanged with the same request parameters."}, {"name": "account_ids", "in": "query", "required": true, "style": "form", "explode": true, "description": "Public UUIDs returned by /api/v2/accounts.", "schema": {"type": "array", "minItems": 1, "maxItems": 50, "uniqueItems": true, "items": {"type": "string", "format": "uuid"}}}, {"name": "extra_data", "in": "query", "description": "When true, adds the nested extra_data object. Requires trades.extended.read.", "schema": {"type": "boolean", "default": false}}, {"name": "sort_time_start", "in": "query", "description": "Inclusive RFC 3339 lower bound for sort_time. Supply together with sort_time_end; omit both for no time window.", "schema": {"type": "string", "format": "date-time"}}, {"name": "sort_time_end", "in": "query", "description": "Exclusive RFC 3339 upper bound for sort_time. Supply together with sort_time_start; must be later than the lower bound.", "schema": {"type": "string", "format": "date-time"}}], "security": [{"testBearer": []}], "x-tradesviz-required-scopes": ["trades.read"], "responses": {"200": {"description": "Journal data limited to this credential's current account grants.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TradeResponse"}}}}, "400": {"description": "Invalid query, cursor, host, or request body.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired, or revoked API key.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Required credential scope missing.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Endpoint or account unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "405": {"description": "Only GET is allowed.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "422": {"description": "Query exceeds account or page limits.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Request, continuation, response-byte or concurrency quota reached. Quotas are shared by user across REST and MCP; honor Retry-After.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"description": "Seconds to wait before retrying.", "schema": {"type": "integer", "minimum": 1}}}}, "500": {"description": "Unexpected internal failure.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "503": {"description": "Database or service unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}}}, "/api/v2/executions": {"get": {"operationId": "listExecutions", "tags": ["Read-only journal"], "parameters": [{"name": "page_size", "in": "query", "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 50}}, {"name": "cursor", "in": "query", "schema": {"type": "string", "maxLength": 4096}, "description": "Pass next_cursor unchanged with the same request parameters."}, {"name": "account_id", "in": "query", "required": true, "description": "Public account UUID returned by /api/v2/accounts.", "schema": {"type": "string", "format": "uuid"}}, {"name": "trade_ref", "in": "query", "required": true, "description": "A trade_ref returned for this same account.", "schema": {"type": "string", "minLength": 1, "maxLength": 200}}], "security": [{"testBearer": []}], "x-tradesviz-required-scopes": ["trades.read", "executions.read"], "responses": {"200": {"description": "Journal data limited to this credential's current account grants.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ExecutionResponse"}}}}, "400": {"description": "Invalid query, cursor, host, or request body.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired, or revoked API key.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Required credential scope missing.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Endpoint or account unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "405": {"description": "Only GET is allowed.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "422": {"description": "Query exceeds account or page limits.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Request, continuation, response-byte or concurrency quota reached. Quotas are shared by user across REST and MCP; honor Retry-After.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"description": "Seconds to wait before retrying.", "schema": {"type": "integer", "minimum": 1}}}}, "500": {"description": "Unexpected internal failure.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "503": {"description": "Database or service unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}}}, "/api/v2/analytics": {"get": {"operationId": "getAccountAnalytics", "tags": ["Read-only journal"], "parameters": [{"name": "account_ids", "in": "query", "required": true, "style": "form", "explode": true, "description": "Public UUIDs returned by /api/v2/accounts.", "schema": {"type": "array", "minItems": 1, "maxItems": 5, "uniqueItems": true, "items": {"type": "string", "format": "uuid"}}}, {"name": "period_start", "in": "query", "required": true, "description": "Inclusive UTC lower bound. Required; the period may span at most 31 days.", "schema": {"type": "string", "format": "date-time"}}, {"name": "period_end", "in": "query", "required": true, "description": "Exclusive UTC upper bound. Required; the period may span at most 31 days.", "schema": {"type": "string", "format": "date-time"}}], "security": [{"testBearer": []}], "x-tradesviz-required-scopes": ["trades.read", "analytics.read"], "responses": {"200": {"description": "Journal data limited to this credential's current account grants.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AnalyticsResponse"}}}}, "400": {"description": "Invalid query, cursor, host, or request body.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "401": {"description": "Missing, invalid, expired, or revoked API key.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "403": {"description": "Required credential scope missing.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "404": {"description": "Endpoint or account unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "405": {"description": "Only GET is allowed.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "422": {"description": "Query exceeds account or page limits.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "429": {"description": "Request, continuation, response-byte or concurrency quota reached. Quotas are shared by user across REST and MCP; honor Retry-After.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}, "headers": {"Retry-After": {"description": "Seconds to wait before retrying.", "schema": {"type": "integer", "minimum": 1}}}}, "500": {"description": "Unexpected internal failure.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}, "503": {"description": "Database or service unavailable.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}}}}}}}, "components": {"schemas": {"Context": {"type": "object", "additionalProperties": false, "required": ["timezone", "base_currency"], "properties": {"timezone": {"type": "string"}, "base_currency": {"type": "string"}}}, "Account": {"type": "object", "additionalProperties": false, "required": ["account_id", "name", "created_at"], "properties": {"account_id": {"type": "string", "format": "uuid"}, "name": {"type": "string"}, "created_at": {"type": "string", "format": "date-time"}}}, "Pagination": {"type": "object", "additionalProperties": false, "required": ["has_more", "next_cursor"], "properties": {"has_more": {"type": "boolean"}, "next_cursor": {"type": ["string", "null"], "description": "Opaque cursor; expires after ten minutes."}}}, "Meta": {"type": "object", "additionalProperties": false, "required": ["request_id", "test_only"], "properties": {"request_id": {"type": "string"}, "test_only": {"type": "boolean", "const": true}, "internal_only": {"type": "boolean"}, "data_source": {"type": "string", "enum": ["configured_database", "capability_functions"]}, "consistency": {"type": "string", "const": "live_keyset"}, "trade_refs": {"type": "string", "const": "not_permanent"}}}, "Error": {"type": "object", "additionalProperties": false, "required": ["error", "meta"], "properties": {"error": {"type": "object", "additionalProperties": false, "required": ["code", "message"], "properties": {"code": {"type": "string"}, "message": {"type": "string"}}}, "meta": {"type": "object", "additionalProperties": false, "required": ["request_id", "test_only"], "properties": {"request_id": {"type": "string"}, "test_only": {"type": "boolean", "const": true}}}}}, "TradeExtraData": {"type": "object", "additionalProperties": false, "required": ["r_value", "percent_return", "native_open_price", "native_close_price", "native_gross_pnl", "native_net_pnl", "total_buy_quantity", "total_sell_quantity", "total_executions", "duration_seconds", "total_credit_debit"], "properties": {"r_value": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "percent_return": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "native_open_price": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "native_close_price": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "native_gross_pnl": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "native_net_pnl": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_buy_quantity": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_sell_quantity": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_executions": {"type": ["integer", "null"], "minimum": 0}, "duration_seconds": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_credit_debit": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}}}, "Trade": {"type": "object", "additionalProperties": false, "required": ["account_id", "trade_ref", "sort_time", "status", "symbol", "underlying", "asset_type", "side", "opened_at", "closed_at", "last_execution_at", "total_quantity", "remaining_quantity", "base_open_price", "base_close_price", "base_gross_pnl", "base_net_pnl", "base_commission", "base_fees", "native_currency", "is_simulated"], "properties": {"account_id": {"type": "string", "format": "uuid"}, "trade_ref": {"type": "string", "description": "Opaque reference; not permanent across trade rebuilds."}, "sort_time": {"type": "string", "format": "date-time"}, "status": {"type": "string", "enum": ["open", "closed", "unknown"]}, "symbol": {"type": ["string", "null"]}, "underlying": {"type": ["string", "null"]}, "asset_type": {"type": ["string", "null"]}, "side": {"type": ["string", "null"]}, "native_currency": {"type": ["string", "null"]}, "opened_at": {"type": ["string", "null"], "format": "date-time"}, "closed_at": {"type": ["string", "null"], "format": "date-time"}, "last_execution_at": {"type": ["string", "null"], "format": "date-time"}, "total_quantity": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "remaining_quantity": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_open_price": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_close_price": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_gross_pnl": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_net_pnl": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_commission": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_fees": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "is_simulated": {"type": ["boolean", "null"]}, "extra_data": {"$ref": "#/components/schemas/TradeExtraData"}}}, "Execution": {"type": "object", "additionalProperties": false, "required": ["account_id", "trade_ref", "execution_ref", "executed_at", "symbol", "side", "quantity", "native_price", "base_price", "native_currency", "base_commission", "base_fees", "asset_type", "underlying", "is_simulated"], "properties": {"account_id": {"type": "string", "format": "uuid"}, "trade_ref": {"type": "string", "description": "Opaque reference; not permanent across trade rebuilds."}, "execution_ref": {"type": "string", "description": "Opaque reference; not permanent across trade rebuilds."}, "executed_at": {"type": "string", "format": "date-time"}, "symbol": {"type": ["string", "null"]}, "side": {"type": ["string", "null"]}, "native_currency": {"type": ["string", "null"]}, "asset_type": {"type": ["string", "null"]}, "underlying": {"type": ["string", "null"]}, "quantity": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "native_price": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_price": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_commission": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "base_fees": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "is_simulated": {"type": ["boolean", "null"]}}}, "Analytics": {"type": "object", "additionalProperties": false, "required": ["account_id", "trade_count", "winning_trades", "losing_trades", "win_rate", "total_net_pnl", "total_gross_pnl", "total_commission", "total_fees", "avg_win", "avg_loss", "profit_factor"], "properties": {"account_id": {"type": "string", "format": "uuid"}, "trade_count": {"type": "integer", "minimum": 0}, "winning_trades": {"type": "integer", "minimum": 0}, "losing_trades": {"type": "integer", "minimum": 0}, "win_rate": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_net_pnl": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_gross_pnl": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_commission": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "total_fees": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "avg_win": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "avg_loss": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}, "profit_factor": {"type": ["string", "null"], "description": "Exact decimal encoded as a string, never a JSON float."}}}, "ContextResponse": {"type": "object", "additionalProperties": false, "required": ["data", "meta", "pagination"], "properties": {"data": {"$ref": "#/components/schemas/Context"}, "meta": {"$ref": "#/components/schemas/Meta"}, "pagination": {"$ref": "#/components/schemas/Pagination"}}}, "AccountResponse": {"type": "object", "additionalProperties": false, "required": ["data", "meta", "pagination"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Account"}, "maxItems": 100}, "meta": {"$ref": "#/components/schemas/Meta"}, "pagination": {"$ref": "#/components/schemas/Pagination"}}}, "TradeResponse": {"type": "object", "additionalProperties": false, "required": ["data", "meta", "pagination"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Trade"}, "maxItems": 100}, "meta": {"$ref": "#/components/schemas/Meta"}, "pagination": {"$ref": "#/components/schemas/Pagination"}}}, "ExecutionResponse": {"type": "object", "additionalProperties": false, "required": ["data", "meta", "pagination"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Execution"}, "maxItems": 100}, "meta": {"$ref": "#/components/schemas/Meta"}, "pagination": {"$ref": "#/components/schemas/Pagination"}}}, "AnalyticsResponse": {"type": "object", "additionalProperties": false, "required": ["data", "meta", "pagination"], "properties": {"data": {"type": "array", "items": {"$ref": "#/components/schemas/Analytics"}, "maxItems": 5}, "meta": {"$ref": "#/components/schemas/Meta"}, "pagination": {"$ref": "#/components/schemas/Pagination"}}}}, "securitySchemes": {"testBearer": {"type": "http", "scheme": "bearer", "bearerFormat": "tvz_api_test_v1.<lookup>.<secret>"}}}}