{"openapi":"3.0.0","paths":{"/api/v1/api-keys/usage":{"get":{"operationId":"ApiKeyApiController_usage","summary":"Get current tier, today usage, and 30-day history","parameters":[],"responses":{"200":{"description":""}},"tags":["API Keys"],"security":[{"bearer":[]}]}},"/api/v1/api-keys":{"get":{"operationId":"ApiKeyApiController_findAll","summary":"List API keys for the authenticated user","parameters":[],"responses":{"200":{"description":""}},"tags":["API Keys"],"security":[{"bearer":[]}]},"post":{"operationId":"ApiKeyApiController_create","summary":"Create a new API key. Raw key is returned once.","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyDto"}}}},"responses":{"201":{"description":""}},"tags":["API Keys"],"security":[{"bearer":[]}]}},"/api/v1/api-keys/{id}":{"delete":{"operationId":"ApiKeyApiController_revoke","summary":"Revoke an API key","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"responses":{"204":{"description":""}},"tags":["API Keys"],"security":[{"bearer":[]}]}},"/api/v1/auth/login":{"post":{"operationId":"AuthApiController_login","summary":"Login and obtain JWT token","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequestDto"}}}},"responses":{"200":{"description":"Login successful"},"401":{"description":"Invalid credentials"}},"tags":["Auth"]}},"/api/v1/billing":{"get":{"operationId":"BillingApiController_getSubscription","summary":"Get current subscription summary","parameters":[],"responses":{"200":{"description":""}},"tags":["Billing"],"security":[{"bearer":[]}]}},"/api/v1/billing/checkout":{"post":{"operationId":"BillingApiController_checkout","summary":"Create a Stripe Checkout session for the given plan","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequestDto"}}}},"responses":{"201":{"description":""}},"tags":["Billing"],"security":[{"bearer":[]}]}},"/api/v1/billing/portal":{"post":{"operationId":"BillingApiController_portal","summary":"Create a Stripe Billing Portal session","parameters":[],"responses":{"201":{"description":""}},"tags":["Billing"],"security":[{"bearer":[]}]}},"/api/v1/cards":{"get":{"operationId":"CardApiController_search","summary":"Search cards by name","parameters":[{"name":"ascend","required":false,"in":"query","schema":{}},{"name":"sort","required":false,"in":"query","schema":{}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}},{"name":"q","required":true,"in":"query","description":"Search query","schema":{}}],"responses":{"200":{"description":"Search results"}},"tags":["Cards"]}},"/api/v1/cards/{cardId}/prices":{"get":{"operationId":"CardApiController_getPricesById","summary":"Get current prices for a card by ID","parameters":[{"name":"cardId","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Card prices"}},"tags":["Cards"]}},"/api/v1/cards/{cardId}/price-history":{"get":{"operationId":"CardApiController_getPriceHistoryById","summary":"Get price history for a card by ID","parameters":[{"name":"cardId","required":true,"in":"path","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"Number of days of history","schema":{"type":"string"}}],"responses":{"200":{"description":"Price history data"}},"tags":["Cards"]}},"/api/v1/cards/{setCode}/{setNumber}/prices":{"get":{"operationId":"CardApiController_getPricesBySetCodeAndNumber","summary":"Get current prices for a card by set code and number","parameters":[{"name":"setCode","required":true,"in":"path","schema":{"type":"string"}},{"name":"setNumber","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Card prices"},"404":{"description":"Card not found"}},"tags":["Cards"]}},"/api/v1/cards/{setCode}/{setNumber}/price-history":{"get":{"operationId":"CardApiController_getPriceHistoryBySetCodeAndNumber","summary":"Get price history for a card by set code and number","parameters":[{"name":"setCode","required":true,"in":"path","schema":{"type":"string"}},{"name":"setNumber","required":true,"in":"path","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"Number of days of history","schema":{"type":"string"}}],"responses":{"200":{"description":"Price history data"},"404":{"description":"Card not found"}},"tags":["Cards"]}},"/api/v1/cards/{setCode}/{setNumber}":{"get":{"operationId":"CardApiController_findBySetCodeAndNumber","summary":"Get card by set code and collector number","parameters":[{"name":"setCode","required":true,"in":"path","schema":{"type":"string"}},{"name":"setNumber","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Card detail"},"404":{"description":"Card not found"}},"tags":["Cards"]}},"/api/v1/inventory":{"get":{"operationId":"InventoryApiController_findAll","summary":"List inventory items","parameters":[{"name":"filter","required":false,"in":"query","schema":{}},{"name":"ascend","required":false,"in":"query","schema":{}},{"name":"sort","required":false,"in":"query","schema":{}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Inventory list"}},"tags":["Inventory"],"security":[{"bearer":[]}]},"post":{"operationId":"InventoryApiController_create","summary":"Add inventory items","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"responses":{"201":{"description":"Items added"}},"tags":["Inventory"],"security":[{"bearer":[]}]},"patch":{"operationId":"InventoryApiController_update","summary":"Update inventory items","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"string"}}}}},"responses":{"200":{"description":"Items updated"}},"tags":["Inventory"],"security":[{"bearer":[]}]},"delete":{"operationId":"InventoryApiController_delete","summary":"Delete inventory item","parameters":[],"responses":{"200":{"description":"Item deleted"}},"tags":["Inventory"],"security":[{"bearer":[]}]}},"/api/v1/inventory/quantities":{"get":{"operationId":"InventoryApiController_getQuantities","summary":"Get inventory quantities for a batch of card IDs","parameters":[{"name":"cardIds","required":true,"in":"query","description":"Comma-separated card IDs","schema":{"type":"string"}}],"responses":{"200":{"description":"Inventory quantities by card ID"}},"tags":["Inventory"],"security":[{"bearer":[]}]}},"/api/v1/portfolio":{"get":{"operationId":"PortfolioApiController_getSummary","summary":"Get portfolio summary","parameters":[],"responses":{"200":{"description":"Portfolio summary"}},"tags":["Portfolio"],"security":[{"bearer":[]}]}},"/api/v1/portfolio/history":{"get":{"operationId":"PortfolioApiController_getHistory","summary":"Get portfolio value history (Premium)","parameters":[{"name":"days","required":false,"in":"query","description":"Number of days of history","schema":{"type":"string"}}],"responses":{"200":{"description":"Value history data"},"403":{"description":"Premium subscription required"}},"tags":["Portfolio"],"security":[{"bearer":[]}]}},"/api/v1/portfolio/performance":{"get":{"operationId":"PortfolioApiController_getPerformance","summary":"Get card performance data","parameters":[{"name":"type","required":false,"in":"query","description":"best or worst","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Number of results","schema":{"type":"string"}}],"responses":{"200":{"description":"Card performance data"}},"tags":["Portfolio"],"security":[{"bearer":[]}]}},"/api/v1/portfolio/refresh":{"post":{"operationId":"PortfolioApiController_refresh","summary":"Refresh portfolio summary","parameters":[],"responses":{"200":{"description":"Summary refreshed"}},"tags":["Portfolio"],"security":[{"bearer":[]}]}},"/api/v1/portfolio/cash-flow":{"get":{"operationId":"PortfolioApiController_getCashFlow","summary":"Get cash flow periods (Premium)","parameters":[],"responses":{"200":{"description":"Cash flow data"},"403":{"description":"Premium subscription required"}},"tags":["Portfolio"],"security":[{"bearer":[]}]}},"/api/v1/portfolio/realized-gains":{"get":{"operationId":"PortfolioApiController_getRealizedGains","summary":"Get realized gains (Premium)","parameters":[],"responses":{"200":{"description":"Realized gains data"}},"tags":["Portfolio"],"security":[{"bearer":[]}]}},"/api/v1/portfolio/breakdown":{"get":{"operationId":"PortfolioApiController_getBreakdown","summary":"Get portfolio value breakdown by dimension (Premium)","parameters":[{"name":"by","required":false,"in":"query","description":"Dimension to group by (set, rarity, type, cost-basis)","schema":{"type":"string"}}],"responses":{"200":{"description":"Breakdown slices and totals"},"403":{"description":"Premium subscription required"}},"tags":["Portfolio"],"security":[{"bearer":[]}]}},"/api/v1/price-alerts":{"get":{"operationId":"PriceAlertApiController_findAll","summary":"List price alerts","parameters":[{"name":"page","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Price alert list"}},"tags":["Price Alerts"],"security":[{"bearer":[]}]},"post":{"operationId":"PriceAlertApiController_create","summary":"Create a price alert","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePriceAlertDto"}}}},"responses":{"201":{"description":"Alert created"}},"tags":["Price Alerts"],"security":[{"bearer":[]}]}},"/api/v1/price-alerts/{id}":{"patch":{"operationId":"PriceAlertApiController_update","summary":"Update a price alert","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePriceAlertDto"}}}},"responses":{"200":{"description":"Alert updated"}},"tags":["Price Alerts"],"security":[{"bearer":[]}]},"delete":{"operationId":"PriceAlertApiController_delete","summary":"Delete a price alert","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"responses":{"200":{"description":"Alert deleted"}},"tags":["Price Alerts"],"security":[{"bearer":[]}]}},"/api/v1/price-alerts/process":{"post":{"operationId":"PriceAlertApiController_process","summary":"Process price alerts (internal, called by cron)","parameters":[{"name":"x-api-key","required":true,"in":"header","schema":{"type":"string"}}],"responses":{"200":{"description":"Processing result"}},"tags":["Price Alerts"]}},"/api/v1/notifications":{"get":{"operationId":"PriceNotificationApiController_findAll","summary":"List notifications","parameters":[{"name":"page","required":false,"in":"query","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Notification list"}},"tags":["Notifications"],"security":[{"bearer":[]}]}},"/api/v1/notifications/unread-count":{"get":{"operationId":"PriceNotificationApiController_unreadCount","summary":"Get unread notification count","parameters":[],"responses":{"200":{"description":"Unread count"}},"tags":["Notifications"],"security":[{"bearer":[]}]}},"/api/v1/notifications/{id}/read":{"patch":{"operationId":"PriceNotificationApiController_markAsRead","summary":"Mark a notification as read","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"responses":{"200":{"description":"Marked as read"}},"tags":["Notifications"],"security":[{"bearer":[]}]}},"/api/v1/notifications/read-all":{"patch":{"operationId":"PriceNotificationApiController_markAllAsRead","summary":"Mark all notifications as read","parameters":[],"responses":{"200":{"description":"All marked as read"}},"tags":["Notifications"],"security":[{"bearer":[]}]}},"/api/v1/sets/{code}/sealed-products":{"get":{"operationId":"SealedProductApiController_findBySet","summary":"List sealed products for a set","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Sealed products for the set"}},"tags":["Sealed Products"]}},"/api/v1/sealed-products/{uuid}":{"get":{"operationId":"SealedProductApiController_findByUuid","summary":"Get sealed product detail","parameters":[{"name":"uuid","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Sealed product detail"},"404":{"description":"Not found"}},"tags":["Sealed Products"]}},"/api/v1/sealed-products/{uuid}/price-history":{"get":{"operationId":"SealedProductApiController_getPriceHistory","summary":"Get sealed product price history","parameters":[{"name":"uuid","required":true,"in":"path","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Price history data"}},"tags":["Sealed Products"]}},"/api/v1/inventory/sealed":{"get":{"operationId":"SealedProductApiController_findInventory","summary":"List sealed product inventory","parameters":[{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Sealed inventory list"}},"tags":["Sealed Products"],"security":[{"bearer":[]}]},"post":{"operationId":"SealedProductApiController_addToInventory","summary":"Add sealed product to inventory (Premium)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SealedInventoryRequestDto"}}}},"responses":{"201":{"description":"Item added"},"403":{"description":"Premium subscription required"}},"tags":["Sealed Products"],"security":[{"bearer":[]}]},"patch":{"operationId":"SealedProductApiController_updateInventory","summary":"Update sealed product inventory quantity (Premium)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SealedInventoryRequestDto"}}}},"responses":{"200":{"description":"Item updated"},"403":{"description":"Premium subscription required"}},"tags":["Sealed Products"],"security":[{"bearer":[]}]},"delete":{"operationId":"SealedProductApiController_removeFromInventory","summary":"Remove sealed product from inventory (Premium)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SealedInventoryDeleteRequestDto"}}}},"responses":{"200":{"description":"Item removed"},"403":{"description":"Premium subscription required"}},"tags":["Sealed Products"],"security":[{"bearer":[]}]}},"/api/v1/sets":{"get":{"operationId":"SetApiController_findAll","summary":"List sets","parameters":[{"name":"group","required":false,"in":"query","description":"Grouping mode: \"block\" for block-level pagination","schema":{}},{"name":"q","required":false,"in":"query","description":"Search query","schema":{}},{"name":"baseOnly","required":false,"in":"query","description":"Show only base/main sets","schema":{}},{"name":"filter","required":false,"in":"query","description":"Filter sets by name","schema":{}},{"name":"ascend","required":false,"in":"query","schema":{}},{"name":"sort","required":false,"in":"query","schema":{}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"List of sets"}},"tags":["Sets"]}},"/api/v1/sets/{code}":{"get":{"operationId":"SetApiController_findByCode","summary":"Get set detail by code","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Set detail"},"404":{"description":"Set not found"}},"tags":["Sets"]}},"/api/v1/sets/{code}/cards":{"get":{"operationId":"SetApiController_findCardsInSet","summary":"Get cards in a set","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"baseOnly","required":false,"in":"query","description":"Show only base set cards","schema":{}},{"name":"filter","required":false,"in":"query","description":"Filter cards by name","schema":{}},{"name":"ascend","required":false,"in":"query","schema":{}},{"name":"sort","required":false,"in":"query","schema":{}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Cards in set"}},"tags":["Sets"]}},"/api/v1/sets/{code}/price-history":{"get":{"operationId":"SetApiController_getPriceHistory","summary":"Get set price history","parameters":[{"name":"code","required":true,"in":"path","schema":{"type":"string"}},{"name":"days","required":false,"in":"query","description":"Number of days of history","schema":{"type":"string"}}],"responses":{"200":{"description":"Set price history data"}},"tags":["Sets"]}},"/api/v1/transactions":{"get":{"operationId":"TransactionApiController_findAll","summary":"List all transactions","parameters":[{"name":"filter","required":false,"in":"query","schema":{}},{"name":"ascend","required":false,"in":"query","schema":{}},{"name":"sort","required":false,"in":"query","schema":{}},{"name":"limit","required":false,"in":"query","schema":{}},{"name":"page","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Transaction list"}},"tags":["Transactions"],"security":[{"bearer":[]}]},"post":{"operationId":"TransactionApiController_create","summary":"Create transaction","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionRequestDto"}}}},"responses":{"201":{"description":"Transaction created"}},"tags":["Transactions"],"security":[{"bearer":[]}]}},"/api/v1/transactions/{id}":{"put":{"operationId":"TransactionApiController_update","summary":"Update transaction","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionUpdateRequestDto"}}}},"responses":{"200":{"description":"Transaction updated"}},"tags":["Transactions"],"security":[{"bearer":[]}]},"delete":{"operationId":"TransactionApiController_delete","summary":"Delete transaction","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"number"}}],"responses":{"200":{"description":"Transaction deleted"}},"tags":["Transactions"],"security":[{"bearer":[]}]}},"/api/v1/transactions/cost-basis/{cardId}":{"get":{"operationId":"TransactionApiController_getCostBasisById","summary":"Get cost basis for a card by ID","parameters":[{"name":"cardId","required":true,"in":"path","schema":{"type":"string"}},{"name":"isFoil","required":false,"in":"query","description":"Whether to check foil version","schema":{"type":"string"}}],"responses":{"200":{"description":"Cost basis data"}},"tags":["Transactions"],"security":[{"bearer":[]}]}},"/api/v1/transactions/cost-basis/{setCode}/{setNumber}":{"get":{"operationId":"TransactionApiController_getCostBasisBySetCodeAndNumber","summary":"Get cost basis for a card by set code and number","parameters":[{"name":"setCode","required":true,"in":"path","schema":{"type":"string"}},{"name":"setNumber","required":true,"in":"path","schema":{"type":"string"}},{"name":"isFoil","required":false,"in":"query","description":"Whether to check foil version","schema":{"type":"string"}}],"responses":{"200":{"description":"Cost basis data"},"404":{"description":"Card not found"}},"tags":["Transactions"],"security":[{"bearer":[]}]}},"/api/v1/user":{"get":{"operationId":"UserApiController_getProfile","summary":"Get current user profile","parameters":[],"responses":{"200":{"description":"User profile"}},"tags":["User"],"security":[{"bearer":[]}]},"patch":{"operationId":"UserApiController_updateProfile","summary":"Update user profile (session only, not API keys)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequestDto"}}}},"responses":{"200":{"description":"Profile updated"}},"tags":["User"],"security":[{"bearer":[]}]},"delete":{"operationId":"UserApiController_deleteAccount","summary":"Delete account (session only, not API keys)","parameters":[],"responses":{"200":{"description":"Account deleted"}},"tags":["User"],"security":[{"bearer":[]}]}},"/api/v1/user/export":{"get":{"operationId":"UserApiController_exportData","summary":"Export all personal data as JSON","parameters":[],"responses":{"200":{"description":"User data export"}},"tags":["User"],"security":[{"bearer":[]}]}},"/api/v1/user/password":{"patch":{"operationId":"UserApiController_updatePassword","summary":"Update password (session only, not API keys)","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordRequestDto"}}}},"responses":{"200":{"description":"Password updated"}},"tags":["User"],"security":[{"bearer":[]}]}}},"info":{"title":"I Want My MTG API","description":"REST API for Magic: The Gathering collection tracking","version":"1.0","contact":{}},"tags":[],"servers":[],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{"CreateApiKeyDto":{"type":"object","properties":{"name":{"type":"string","description":"User-supplied label for the key","maxLength":64}},"required":["name"]},"LoginRequestDto":{"type":"object","properties":{"email":{"type":"string","example":"user@example.com"},"password":{"type":"string"}},"required":["email","password"]},"CheckoutRequestDto":{"type":"object","properties":{"plan":{"type":"string","enum":["monthly","annual"]}},"required":["plan"]},"CreatePriceAlertDto":{"type":"object","properties":{}},"UpdatePriceAlertDto":{"type":"object","properties":{}},"SealedInventoryRequestDto":{"type":"object","properties":{"sealedProductUuid":{"type":"string"},"quantity":{"type":"number"}},"required":["sealedProductUuid","quantity"]},"SealedInventoryDeleteRequestDto":{"type":"object","properties":{"sealedProductUuid":{"type":"string"}},"required":["sealedProductUuid"]},"TransactionRequestDto":{"type":"object","properties":{}},"TransactionUpdateRequestDto":{"type":"object","properties":{}},"UpdateUserRequestDto":{"type":"object","properties":{}},"UpdatePasswordRequestDto":{"type":"object","properties":{}}}}}