{"openapi":"3.1.0","info":{"title":"Vings External API","version":"0.1.0","description":"Readonly external API for authenticated Vings financial data."},"servers":[{"url":"https://external.vin.gs/api","description":"Production"}],"tags":[{"name":"Transactions","description":"Transaction search and recurring payments"},{"name":"Cashflow","description":"Cashflow summaries"},{"name":"Spending","description":"Spending aggregates and merchants"},{"name":"Budgets","description":"Budget categories and summaries"},{"name":"Banks","description":"Connected bank status"},{"name":"Portfolio","description":"Portfolio snapshots and history"},{"name":"Preferences","description":"User preferences"},{"name":"OAuth","description":"OAuth protected-resource metadata (RFC 9728)"},{"name":"Health","description":"Liveness and readiness"},{"name":"User","description":"Authenticated user"},{"name":"MCP","description":"Model Context Protocol JSON-RPC transport"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Vings OAuth access token or personal access token (`vng_pat_…`). Use `Authorization: Bearer …`."}},"schemas":{"StatusResponse":{"type":"object","properties":{"status":{"type":"string","example":"ok"}},"required":["status"]},"MeResponse":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"capabilities":{"type":"object","properties":{"readonly":{"type":"boolean","enum":[true]},"rest":{"type":"boolean","enum":[true]},"mcp":{"type":"boolean","enum":[true]}},"required":["readonly","rest","mcp"]}},"required":["id","capabilities"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"UNAUTHORIZED"},"message":{"type":"string","example":"Missing bearer token"},"details":{"nullable":true},"requestId":{"type":"string"}},"required":["code","message"]}},"required":["error"]},"JsonRpcResponse":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"anyOf":[{"type":"string"},{"type":"number"},{"nullable":true}]},"result":{"nullable":true},"error":{"type":"object","properties":{"code":{"type":"number"},"message":{"type":"string"}},"required":["code","message"]}},"required":["jsonrpc"]},"JsonRpcRequest":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"anyOf":[{"type":"string"},{"type":"number"},{"nullable":true}]},"method":{"type":"string","description":"JSON-RPC method (initialize, notifications/initialized, tools/list, tools/call)","example":"tools/list"},"params":{"type":"object","additionalProperties":{"nullable":true}}},"required":["jsonrpc","method"]},"OAuthProtectedResourceMetadata":{"type":"object","properties":{"resource":{"type":"string","format":"uri"},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string"}},"resource_name":{"type":"string"}},"required":["resource","authorization_servers","scopes_supported","bearer_methods_supported","resource_name"]}},"parameters":{}},"paths":{"/health":{"get":{"tags":["Health"],"responses":{"200":{"description":"Liveness check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/ready":{"get":{"tags":["Health"],"responses":{"200":{"description":"Readiness check","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}},"503":{"description":"Service is not ready","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusResponse"}}}}}}},"/v1/me":{"get":{"tags":["User"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Authenticated user and external API capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/mcp":{"post":{"tags":["MCP"],"description":"JSON-RPC 2.0 transport for the Vings readonly MCP server.\n\nSupported methods:\n- `initialize`\n- `notifications/initialized` (returns HTTP 202 with no body)\n- `tools/list`\n- `tools/call`\n\nPer-tool input and output JSON Schemas are returned by `tools/list` (`inputSchema`, `outputSchema`) and are not duplicated in this OpenAPI document.","security":[{"bearerAuth":[]}],"externalDocs":{"description":"Model Context Protocol","url":"https://modelcontextprotocol.io/specification/2025-06-18"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/JsonRpcRequest"},{"type":"array","items":{"$ref":"#/components/schemas/JsonRpcRequest"}}]}}}},"responses":{"200":{"description":"JSON-RPC result (single object or batch array)","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/JsonRpcResponse"},{"type":"array","items":{"$ref":"#/components/schemas/JsonRpcResponse"}}]}}}},"202":{"description":"Notification accepted (`notifications/initialized` with no JSON-RPC response body)"},"400":{"description":"Invalid JSON-RPC request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token (includes WWW-Authenticate for OAuth protected resource discovery)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"tags":["MCP"],"description":"MCP requires JSON-RPC POST requests","responses":{"405":{"description":"Method not allowed — use POST with a JSON-RPC body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["OAuth"],"responses":{"200":{"description":"OAuth 2.0 Protected Resource Metadata (RFC 9728) for the Vings External REST API","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthProtectedResourceMetadata"}}}}}}},"/.well-known/oauth-protected-resource/mcp":{"get":{"tags":["OAuth"],"responses":{"200":{"description":"OAuth 2.0 Protected Resource Metadata (RFC 9728) for the Vings MCP server at /api/mcp","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthProtectedResourceMetadata"}}}}}}},"/v1/transactions":{"get":{"tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"dateFrom","in":"query"},{"schema":{"type":"string"},"required":false,"name":"dateTo","in":"query"},{"schema":{"type":"string"},"required":false,"name":"minAmountCents","in":"query"},{"schema":{"type":"string"},"required":false,"name":"maxAmountCents","in":"query"},{"schema":{"type":"string"},"required":false,"name":"merchantQuery","in":"query"},{"schema":{"type":"string"},"required":false,"name":"category","in":"query"},{"schema":{"type":"string","description":"Comma-separated categories"},"required":false,"description":"Comma-separated categories","name":"categories","in":"query"},{"schema":{"type":"string","enum":["INCOME","EXPENSE"]},"required":false,"name":"type","in":"query"},{"schema":{"type":"string","description":"Comma-separated account IDs"},"required":false,"description":"Comma-separated account IDs","name":"accountIds","in":"query"},{"schema":{"type":"string"},"required":false,"name":"pending","in":"query"},{"schema":{"type":"string"},"required":false,"name":"hidden","in":"query"},{"schema":{"type":"string","description":"URL-encoded JSON cursor with date and id"},"required":false,"description":"URL-encoded JSON cursor with date and id","name":"cursor","in":"query"},{"schema":{"type":"string"},"required":false,"name":"pageSize","in":"query"},{"schema":{"type":"string"},"required":false,"name":"showInternalTransfers","in":"query"}],"responses":{"200":{"description":"Cursor-paginated transaction search results","content":{"application/json":{"schema":{"type":"object","properties":{"transactions":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["INCOME"]},"category":{"type":"string","enum":["DIVIDEND","GIFT","INTEREST","INVESTMENT","PENSION","REFUND","SALARY","TRANSFER_IN"]},"amount_cents":{"type":"number"},"date":{"type":"string"},"title":{"type":"string"},"id":{"type":"string"},"pending":{"type":"boolean"},"currency":{"type":"string","nullable":true},"plaid_category":{"type":"string","nullable":true},"merchant_name":{"type":"string","nullable":true},"account_name":{"type":"string","nullable":true},"bank_name":{"type":"string","nullable":true},"linked_transaction_id":{"type":"string","nullable":true}},"required":["type","category","amount_cents","date","title","id","pending","currency"]},{"type":"object","properties":{"type":{"type":"string","enum":["EXPENSE"]},"category":{"anyOf":[{"type":"string","enum":["BOOKS","CINEMA","CONCERT","HOBBY","MUSIC","NIGHTLIFE","SPORTS","SUBSCRIPTIONS","VACATION","VIDEO_GAMES"]},{"type":"string","enum":["DRINKS","COFFEE","DELIVERY","FAST_FOOD","GROCERIES","RESTAURANT","VENDING_MACHINE"]},{"type":"string","enum":["DOCTOR","DENTIST","MEDICINE","PHARMACY","THERAPY","VISION"]},{"type":"string","enum":["ELECTRICITY","FURNITURE","HARDWARE","INTERNET","MAINTANANCE","PHONE","RENT","HYDRO"]},{"type":"string","enum":["BEAUTY","CHARITY","CLOTHING","EDUCATION","GYM","HAIR","HOTEL","PET","SHOPPING"]},{"type":"string","enum":["ATM","CREDIT_CARD","CAR_LOAN","MORTGAGE","INSURANCE","STUDENT_LOAN","TAXES","TRANSFER_OUT"]},{"type":"string","enum":["ACCOUNTING","BANK_COST","CHILDCARE","ELECTRONICS","GIFTS","SHIPPING","SUPPLIES","OTHER"]},{"type":"string","enum":["BIKESHARE","BUS","GAS","FLIGHT","PARKING","REPAIR","TAXI","TRAIN"]}]},"amount_cents":{"type":"number"},"date":{"type":"string"},"title":{"type":"string"},"id":{"type":"string"},"pending":{"type":"boolean"},"currency":{"type":"string","nullable":true},"plaid_category":{"type":"string","nullable":true},"merchant_name":{"type":"string","nullable":true},"account_name":{"type":"string","nullable":true},"bank_name":{"type":"string","nullable":true},"linked_transaction_id":{"type":"string","nullable":true}},"required":["type","category","amount_cents","date","title","id","pending","currency"]},{"type":"object","properties":{"type":{"type":"string","enum":["INTERNAL_TRANSFER"]},"category":{"type":"string","enum":["INTERNAL_TRANSFER_IN","INTERNAL_TRANSFER_OUT"]},"amount_cents":{"type":"number"},"date":{"type":"string"},"title":{"type":"string"},"id":{"type":"string"},"pending":{"type":"boolean"},"currency":{"type":"string","nullable":true},"plaid_category":{"type":"string","nullable":true},"merchant_name":{"type":"string","nullable":true},"account_name":{"type":"string","nullable":true},"bank_name":{"type":"string","nullable":true},"linked_transaction_id":{"type":"string","nullable":true}},"required":["type","category","amount_cents","date","title","id","pending","currency"]}]}},"pagination":{"type":"object","properties":{"nextCursor":{"type":"object","nullable":true,"properties":{"date":{"type":"string"},"id":{"type":"string","format":"uuid"}},"required":["date","id"],"description":"Cursor for next page - null if no more pages"},"hasMore":{"type":"boolean","description":"Whether there are more pages available"}},"required":["hasMore"]}},"required":["transactions","pagination"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/cashflow/summary":{"get":{"tags":["Cashflow"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"2026-01-01"},"required":false,"name":"dateFrom","in":"query"},{"schema":{"type":"string","example":"2026-01-31"},"required":false,"name":"dateTo","in":"query"},{"schema":{"type":"string","enum":["1m","3m","6m","1y","all"]},"required":false,"name":"timeRange","in":"query"}],"responses":{"200":{"description":"Cashflow summary","content":{"application/json":{"schema":{"type":"object","properties":{"expenseTotal":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Total expenses in user's preferred currency"},"incomeTotal":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Total income in user's preferred currency"},"net":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Net cashflow (income - expenses) in user's preferred currency"}},"required":["expenseTotal","incomeTotal","net"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/spending/summary":{"get":{"tags":["Spending"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["1m","3m","6m","1y","all"]},"required":true,"name":"timeRange","in":"query"},{"schema":{"type":"string"},"required":false,"name":"excludedCategories","in":"query"},{"schema":{"type":"string"},"required":false,"name":"categoryGroup","in":"query"}],"responses":{"200":{"description":"Spending summary over time","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"date":{"type":"string","description":"Date string for this spending period"}},"required":["date"],"additionalProperties":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Spending amount for this date in various currencies"}},"description":"Array of spending summaries by date, with amounts in different currencies"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/spending/categories":{"get":{"tags":["Spending"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"2026-01-01"},"required":false,"name":"dateFrom","in":"query"},{"schema":{"type":"string","example":"2026-01-31"},"required":false,"name":"dateTo","in":"query"},{"schema":{"type":"string","enum":["1m","3m","6m","1y","all"]},"required":false,"name":"timeRange","in":"query"},{"schema":{"type":"string"},"required":false,"name":"categories","in":"query"},{"schema":{"type":"string"},"required":false,"name":"topN","in":"query"}],"responses":{"200":{"description":"Category spending breakdown","content":{"application/json":{"schema":{"type":"object","properties":{"totalExpense":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Total expense amount in user's preferred currency"},"categories":{"type":"array","items":{"type":"object","properties":{"category":{"anyOf":[{"type":"string","enum":["BOOKS","CINEMA","CONCERT","HOBBY","MUSIC","NIGHTLIFE","SPORTS","SUBSCRIPTIONS","VACATION","VIDEO_GAMES"]},{"type":"string","enum":["DRINKS","COFFEE","DELIVERY","FAST_FOOD","GROCERIES","RESTAURANT","VENDING_MACHINE"]},{"type":"string","enum":["DOCTOR","DENTIST","MEDICINE","PHARMACY","THERAPY","VISION"]},{"type":"string","enum":["ELECTRICITY","FURNITURE","HARDWARE","INTERNET","MAINTANANCE","PHONE","RENT","HYDRO"]},{"type":"string","enum":["BEAUTY","CHARITY","CLOTHING","EDUCATION","GYM","HAIR","HOTEL","PET","SHOPPING"]},{"type":"string","enum":["ATM","CREDIT_CARD","CAR_LOAN","MORTGAGE","INSURANCE","STUDENT_LOAN","TAXES","TRANSFER_OUT"]},{"type":"string","enum":["ACCOUNTING","BANK_COST","CHILDCARE","ELECTRONICS","GIFTS","SHIPPING","SUPPLIES","OTHER"]},{"type":"string","enum":["BIKESHARE","BUS","GAS","FLIGHT","PARKING","REPAIR","TAXI","TRAIN"]}],"description":"Expense category name"},"total":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Total spending in this category"},"percentOfTotal":{"type":"number","description":"Percentage of total expense"}},"required":["category","total","percentOfTotal"]},"description":"Top categories sorted by spending amount"}},"required":["totalExpense","categories"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/spending/merchants/top":{"get":{"tags":["Spending"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","example":"2026-01-01"},"required":false,"name":"dateFrom","in":"query"},{"schema":{"type":"string","example":"2026-01-31"},"required":false,"name":"dateTo","in":"query"},{"schema":{"type":"string","enum":["1m","3m","6m","1y","all"]},"required":false,"name":"timeRange","in":"query"},{"schema":{"type":"string"},"required":false,"name":"query","in":"query"},{"schema":{"type":"string"},"required":false,"name":"topN","in":"query"}],"responses":{"200":{"description":"Top merchants by spending","content":{"application/json":{"schema":{"type":"object","properties":{"totalExpense":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Total expense amount in user's preferred currency"},"merchants":{"type":"array","items":{"type":"object","properties":{"merchant":{"type":"string","description":"Merchant name (normalized)"},"total":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Total spending at this merchant"},"percentOfTotal":{"type":"number","description":"Percentage of total expense"},"transactionCount":{"type":"number","description":"Number of transactions"}},"required":["merchant","total","percentOfTotal","transactionCount"]},"description":"Top merchants sorted by spending amount"}},"required":["totalExpense","merchants"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/recurring-payments":{"get":{"tags":["Transactions"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"monthsBack","in":"query"}],"responses":{"200":{"description":"Detected recurring payments","content":{"application/json":{"schema":{"type":"object","properties":{"recurring":{"type":"array","items":{"type":"object","properties":{"merchant":{"type":"string","description":"Merchant name"},"cadence":{"type":"string","enum":["monthly","yearly","unknown"],"description":"Detected payment cadence"},"avgAmount":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Average transaction amount"},"lastDate":{"type":"string","description":"Date of most recent transaction (YYYY-MM-DD)"},"nextDate":{"type":"string","description":"Estimated next payment date (YYYY-MM-DD)"},"occurrences":{"type":"number","description":"Number of occurrences detected"}},"required":["merchant","cadence","avgAmount","lastDate","occurrences"]},"description":"Detected recurring payments"}},"required":["recurring"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/budgets/categories":{"get":{"tags":["Budgets"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Budget categories","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"category":{"anyOf":[{"type":"string","enum":["DIVIDEND","GIFT","INTEREST","INVESTMENT","PENSION","REFUND","SALARY","TRANSFER_IN"]},{"type":"string","enum":["BOOKS","CINEMA","CONCERT","HOBBY","MUSIC","NIGHTLIFE","SPORTS","SUBSCRIPTIONS","VACATION","VIDEO_GAMES"]},{"type":"string","enum":["DRINKS","COFFEE","DELIVERY","FAST_FOOD","GROCERIES","RESTAURANT","VENDING_MACHINE"]},{"type":"string","enum":["DOCTOR","DENTIST","MEDICINE","PHARMACY","THERAPY","VISION"]},{"type":"string","enum":["ELECTRICITY","FURNITURE","HARDWARE","INTERNET","MAINTANANCE","PHONE","RENT","HYDRO"]},{"type":"string","enum":["BEAUTY","CHARITY","CLOTHING","EDUCATION","GYM","HAIR","HOTEL","PET","SHOPPING"]},{"type":"string","enum":["ATM","CREDIT_CARD","CAR_LOAN","MORTGAGE","INSURANCE","STUDENT_LOAN","TAXES","TRANSFER_OUT"]},{"type":"string","enum":["ACCOUNTING","BANK_COST","CHILDCARE","ELECTRONICS","GIFTS","SHIPPING","SUPPLIES","OTHER"]},{"type":"string","enum":["BIKESHARE","BUS","GAS","FLIGHT","PARKING","REPAIR","TAXI","TRAIN"]}]},"target_amount_cents":{"type":"number"},"currency":{"type":"string","nullable":true},"id":{"type":"string"}},"required":["category","target_amount_cents","currency","id"],"description":"Budget category with target amount and currency"},"description":"Array of all user-defined budget categories with their targets. Each category includes: category name, target amount in cents, currency code, and record ID."}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/budgets/summary":{"get":{"tags":["Budgets"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":false,"name":"month","in":"query"},{"schema":{"type":"string"},"required":false,"name":"year","in":"query"}],"responses":{"200":{"description":"Budget category summary","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"category":{"anyOf":[{"type":"string","enum":["BOOKS","CINEMA","CONCERT","HOBBY","MUSIC","NIGHTLIFE","SPORTS","SUBSCRIPTIONS","VACATION","VIDEO_GAMES"]},{"type":"string","enum":["DRINKS","COFFEE","DELIVERY","FAST_FOOD","GROCERIES","RESTAURANT","VENDING_MACHINE"]},{"type":"string","enum":["DOCTOR","DENTIST","MEDICINE","PHARMACY","THERAPY","VISION"]},{"type":"string","enum":["ELECTRICITY","FURNITURE","HARDWARE","INTERNET","MAINTANANCE","PHONE","RENT","HYDRO"]},{"type":"string","enum":["BEAUTY","CHARITY","CLOTHING","EDUCATION","GYM","HAIR","HOTEL","PET","SHOPPING"]},{"type":"string","enum":["ATM","CREDIT_CARD","CAR_LOAN","MORTGAGE","INSURANCE","STUDENT_LOAN","TAXES","TRANSFER_OUT"]},{"type":"string","enum":["ACCOUNTING","BANK_COST","CHILDCARE","ELECTRONICS","GIFTS","SHIPPING","SUPPLIES","OTHER"]},{"type":"string","enum":["BIKESHARE","BUS","GAS","FLIGHT","PARKING","REPAIR","TAXI","TRAIN"]}],"description":"Expense category name"},"total":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Total spending in this category for the specified month/year"},"target":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"],"description":"Budget target amount for this category (if set by user)"},"currency":{"type":"string","description":"Currency code for the amounts"}},"required":["category","total","currency"]},"description":"Array of budget category summaries showing spending vs. targets for each category"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/banks/status":{"get":{"tags":["Banks"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Connected bank status","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Item ID"},"bank_name":{"type":"string","description":"Bank name"},"needs_update":{"type":"boolean","description":"Whether the item needs an update"},"new_accounts_available":{"type":"boolean","description":"Whether new accounts are available"},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Account ID"},"name":{"type":"string","description":"Account name"},"type":{"type":"string","nullable":true,"description":"Account type"},"subtype":{"type":"string","nullable":true,"description":"Account subtype"},"balance_cents":{"type":"number","nullable":true,"description":"Account balance in cents"},"currency":{"type":"string","nullable":true,"description":"Account currency"}},"required":["id","name","type","subtype","balance_cents","currency"]}}},"required":["id","bank_name","needs_update","new_accounts_available","accounts"]}}},"required":["items"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/portfolio":{"get":{"tags":["Portfolio"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Redacted portfolio snapshot (no Plaid secrets; wallets and securities may use generic object maps)","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"]},"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"bank_name":{"type":"string"},"needs_update":{"type":"boolean"},"new_accounts_available":{"type":"boolean"},"total":{"type":"object","properties":{"amount_cents":{"type":"number"},"currency":{"type":"string"}},"required":["amount_cents","currency"]},"currency":{"type":"string"},"accounts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","nullable":true},"subtype":{"type":"string","nullable":true},"balance_cents":{"type":"number","nullable":true},"currency":{"type":"string","nullable":true},"updated_at":{"type":"string"},"has_holdings":{"type":"boolean"}},"required":["id","name","type","subtype","balance_cents","currency"]}}},"required":["id","total","currency","accounts"]}},"wallets":{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}},"paper_accounts":{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}},"securitiesByItem":{"type":"object","additionalProperties":{"type":"array","items":{"type":"object","properties":{"security":{"type":"object","additionalProperties":{"nullable":true}},"holding":{"type":"object","additionalProperties":{"nullable":true}},"accountId":{"type":"string"}},"required":["security","holding"]}},"default":{}}},"required":["total","items","wallets","paper_accounts"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/portfolio/history":{"get":{"tags":["Portfolio"],"security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["1m","3m","6m","1y"]},"required":false,"name":"timeRange","in":"query"}],"responses":{"200":{"description":"Portfolio time series","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"created_at":{"type":"string"},"currency":{"type":"string","nullable":true},"id":{"type":"string"},"total_amount_cents":{"type":"number"},"user_id":{"type":"string","nullable":true},"vault_balances":{"type":"array","nullable":true,"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["wallet","item","paper"]},"balance_cents":{"type":"number"},"currency":{"type":"string"}},"required":["id","type","balance_cents","currency"]}}},"required":["created_at","currency","id","total_amount_cents","user_id"]}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/preferences":{"get":{"tags":["Preferences"],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User preferences","content":{"application/json":{"schema":{"type":"object","properties":{"excluded_categories":{"type":"array","nullable":true,"items":{"anyOf":[{"type":"string","enum":["BOOKS","CINEMA","CONCERT","HOBBY","MUSIC","NIGHTLIFE","SPORTS","SUBSCRIPTIONS","VACATION","VIDEO_GAMES"]},{"type":"string","enum":["DRINKS","COFFEE","DELIVERY","FAST_FOOD","GROCERIES","RESTAURANT","VENDING_MACHINE"]},{"type":"string","enum":["DOCTOR","DENTIST","MEDICINE","PHARMACY","THERAPY","VISION"]},{"type":"string","enum":["ELECTRICITY","FURNITURE","HARDWARE","INTERNET","MAINTANANCE","PHONE","RENT","HYDRO"]},{"type":"string","enum":["BEAUTY","CHARITY","CLOTHING","EDUCATION","GYM","HAIR","HOTEL","PET","SHOPPING"]},{"type":"string","enum":["ATM","CREDIT_CARD","CAR_LOAN","MORTGAGE","INSURANCE","STUDENT_LOAN","TAXES","TRANSFER_OUT"]},{"type":"string","enum":["ACCOUNTING","BANK_COST","CHILDCARE","ELECTRONICS","GIFTS","SHIPPING","SUPPLIES","OTHER"]},{"type":"string","enum":["BIKESHARE","BUS","GAS","FLIGHT","PARKING","REPAIR","TAXI","TRAIN"]}]}}},"required":["excluded_categories"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid bearer token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}}}