# PortfolioHub API Examples ## 1. Purpose This document contains example requests and responses for PortfolioHub HTTP APIs. - Sync rule: when files under `app/api/` or `app/schemas/` change, this document must be updated in the same commit/PR. - Companion spec: `docs/portfoliohub-spec.md` ## 2. Conventions - Base URL example: `http://localhost:8000` - Auth header format: `Authorization: Bearer ` - JSON examples are representative and may omit some optional fields. ## 3. Health ### 3.1 GET /health Request: ```bash curl -X GET "http://localhost:8000/health" ``` Response 200: ```json { "status": "ok" } ``` ## 4. Portfolios ### 4.1 GET /portfolios Request: ```bash curl -X GET "http://localhost:8000/portfolios?broker=upbit&status_filter=enabled" \ -H "Authorization: Bearer " ``` Response 200: ```json [ { "portfolio_id": "krw-btc", "broker": "upbit", "status": "enabled", "symbol": "KRW-BTC", "cash_balance": 1000000.0, "asset_quantity": 0.1, "price": 100000000.0, "profit_buffer": 0.0, "active_strategy_id": "stv-001", "avabile_strategies": ["stv-001"], "created_at": "2026-04-03T00:00:00Z", "updated_at": "2026-04-03T00:00:00Z", "last_trade_at": "2026-04-03T00:00:00Z", "total_value": 11000000.0 } ] ``` ### 4.2 GET /portfolios/{portfolio_id} Request: ```bash curl -X GET "http://localhost:8000/portfolios/krw-btc?recent_trades=5" \ -H "Authorization: Bearer " ``` Response 200: ```json { "portfolio": { "portfolio_id": "krw-btc", "broker": "upbit", "status": "enabled", "symbol": "KRW-BTC", "cash_balance": 1000000.0, "asset_quantity": 0.1, "price": 100000000.0, "profit_buffer": 0.0, "active_strategy_id": "stv-001", "avabile_strategies": ["stv-001"], "created_at": "2026-04-03T00:00:00Z", "updated_at": "2026-04-03T00:00:00Z", "last_trade_at": "2026-04-03T00:00:00Z" }, "recent_entries": [ { "portfolio_id": "krw-btc", "recorded_at": "2026-04-03T00:00:00Z", "action": "buy", "price": 100000000.0, "quantity": 0.1, "fee_amount": 0.0, "tax_amount": 0.0, "cash_balance_after": 1000000.0, "asset_quantity_after": 0.1, "total_value_after": 11000000.0, "profit_buffer_after": 0.0, "strategy_set_id": "stv-001", "note": "" } ], "strategy_set": { "id": "stv-001", "name": "target_value", "config": "{}", "nick": "target_value:99914b932bd3", "created_at": "2026-04-03T00:00:00Z" }, "live_quantity": null } ``` ### 4.3 POST /portfolios Request: ```bash curl -X POST "http://localhost:8000/portfolios" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "portfolio_id": "krw-btc", "broker": "upbit", "status": "enabled", "symbol": "KRW-BTC", "strategy_name": "target_value", "strategy_params": {}, "active_strategy_id": null, "avabile_strategies": null, "cash_balance": 1000000, "asset_quantity": 0, "asset_price": 0, "profit_buffer": 0 }' ``` Response 201: - Response body shape is `PortfolioDetailResponse` (same as 4.2). ### 4.4 PATCH /portfolios/{portfolio_id} Request: ```bash curl -X PATCH "http://localhost:8000/portfolios/krw-btc" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "broker": "upbit", "symbol": "KRW-BTC" }' ``` Response 200: - Response body shape is `PortfolioDetailResponse`. ### 4.5 POST /portfolios/{portfolio_id}/buy Request: ```bash curl -X POST "http://localhost:8000/portfolios/krw-btc/buy" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"quantity": 0.01, "price": 100000000, "fee": 0, "tax": 0, "note": ""}' ``` Response 200: - Response body shape is `PortfolioDetailResponse`. ### 4.6 POST /portfolios/{portfolio_id}/sell Request: ```bash curl -X POST "http://localhost:8000/portfolios/krw-btc/sell" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"quantity": 0.01, "price": 100000000, "fee": 0, "tax": 0, "note": ""}' ``` Response 200: - Response body shape is `PortfolioDetailResponse`. ### 4.7 POST /portfolios/{portfolio_id}/invest Request: ```bash curl -X POST "http://localhost:8000/portfolios/krw-btc/invest" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"movement_type": "deposit", "amount": 50000, "note": ""}' ``` Response 200: - Response body shape is `PortfolioDetailResponse`. ### 4.8 POST /portfolios/{portfolio_id}/transfer Request: ```bash curl -X POST "http://localhost:8000/portfolios/krw-btc/transfer" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"direction": "to-buffer", "amount": 10000, "note": ""}' ``` Response 200: - Response body shape is `PortfolioDetailResponse`. ### 4.9 POST /portfolios/{portfolio_id}/reset Request: ```bash curl -X POST "http://localhost:8000/portfolios/krw-btc/reset" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"infer_symbol": "KRW-BTC"}' ``` Response 200: - Response body shape is `PortfolioDetailResponse`. ### 4.10 DELETE /portfolios/{portfolio_id} Request: ```bash curl -X DELETE "http://localhost:8000/portfolios/krw-btc?keep_ledger=false" \ -H "Authorization: Bearer " ``` Response 204: - No content. ## 5. Common Error Examples ### 5.1 Missing token Response 401: ```json { "detail": "Missing bearer token" } ``` ### 5.2 Invalid token Response 401: ```json { "detail": "Invalid token" } ``` ### 5.3 Insufficient permission Response 403: ```json { "detail": "Insufficient permission" } ```