--- openapi: 3.0.3 info: title: Sure API version: v1 description: OpenAPI documentation generated from executable request specs. servers: - url: https://app.sure.am description: Production - url: http://localhost:3000 description: Local development components: securitySchemes: apiKeyAuth: type: apiKey name: X-Api-Key in: header description: API key for authentication. Generate one from your account settings. schemas: Pagination: type: object required: - page - per_page - total_count - total_pages properties: page: type: integer minimum: 1 per_page: type: integer minimum: 1 total_count: type: integer minimum: 0 total_pages: type: integer minimum: 0 ErrorResponse: type: object required: - error properties: error: type: string message: type: string nullable: true details: oneOf: - type: array items: type: string - type: object nullable: true errors: type: array items: type: string nullable: true description: Validation error messages (alternative to details used by trades, valuations, etc.) ErrorResponseWithImportId: type: object required: - error - import_id properties: error: type: string message: type: string nullable: true import_id: type: string format: uuid description: Import ID preserved for retry or inspection after upload succeeds but publish fails MfaRequiredResponse: type: object required: - error - mfa_required properties: error: type: string mfa_required: type: boolean ToolCall: type: object required: - id - function_name - function_arguments - created_at properties: id: type: string format: uuid function_name: type: string function_arguments: type: object additionalProperties: true function_result: type: object additionalProperties: true nullable: true created_at: type: string format: date-time Message: type: object required: - id - type - role - content - created_at - updated_at properties: id: type: string format: uuid type: type: string enum: - user_message - assistant_message role: type: string enum: - user - assistant content: type: string model: type: string nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time tool_calls: type: array items: "$ref": "#/components/schemas/ToolCall" nullable: true MessageResponse: allOf: - "$ref": "#/components/schemas/Message" - type: object required: - chat_id properties: chat_id: type: string format: uuid ai_response_status: type: string enum: - pending - complete - failed nullable: true ai_response_message: type: string nullable: true ChatResource: type: object required: - id - title - created_at - updated_at properties: id: type: string format: uuid title: type: string error: type: string nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time ChatSummary: allOf: - "$ref": "#/components/schemas/ChatResource" - type: object required: - message_count properties: message_count: type: integer minimum: 0 last_message_at: type: string format: date-time nullable: true ChatDetail: allOf: - "$ref": "#/components/schemas/ChatResource" - type: object required: - messages properties: messages: type: array items: "$ref": "#/components/schemas/Message" pagination: "$ref": "#/components/schemas/Pagination" nullable: true ChatCollection: type: object required: - chats - pagination properties: chats: type: array items: "$ref": "#/components/schemas/ChatSummary" pagination: "$ref": "#/components/schemas/Pagination" RetryResponse: type: object required: - message - message_id properties: message: type: string message_id: type: string format: uuid Account: type: object required: - id - name - account_type properties: id: type: string format: uuid name: type: string account_type: type: string nullable: true status: type: string AccountDetail: type: object required: - id - name - balance - balance_cents - cash_balance - cash_balance_cents - currency - classification - account_type - status - created_at - updated_at properties: id: type: string format: uuid name: type: string balance: type: string balance_cents: type: integer description: Signed balance in minor currency units cash_balance: type: string cash_balance_cents: type: integer description: Signed cash balance in minor currency units currency: type: string classification: type: string account_type: type: string nullable: true subtype: type: string nullable: true status: type: string enum: - active - draft - disabled - pending_deletion institution_name: type: string nullable: true institution_domain: type: string nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time AccountCollection: type: object required: - accounts - pagination properties: accounts: type: array items: "$ref": "#/components/schemas/AccountDetail" pagination: "$ref": "#/components/schemas/Pagination" Category: type: object required: - id - name - color - icon properties: id: type: string format: uuid name: type: string color: type: string icon: type: string CategoryParent: type: object required: - id - name properties: id: type: string format: uuid name: type: string CategoryDetail: type: object required: - id - name - color - icon - subcategories_count - created_at - updated_at properties: id: type: string format: uuid name: type: string color: type: string icon: type: string parent: "$ref": "#/components/schemas/CategoryParent" nullable: true subcategories_count: type: integer minimum: 0 created_at: type: string format: date-time updated_at: type: string format: date-time CategoryCollection: type: object required: - categories - pagination properties: categories: type: array items: "$ref": "#/components/schemas/CategoryDetail" pagination: "$ref": "#/components/schemas/Pagination" Merchant: type: object required: - id - name properties: id: type: string format: uuid name: type: string MerchantDetail: type: object required: - id - name - type - created_at - updated_at properties: id: type: string format: uuid name: type: string type: type: string enum: - FamilyMerchant - ProviderMerchant created_at: type: string format: date-time updated_at: type: string format: date-time Tag: type: object required: - id - name - color properties: id: type: string format: uuid name: type: string color: type: string TagDetail: type: object required: - id - name - color - created_at - updated_at properties: id: type: string format: uuid name: type: string color: type: string created_at: type: string format: date-time updated_at: type: string format: date-time TagCollection: type: array items: "$ref": "#/components/schemas/TagDetail" RuleAction: type: object required: - id - action_type - created_at - updated_at properties: id: type: string format: uuid action_type: type: string value: type: string nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time RuleCondition: type: object required: - id - condition_type - operator - sub_conditions - created_at - updated_at properties: id: type: string format: uuid condition_type: type: string operator: type: string value: type: string nullable: true sub_conditions: type: array items: "$ref": "#/components/schemas/RuleCondition" created_at: type: string format: date-time updated_at: type: string format: date-time Rule: type: object required: - id - resource_type - active - conditions - actions - created_at - updated_at properties: id: type: string format: uuid name: type: string nullable: true resource_type: type: string enum: - transaction active: type: boolean effective_date: type: string format: date nullable: true conditions: type: array items: "$ref": "#/components/schemas/RuleCondition" actions: type: array items: "$ref": "#/components/schemas/RuleAction" created_at: type: string format: date-time updated_at: type: string format: date-time RuleResponse: type: object required: - data properties: data: "$ref": "#/components/schemas/Rule" RuleCollection: type: object required: - data - meta properties: data: type: array items: "$ref": "#/components/schemas/Rule" meta: type: object required: - current_page - total_pages - total_count - per_page properties: current_page: type: integer next_page: type: integer nullable: true prev_page: type: integer nullable: true total_pages: type: integer total_count: type: integer per_page: type: integer Transfer: type: object required: - id - amount - currency properties: id: type: string format: uuid amount: type: string currency: type: string other_account: "$ref": "#/components/schemas/Account" nullable: true RecurringTransaction: type: object required: - id - amount - amount_cents - currency - expected_day_of_month - last_occurrence_date - next_expected_date - status - occurrence_count - manual - created_at - updated_at properties: id: type: string format: uuid amount: type: string amount_cents: type: integer description: Amount in currency minor units currency: type: string expected_day_of_month: type: integer minimum: 1 maximum: 31 last_occurrence_date: type: string format: date next_expected_date: type: string format: date status: type: string enum: - active - inactive occurrence_count: type: integer minimum: 0 name: type: string nullable: true manual: type: boolean expected_amount_min: type: string nullable: true expected_amount_min_cents: type: integer nullable: true description: Minimum expected amount in currency minor units expected_amount_max: type: string nullable: true expected_amount_max_cents: type: integer nullable: true description: Maximum expected amount in currency minor units expected_amount_avg: type: string nullable: true expected_amount_avg_cents: type: integer nullable: true description: Average expected amount in currency minor units account: "$ref": "#/components/schemas/Account" nullable: true merchant: "$ref": "#/components/schemas/Merchant" nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time RecurringTransactionCollection: type: object required: - recurring_transactions - pagination properties: recurring_transactions: type: array items: "$ref": "#/components/schemas/RecurringTransaction" pagination: "$ref": "#/components/schemas/Pagination" Transaction: type: object required: - id - date - amount - currency - name - classification - account - tags - created_at - updated_at properties: id: type: string format: uuid date: type: string format: date amount: type: string currency: type: string name: type: string notes: type: string nullable: true classification: type: string account: "$ref": "#/components/schemas/Account" category: "$ref": "#/components/schemas/Category" nullable: true merchant: "$ref": "#/components/schemas/Merchant" nullable: true tags: type: array items: "$ref": "#/components/schemas/Tag" transfer: "$ref": "#/components/schemas/Transfer" nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time TransactionCollection: type: object required: - transactions - pagination properties: transactions: type: array items: "$ref": "#/components/schemas/Transaction" pagination: "$ref": "#/components/schemas/Pagination" Valuation: type: object required: - id - date - amount - currency - kind - account - created_at - updated_at properties: id: type: string format: uuid date: type: string format: date amount: type: string currency: type: string notes: type: string nullable: true kind: type: string account: "$ref": "#/components/schemas/Account" created_at: type: string format: date-time updated_at: type: string format: date-time ValuationCollection: type: object required: - valuations - pagination properties: valuations: type: array items: "$ref": "#/components/schemas/Valuation" pagination: "$ref": "#/components/schemas/Pagination" DeleteResponse: type: object required: - message properties: message: type: string ImportConfiguration: type: object properties: date_col_label: type: string nullable: true amount_col_label: type: string nullable: true name_col_label: type: string nullable: true category_col_label: type: string nullable: true tags_col_label: type: string nullable: true notes_col_label: type: string nullable: true account_col_label: type: string nullable: true date_format: type: string nullable: true number_format: type: string nullable: true signage_convention: type: string nullable: true ImportStats: type: object required: - rows_count - valid_rows_count - invalid_rows_count - mappings_count - unassigned_mappings_count properties: rows_count: type: integer minimum: 0 valid_rows_count: type: integer minimum: 0 invalid_rows_count: type: integer minimum: 0 mappings_count: type: integer minimum: 0 unassigned_mappings_count: type: integer minimum: 0 ImportStatusSummary: type: object required: - uploaded - configured - terminal properties: uploaded: type: boolean configured: type: boolean terminal: type: boolean ImportStatusDetail: allOf: - "$ref": "#/components/schemas/ImportStatusSummary" - type: object required: - cleaned - publishable - revertable properties: cleaned: type: boolean publishable: type: boolean revertable: type: boolean ImportSummary: type: object required: - id - type - status - created_at - updated_at - status_detail properties: id: type: string format: uuid type: type: string enum: - TransactionImport - TradeImport - AccountImport - MintImport - CategoryImport - RuleImport - SureImport status: type: string enum: - pending - complete - importing - reverting - revert_failed - failed created_at: type: string format: date-time updated_at: type: string format: date-time account_id: type: string format: uuid nullable: true rows_count: type: integer minimum: 0 error: type: string nullable: true status_detail: "$ref": "#/components/schemas/ImportStatusSummary" ImportDetail: type: object required: - id - type - status - created_at - updated_at - status_detail - configuration - stats properties: id: type: string format: uuid type: type: string enum: - TransactionImport - TradeImport - AccountImport - MintImport - CategoryImport - RuleImport - SureImport status: type: string enum: - pending - complete - importing - reverting - revert_failed - failed created_at: type: string format: date-time updated_at: type: string format: date-time account_id: type: string format: uuid nullable: true error: type: string nullable: true status_detail: "$ref": "#/components/schemas/ImportStatusDetail" configuration: "$ref": "#/components/schemas/ImportConfiguration" stats: "$ref": "#/components/schemas/ImportStats" ImportCollection: type: object required: - data - meta properties: data: type: array items: "$ref": "#/components/schemas/ImportSummary" meta: type: object required: - current_page - total_pages - total_count - per_page properties: current_page: type: integer minimum: 1 next_page: type: integer nullable: true prev_page: type: integer nullable: true total_pages: type: integer minimum: 0 total_count: type: integer minimum: 0 per_page: type: integer minimum: 1 ImportResponse: type: object required: - data properties: data: "$ref": "#/components/schemas/ImportDetail" Trade: type: object required: - id - date - amount - currency - name - qty - price - account - created_at - updated_at properties: id: type: string format: uuid date: type: string format: date amount: type: string currency: type: string name: type: string notes: type: string nullable: true qty: type: string price: type: string investment_activity_label: type: string nullable: true account: "$ref": "#/components/schemas/Account" security: type: object nullable: true properties: id: type: string format: uuid ticker: type: string name: type: string nullable: true category: type: object nullable: true properties: id: type: string format: uuid name: type: string created_at: type: string format: date-time updated_at: type: string format: date-time TradeCollection: type: object required: - trades - pagination properties: trades: type: array items: "$ref": "#/components/schemas/Trade" pagination: "$ref": "#/components/schemas/Pagination" Holding: type: object required: - id - date - qty - price - amount - currency - account - security - created_at - updated_at properties: id: type: string format: uuid date: type: string format: date qty: type: string description: Quantity of shares held price: type: string description: Formatted price per share amount: type: string currency: type: string cost_basis_source: type: string nullable: true account: "$ref": "#/components/schemas/Account" security: type: object required: - id - ticker - name properties: id: type: string format: uuid ticker: type: string name: type: string nullable: true avg_cost: type: string nullable: true created_at: type: string format: date-time updated_at: type: string format: date-time HoldingCollection: type: object required: - holdings - pagination properties: holdings: type: array items: "$ref": "#/components/schemas/Holding" pagination: "$ref": "#/components/schemas/Pagination" Money: type: object required: - amount - currency - formatted properties: amount: type: string description: Numeric amount as string currency: type: string description: ISO 4217 currency code formatted: type: string description: Locale-formatted money string BalanceSheet: type: object required: - currency - net_worth - assets - liabilities properties: currency: type: string description: Family primary currency net_worth: "$ref": "#/components/schemas/Money" assets: "$ref": "#/components/schemas/Money" liabilities: "$ref": "#/components/schemas/Money" SuccessMessage: type: object required: - message properties: message: type: string paths: "/api/v1/accounts": get: summary: List accounts tags: - Accounts security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: include_disabled in: query required: false description: Include disabled accounts in the response. Defaults to false. schema: type: boolean responses: '200': description: accounts paginated content: application/json: schema: "$ref": "#/components/schemas/AccountCollection" "/api/v1/accounts/{id}": parameters: - name: id in: path required: true description: Account ID schema: type: string format: uuid get: summary: Retrieve an account tags: - Accounts security: - apiKeyAuth: [] parameters: - name: include_disabled in: query required: false description: Allow retrieving a disabled account. Defaults to false. schema: type: boolean responses: '200': description: account retrieved content: application/json: schema: "$ref": "#/components/schemas/AccountDetail" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: insufficient scope content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: account not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/auth/signup": post: summary: Sign up a new user tags: - Auth parameters: [] responses: '201': description: user created content: application/json: schema: type: object properties: access_token: type: string refresh_token: type: string token_type: type: string expires_in: type: integer created_at: type: integer user: type: object properties: id: type: string format: uuid email: type: string first_name: type: string last_name: type: string ui_layout: type: string enum: - dashboard - intro ai_enabled: type: boolean '422': description: validation error content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: invite code required or invalid content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: user: type: object properties: email: type: string format: email description: User email address password: type: string description: Password (min 8 chars, mixed case, number, special char) first_name: type: string last_name: type: string required: - email - password device: type: object properties: device_id: type: string description: Unique device identifier device_name: type: string description: Human-readable device name device_type: type: string description: Device type (e.g. ios, android) os_version: type: string app_version: type: string required: - device_id - device_name - device_type - os_version - app_version invite_code: type: string nullable: true description: Invite code (required when invites are enforced) required: - user - device required: true "/api/v1/auth/login": post: summary: Log in with email and password tags: - Auth parameters: [] responses: '200': description: login successful content: application/json: schema: type: object properties: access_token: type: string refresh_token: type: string token_type: type: string expires_in: type: integer created_at: type: integer user: type: object properties: id: type: string format: uuid email: type: string first_name: type: string last_name: type: string ui_layout: type: string enum: - dashboard - intro ai_enabled: type: boolean '401': description: invalid credentials or MFA required content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: email: type: string format: email password: type: string otp_code: type: string nullable: true description: TOTP code if MFA is enabled device: type: object properties: device_id: type: string device_name: type: string device_type: type: string os_version: type: string app_version: type: string required: - device_id - device_name - device_type - os_version - app_version required: - email - password - device required: true "/api/v1/auth/sso_exchange": post: summary: Exchange mobile SSO authorization code for tokens tags: - Auth description: Exchanges a one-time authorization code (received via deep link after mobile SSO) for OAuth tokens. The code is single-use and expires after 5 minutes. parameters: [] responses: '200': description: tokens issued content: application/json: schema: type: object properties: access_token: type: string refresh_token: type: string token_type: type: string expires_in: type: integer created_at: type: integer user: type: object properties: id: type: string format: uuid email: type: string first_name: type: string last_name: type: string ui_layout: type: string enum: - dashboard - intro ai_enabled: type: boolean '401': description: invalid or expired code content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: code: type: string description: One-time authorization code from mobile SSO callback required: - code required: true "/api/v1/auth/refresh": post: summary: Refresh an access token tags: - Auth parameters: [] responses: '200': description: token refreshed content: application/json: schema: type: object properties: access_token: type: string refresh_token: type: string token_type: type: string expires_in: type: integer created_at: type: integer '401': description: invalid refresh token content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '400': description: missing refresh token content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: refresh_token: type: string description: The refresh token from a previous login or refresh device: type: object properties: device_id: type: string required: - device_id required: - refresh_token - device required: true "/api/v1/auth/sso_link": post: summary: Link an existing account via SSO tags: - Auth description: Authenticates with email/password and links the SSO identity from a previously issued linking code. Creates an OidcIdentity, logs the link via SsoAuditLog, and issues mobile OAuth tokens. parameters: [] responses: '200': description: account linked and tokens issued content: application/json: schema: type: object properties: access_token: type: string refresh_token: type: string token_type: type: string expires_in: type: integer created_at: type: integer user: type: object properties: id: type: string format: uuid email: type: string first_name: type: string last_name: type: string ui_layout: type: string enum: - dashboard - intro ai_enabled: type: boolean '400': description: missing linking code content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '401': description: invalid credentials or expired linking code content: application/json: schema: oneOf: - "$ref": "#/components/schemas/ErrorResponse" - "$ref": "#/components/schemas/MfaRequiredResponse" requestBody: content: application/json: schema: type: object properties: linking_code: type: string description: One-time linking code from mobile SSO onboarding redirect email: type: string format: email description: Email of the existing account to link password: type: string description: Password for the existing account required: - linking_code - email - password required: true "/api/v1/auth/sso_create_account": post: summary: Create a new account via SSO tags: - Auth description: Creates a new user and family from a previously issued linking code. Links the SSO identity via OidcIdentity, logs the JIT account creation via SsoAuditLog, and issues mobile OAuth tokens. The linking code must have allow_account_creation enabled. parameters: [] responses: '200': description: account created and tokens issued content: application/json: schema: type: object properties: access_token: type: string refresh_token: type: string token_type: type: string expires_in: type: integer created_at: type: integer user: type: object properties: id: type: string format: uuid email: type: string first_name: type: string last_name: type: string ui_layout: type: string enum: - dashboard - intro ai_enabled: type: boolean '400': description: missing linking code content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '401': description: invalid or expired linking code content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: account creation disabled content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: user validation error content: application/json: schema: type: object properties: errors: type: array items: type: string requestBody: content: application/json: schema: type: object properties: linking_code: type: string description: One-time linking code from mobile SSO onboarding redirect first_name: type: string description: First name (overrides value from SSO provider if provided) last_name: type: string description: Last name (overrides value from SSO provider if provided) required: - linking_code required: true "/api/v1/auth/enable_ai": patch: summary: Enable AI features for the authenticated user tags: - Auth security: - apiKeyAuth: [] responses: '200': description: ai enabled content: application/json: schema: type: object properties: user: type: object properties: id: type: string format: uuid email: type: string first_name: type: string nullable: true last_name: type: string nullable: true ui_layout: type: string enum: - dashboard - intro ai_enabled: type: boolean '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: insufficient scope content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/balance_sheet": get: summary: Show balance sheet tags: - Balance Sheet description: Returns the family balance sheet including net worth, total assets, and total liabilities with amounts converted to the family's primary currency. security: - apiKeyAuth: [] responses: '200': description: balance sheet returned content: application/json: schema: "$ref": "#/components/schemas/BalanceSheet" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/categories": get: summary: List categories tags: - Categories security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: roots_only in: query required: false description: Return only root categories (no parent) schema: type: boolean - name: parent_id in: query required: false description: Filter by parent category ID schema: type: string format: uuid responses: '200': description: categories filtered by parent content: application/json: schema: "$ref": "#/components/schemas/CategoryCollection" "/api/v1/categories/{id}": parameters: - name: id in: path required: true description: Category ID schema: type: string get: summary: Retrieve a category tags: - Categories security: - apiKeyAuth: [] responses: '200': description: subcategory retrieved with parent content: application/json: schema: "$ref": "#/components/schemas/CategoryDetail" '404': description: category not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/chats": get: summary: List chats tags: - Chats security: - apiKeyAuth: [] responses: '200': description: chats listed content: application/json: schema: "$ref": "#/components/schemas/ChatCollection" '403': description: AI features disabled content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create chat tags: - Chats security: - apiKeyAuth: [] parameters: [] responses: '201': description: chat created content: application/json: schema: "$ref": "#/components/schemas/ChatDetail" '422': description: validation error content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: title: type: string example: Monthly budget review message: type: string description: Optional initial message in the chat model: type: string description: Optional OpenAI model identifier required: - title required: true "/api/v1/chats/{id}": parameters: - name: id in: path required: true description: Chat ID schema: type: string get: summary: Retrieve a chat tags: - Chats security: - apiKeyAuth: [] responses: '200': description: chat retrieved content: application/json: schema: "$ref": "#/components/schemas/ChatDetail" '404': description: chat not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a chat tags: - Chats security: - apiKeyAuth: [] parameters: [] responses: '200': description: chat updated content: application/json: schema: "$ref": "#/components/schemas/ChatDetail" '404': description: chat not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: validation error content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: title: type: string example: Updated chat title required: true delete: summary: Delete a chat tags: - Chats security: - apiKeyAuth: [] responses: '204': description: chat deleted '404': description: chat not found "/api/v1/chats/{chat_id}/messages": parameters: - name: chat_id in: path required: true description: Chat ID schema: type: string post: summary: Create a message tags: - Chat Messages security: - apiKeyAuth: [] parameters: [] responses: '201': description: message created content: application/json: schema: "$ref": "#/components/schemas/MessageResponse" '404': description: chat not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: validation error content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: content: type: string model: type: string required: - content required: true "/api/v1/chats/{chat_id}/messages/retry": parameters: - name: chat_id in: path required: true description: Chat ID schema: type: string post: summary: Retry the last assistant response tags: - Chat Messages security: - apiKeyAuth: [] responses: '202': description: retry started content: application/json: schema: "$ref": "#/components/schemas/RetryResponse" '404': description: chat not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: no assistant message available content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/holdings": get: summary: List holdings tags: - Holdings security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: account_id in: query required: false description: Filter by account ID schema: type: string - name: account_ids in: query required: false description: Filter by multiple account IDs schema: type: array items: type: string - name: date in: query required: false description: Filter by exact date schema: type: string format: date - name: start_date in: query required: false description: Filter holdings from this date (inclusive) schema: type: string format: date - name: end_date in: query required: false description: Filter holdings until this date (inclusive) schema: type: string format: date - name: security_id in: query required: false description: Filter by security ID schema: type: string responses: '200': description: holdings paginated content: application/json: schema: "$ref": "#/components/schemas/HoldingCollection" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: invalid date filter content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/holdings/{id}": parameters: - name: id in: path required: true description: Holding ID schema: type: string get: summary: Retrieve holding tags: - Holdings security: - apiKeyAuth: [] responses: '200': description: holding retrieved content: application/json: schema: "$ref": "#/components/schemas/Holding" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: holding not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/imports": get: summary: List imports description: List all imports for the user's family with pagination and filtering. tags: - Imports security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: status in: query required: false description: Filter by status schema: type: string enum: - pending - complete - importing - reverting - revert_failed - failed - name: type in: query required: false description: Filter by import type schema: type: string enum: - TransactionImport - TradeImport - AccountImport - MintImport - CategoryImport - RuleImport - SureImport responses: '200': description: imports filtered by type content: application/json: schema: "$ref": "#/components/schemas/ImportCollection" post: summary: Create import description: Create a new import from raw CSV content, inline Sure NDJSON content, or an uploaded Sure NDJSON file. tags: - Imports security: - apiKeyAuth: [] parameters: [] responses: '201': description: import created content: application/json: schema: "$ref": "#/components/schemas/ImportResponse" '422': description: validation error - file too large content: application/json: schema: oneOf: - "$ref": "#/components/schemas/ErrorResponse" - "$ref": "#/components/schemas/ErrorResponseWithImportId" '500': description: import uploaded but publish enqueue failed content: application/json: schema: "$ref": "#/components/schemas/ErrorResponseWithImportId" requestBody: content: application/json: schema: type: object properties: raw_file_content: type: string description: Raw CSV or Sure NDJSON content as a string. Required for SureImport unless a multipart file is uploaded. type: type: string enum: - TransactionImport - TradeImport - AccountImport - MintImport - CategoryImport - RuleImport - SureImport description: Import type (defaults to TransactionImport) account_id: type: string format: uuid description: Account ID to import into publish: type: string description: Set to "true" to automatically queue for processing if configuration is valid date_col_label: type: string description: CSV imports only. Header name for the date column amount_col_label: type: string description: CSV imports only. Header name for the amount column name_col_label: type: string description: CSV imports only. Header name for the transaction name column category_col_label: type: string description: CSV imports only. Header name for the category column tags_col_label: type: string description: CSV imports only. Header name for the tags column notes_col_label: type: string description: CSV imports only. Header name for the notes column account_col_label: type: string description: CSV imports only. Header name for the account column when importing rows across multiple accounts qty_col_label: type: string description: CSV trade imports only. Header name for the quantity column ticker_col_label: type: string description: CSV trade imports only. Header name for the ticker column price_col_label: type: string description: CSV trade imports only. Header name for the price column entity_type_col_label: type: string description: CSV imports only. Header name for the entity type column currency_col_label: type: string description: CSV imports only. Header name for the currency column exchange_operating_mic_col_label: type: string description: CSV trade imports only. Header name for the exchange operating MIC column date_format: type: string description: CSV imports only. Date format pattern (e.g., "%m/%d/%Y") number_format: type: string enum: - '1,234.56' - 1.234,56 - 1 234,56 - '1,234' description: CSV imports only. Number format for parsing amounts signage_convention: type: string enum: - inflows_positive - inflows_negative description: CSV imports only. How to interpret positive/negative amounts col_sep: type: string enum: - "," - ";" description: CSV imports only. Column separator amount_type_strategy: type: string enum: - signed_amount - custom_column description: CSV imports only. Amount parsing strategy amount_type_inflow_value: type: string description: CSV imports only. Column value that marks an amount as an inflow when using custom_column strategy multipart/form-data: schema: type: object properties: raw_file_content: type: string description: Raw CSV or Sure NDJSON content as a string. Required for SureImport unless a multipart file is uploaded. type: type: string enum: - TransactionImport - TradeImport - AccountImport - MintImport - CategoryImport - RuleImport - SureImport description: Import type (defaults to TransactionImport) account_id: type: string format: uuid description: Account ID to import into publish: type: string description: Set to "true" to automatically queue for processing if configuration is valid date_col_label: type: string description: CSV imports only. Header name for the date column amount_col_label: type: string description: CSV imports only. Header name for the amount column name_col_label: type: string description: CSV imports only. Header name for the transaction name column category_col_label: type: string description: CSV imports only. Header name for the category column tags_col_label: type: string description: CSV imports only. Header name for the tags column notes_col_label: type: string description: CSV imports only. Header name for the notes column account_col_label: type: string description: CSV imports only. Header name for the account column when importing rows across multiple accounts qty_col_label: type: string description: CSV trade imports only. Header name for the quantity column ticker_col_label: type: string description: CSV trade imports only. Header name for the ticker column price_col_label: type: string description: CSV trade imports only. Header name for the price column entity_type_col_label: type: string description: CSV imports only. Header name for the entity type column currency_col_label: type: string description: CSV imports only. Header name for the currency column exchange_operating_mic_col_label: type: string description: CSV trade imports only. Header name for the exchange operating MIC column date_format: type: string description: CSV imports only. Date format pattern (e.g., "%m/%d/%Y") number_format: type: string enum: - '1,234.56' - 1.234,56 - 1 234,56 - '1,234' description: CSV imports only. Number format for parsing amounts signage_convention: type: string enum: - inflows_positive - inflows_negative description: CSV imports only. How to interpret positive/negative amounts col_sep: type: string enum: - "," - ";" description: CSV imports only. Column separator amount_type_strategy: type: string enum: - signed_amount - custom_column description: CSV imports only. Amount parsing strategy amount_type_inflow_value: type: string description: CSV imports only. Column value that marks an amount as an inflow when using custom_column strategy "/api/v1/imports/{id}": parameters: - name: id in: path required: true description: Import ID schema: type: string get: summary: Retrieve an import description: Retrieve detailed information about a specific import, including configuration and row statistics. tags: - Imports security: - apiKeyAuth: [] responses: '200': description: import retrieved content: application/json: schema: "$ref": "#/components/schemas/ImportResponse" '404': description: import not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/merchants": get: summary: List merchants tags: - Merchants security: - apiKeyAuth: [] responses: '200': description: merchants listed content: application/json: schema: type: array items: "$ref": "#/components/schemas/MerchantDetail" "/api/v1/merchants/{id}": parameters: - name: id in: path required: true description: Merchant ID schema: type: string get: summary: Retrieve a merchant tags: - Merchants security: - apiKeyAuth: [] responses: '200': description: merchant retrieved content: application/json: schema: "$ref": "#/components/schemas/MerchantDetail" '404': description: merchant not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/recurring_transactions": get: summary: List recurring transactions tags: - Recurring Transactions security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: status in: query required: false description: Filter by recurring status schema: type: string enum: - active - inactive - name: account_id in: query required: false description: Filter by account ID schema: type: string format: uuid responses: '200': description: recurring transactions listed content: application/json: schema: "$ref": "#/components/schemas/RecurringTransactionCollection" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: validation error - malformed account filter content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create recurring transaction tags: - Recurring Transactions security: - apiKeyAuth: [] parameters: [] responses: '201': description: recurring transaction created content: application/json: schema: "$ref": "#/components/schemas/RecurringTransaction" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: forbidden - requires read_write scope content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: account not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: validation error - negative occurrence count content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: recurring_transaction: type: object properties: account_id: type: string format: uuid nullable: true merchant_id: type: string format: uuid nullable: true name: type: string nullable: true amount: type: number currency: type: string expected_day_of_month: type: integer minimum: 1 maximum: 31 last_occurrence_date: type: string format: date next_expected_date: type: string format: date status: type: string enum: - active - inactive occurrence_count: type: integer minimum: 0 manual: type: boolean expected_amount_min: type: number nullable: true expected_amount_max: type: number nullable: true expected_amount_avg: type: number nullable: true required: - amount - currency - expected_day_of_month - last_occurrence_date - next_expected_date anyOf: - required: - name - required: - merchant_id required: - recurring_transaction required: true "/api/v1/recurring_transactions/{id}": parameters: - name: id in: path required: true description: Recurring transaction ID schema: type: string get: summary: Retrieve recurring transaction tags: - Recurring Transactions security: - apiKeyAuth: [] responses: '200': description: recurring transaction retrieved content: application/json: schema: "$ref": "#/components/schemas/RecurringTransaction" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: recurring transaction not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update recurring transaction tags: - Recurring Transactions security: - apiKeyAuth: [] parameters: [] responses: '200': description: recurring transaction updated content: application/json: schema: "$ref": "#/components/schemas/RecurringTransaction" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: forbidden - requires read_write scope content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: recurring transaction not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: validation error content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: recurring_transaction: type: object properties: status: type: string enum: - active - inactive expected_day_of_month: type: integer minimum: 1 maximum: 31 next_expected_date: type: string format: date required: true delete: summary: Delete recurring transaction tags: - Recurring Transactions security: - apiKeyAuth: [] responses: '200': description: recurring transaction deleted content: application/json: schema: "$ref": "#/components/schemas/SuccessMessage" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: forbidden - requires read_write scope content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: recurring transaction not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/rules": get: summary: List rules tags: - Rules security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: resource_type in: query required: false description: Filter by rule resource type schema: type: string enum: - transaction - name: active in: query required: false description: Filter by active status schema: type: boolean responses: '200': description: rules listed content: application/json: schema: "$ref": "#/components/schemas/RuleCollection" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: forbidden - requires read scope content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: unsupported resource type content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/rules/{id}": parameters: - name: id in: path required: true description: Rule ID schema: type: string get: summary: Retrieve a rule tags: - Rules security: - apiKeyAuth: [] responses: '200': description: rule retrieved content: application/json: schema: "$ref": "#/components/schemas/RuleResponse" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '403': description: forbidden - requires read scope content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: rule not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/tags": get: summary: List tags tags: - Tags security: - apiKeyAuth: [] responses: '200': description: tags listed content: application/json: schema: "$ref": "#/components/schemas/TagCollection" post: summary: Create tag tags: - Tags security: - apiKeyAuth: [] parameters: [] responses: '201': description: tag created with auto-assigned color content: application/json: schema: "$ref": "#/components/schemas/TagDetail" '422': description: validation error - missing name content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: tag: type: object properties: name: type: string description: Tag name (required) color: type: string description: Hex color code (optional, auto-assigned if not provided) required: - name required: - tag required: true "/api/v1/tags/{id}": parameters: - name: id in: path required: true description: Tag ID schema: type: string get: summary: Retrieve a tag tags: - Tags security: - apiKeyAuth: [] responses: '200': description: tag retrieved content: application/json: schema: "$ref": "#/components/schemas/TagDetail" '404': description: tag not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a tag tags: - Tags security: - apiKeyAuth: [] parameters: [] responses: '200': description: tag updated content: application/json: schema: "$ref": "#/components/schemas/TagDetail" '404': description: tag not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: tag: type: object properties: name: type: string color: type: string required: true delete: summary: Delete a tag tags: - Tags security: - apiKeyAuth: [] responses: '204': description: tag deleted '404': description: tag not found "/api/v1/trades": get: summary: List trades tags: - Trades security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: account_id in: query required: false description: Filter by account ID schema: type: string - name: account_ids in: query required: false description: Filter by multiple account IDs schema: type: array items: type: string - name: start_date in: query required: false description: Filter trades from this date (inclusive) schema: type: string format: date - name: end_date in: query required: false description: Filter trades until this date (inclusive) schema: type: string format: date responses: '200': description: trades paginated content: application/json: schema: "$ref": "#/components/schemas/TradeCollection" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: invalid date filter content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create trade tags: - Trades security: - apiKeyAuth: [] parameters: [] responses: '201': description: trade created content: application/json: schema: "$ref": "#/components/schemas/Trade" '422': description: validation error - missing security identifier content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: account not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: trade: type: object properties: account_id: type: string format: uuid description: Account ID (required) date: type: string format: date description: Trade date (required) qty: type: number description: Quantity (required) price: type: number description: Price (required) type: type: string enum: - buy - sell description: Trade type (required) security_id: type: string format: uuid description: Security ID (one of security_id, ticker, manual_ticker required) ticker: type: string description: Ticker symbol manual_ticker: type: string description: Manual ticker for offline securities currency: type: string description: Currency (defaults to account currency) investment_activity_label: type: string description: Activity label (e.g. Buy, Sell) category_id: type: string format: uuid description: Category ID required: - account_id - date - qty - price - type required: - trade required: true "/api/v1/trades/{id}": parameters: - name: id in: path required: true description: Trade ID schema: type: string get: summary: Retrieve trade tags: - Trades security: - apiKeyAuth: [] responses: '200': description: trade retrieved content: application/json: schema: "$ref": "#/components/schemas/Trade" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: trade not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update trade tags: - Trades security: - apiKeyAuth: [] parameters: [] responses: '200': description: trade updated content: application/json: schema: "$ref": "#/components/schemas/Trade" '404': description: trade not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: trade: type: object properties: date: type: string format: date qty: type: number price: type: number type: type: string enum: - buy - sell nature: type: string enum: - inflow - outflow name: type: string notes: type: string currency: type: string investment_activity_label: type: string category_id: type: string format: uuid required: true delete: summary: Delete trade tags: - Trades security: - apiKeyAuth: [] responses: '200': description: trade deleted content: application/json: schema: "$ref": "#/components/schemas/DeleteResponse" '404': description: trade not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/transactions": get: summary: List transactions tags: - Transactions security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: account_id in: query required: false description: Filter by account ID schema: type: string - name: category_id in: query required: false description: Filter by category ID schema: type: string - name: merchant_id in: query required: false description: Filter by merchant ID schema: type: string - name: start_date in: query required: false description: Filter transactions from this date schema: type: string format: date - name: end_date in: query required: false description: Filter transactions until this date schema: type: string format: date - name: min_amount in: query required: false description: Filter by minimum amount schema: type: number - name: max_amount in: query required: false description: Filter by maximum amount schema: type: number - name: type in: query required: false description: Filter by transaction type schema: type: string enum: - income - expense - name: search in: query required: false description: Search by name, notes, or merchant name schema: type: string - name: account_ids in: query required: false description: Filter by multiple account IDs schema: type: array items: type: string - name: category_ids in: query required: false description: Filter by multiple category IDs schema: type: array items: type: string - name: merchant_ids in: query required: false description: Filter by multiple merchant IDs schema: type: array items: type: string - name: tag_ids in: query required: false description: Filter by tag IDs schema: type: array items: type: string responses: '200': description: transactions filtered by date range content: application/json: schema: "$ref": "#/components/schemas/TransactionCollection" post: summary: Create transaction tags: - Transactions security: - apiKeyAuth: [] parameters: [] responses: '201': description: transaction created content: application/json: schema: "$ref": "#/components/schemas/Transaction" '422': description: validation error - missing required fields content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: transaction: type: object properties: account_id: type: string format: uuid description: Account ID (required) date: type: string format: date description: Transaction date amount: type: number description: Transaction amount name: type: string description: Transaction name/description description: type: string description: Alternative to name field notes: type: string description: Additional notes currency: type: string description: Currency code (defaults to family currency) category_id: type: string format: uuid description: Category ID merchant_id: type: string format: uuid description: Merchant ID nature: type: string enum: - income - expense - inflow - outflow description: Transaction nature (determines sign) tag_ids: type: array items: type: string format: uuid description: Array of tag IDs required: - account_id - date - amount - name required: - transaction required: true "/api/v1/transactions/{id}": parameters: - name: id in: path required: true description: Transaction ID schema: type: string get: summary: Retrieve a transaction tags: - Transactions security: - apiKeyAuth: [] responses: '200': description: transaction retrieved content: application/json: schema: "$ref": "#/components/schemas/Transaction" '404': description: transaction not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a transaction tags: - Transactions security: - apiKeyAuth: [] parameters: [] responses: '200': description: transaction updated content: application/json: schema: "$ref": "#/components/schemas/Transaction" '404': description: transaction not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: transaction: type: object properties: date: type: string format: date amount: type: number name: type: string description: type: string description: Alternative to name field notes: type: string currency: type: string description: Currency code category_id: type: string format: uuid merchant_id: type: string format: uuid nature: type: string enum: - income - expense - inflow - outflow tag_ids: type: array items: type: string format: uuid description: Array of tag IDs to assign. Omit to preserve existing tags; use [] to clear all tags. required: true delete: summary: Delete a transaction tags: - Transactions security: - apiKeyAuth: [] responses: '200': description: transaction deleted content: application/json: schema: "$ref": "#/components/schemas/DeleteResponse" '404': description: transaction not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/users/reset": delete: summary: Reset account tags: - Users description: Resets all financial data (accounts, categories, merchants, tags, etc.) for the current user's family while keeping the user account intact. The reset runs asynchronously in the background. Requires admin role. security: - apiKeyAuth: [] responses: '200': description: account reset initiated content: application/json: schema: "$ref": "#/components/schemas/SuccessMessage" '401': description: unauthorized '403': description: forbidden - requires read_write scope and admin role "/api/v1/users/me": delete: summary: Delete account tags: - Users description: Permanently deactivates the current user account and all associated data. This action cannot be undone. security: - apiKeyAuth: [] responses: '200': description: account deleted content: application/json: schema: "$ref": "#/components/schemas/SuccessMessage" '401': description: unauthorized '403': description: insufficient scope '422': description: deactivation failed content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v1/valuations": get: summary: List valuations tags: - Valuations security: - apiKeyAuth: [] parameters: - name: page in: query required: false description: 'Page number (default: 1)' schema: type: integer - name: per_page in: query required: false description: 'Items per page (default: 25, max: 100)' schema: type: integer - name: account_id in: query required: false description: Filter by account ID schema: type: string format: uuid - name: start_date in: query required: false description: Filter valuations from this date schema: type: string format: date - name: end_date in: query required: false description: Filter valuations until this date schema: type: string format: date responses: '200': description: valuations listed content: application/json: schema: "$ref": "#/components/schemas/ValuationCollection" '401': description: unauthorized content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '422': description: invalid account filter content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create valuation tags: - Valuations security: - apiKeyAuth: [] parameters: [] responses: '201': description: valuation created content: application/json: schema: "$ref": "#/components/schemas/Valuation" '422': description: validation error - missing date content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: account not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: valuation: type: object properties: account_id: type: string format: uuid description: Account ID (required) amount: type: number description: Valuation amount (required) date: type: string format: date description: Valuation date (required) notes: type: string description: Additional notes required: - account_id - amount - date required: - valuation required: true "/api/v1/valuations/{id}": parameters: - name: id in: path required: true description: Valuation ID (entry ID) schema: type: string get: summary: Retrieve a valuation tags: - Valuations security: - apiKeyAuth: [] responses: '200': description: valuation retrieved content: application/json: schema: "$ref": "#/components/schemas/Valuation" '404': description: valuation not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a valuation tags: - Valuations security: - apiKeyAuth: [] parameters: [] responses: '200': description: valuation updated with amount and date content: application/json: schema: "$ref": "#/components/schemas/Valuation" '422': description: validation error - only one of amount/date provided content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" '404': description: valuation not found content: application/json: schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: valuation: type: object properties: amount: type: number description: New valuation amount (must provide with date) date: type: string format: date description: New valuation date (must provide with amount) notes: type: string description: Additional notes required: true