{"openapi":"3.1.0","info":{"title":"Penny API","version":"1.0.0","description":"The API for Penny, a personal finance app for managing household finances. Connect financial accounts, track transactions and balances, organize spending, and manage recurring transactions."},"paths":{"/v1/users/me":{"get":{"operationId":"get_current_user","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserWithHouseholdsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}}},"summary":"Get Current User","description":"Retrieves the user associated with the API token, including their profile, household memberships, selected household, and subscription summary.\n\nUse the household IDs in this response for household-scoped requests. Each household's `role` and `access_status` describe the caller's access to that household.","tags":["users"],"security":[{"PersonalApiToken":[]}]},"patch":{"operationId":"update_current_user","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadOnlyToken"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Current User","description":"Updates the authenticated user's display name and returns the updated profile.\n\nSend only the fields you want to change. Omitted fields retain their current values.","tags":["users"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserRequestPatch"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/users/me/image":{"put":{"operationId":"upload_user_image","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageUploadResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageInvalidFileType"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadOnlyToken"}}}},"413":{"description":"Content Too Large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageFileTooLarge"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Upload User Image","description":"Uploads or replaces the authenticated user's profile image and returns its display URL.\n\nSend the image as the `file` field in a `multipart/form-data` request. Accepts JPEG, PNG, or WebP up to 5 MiB (5,242,880 bytes) and 25 million decoded pixels, including all animation frames.","tags":["users"],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"format":"binary","title":"File","type":"string"}},"required":["file"],"title":"FileParams","type":"object"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_user_image","parameters":[],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadOnlyToken"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageNoImage"}}}}},"summary":"Delete User Image","description":"Removes the authenticated user's uploaded profile image. Subsequent profile responses return `image_url: null`.\n\nReturns `204` with no response body on success, or `no_image` if the user has no uploaded image.","tags":["users"],"security":[{"PersonalApiToken":[]}]}},"/v1/households":{"get":{"operationId":"list_households","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}}},"summary":"List Households","description":"Lists every household the authenticated user belongs to, including its currency, timezone, preferences, and the user's role.\n\nUse `access_status` to determine whether a household is available before requesting its financial data. The response includes the complete list without pagination.","tags":["households"],"security":[{"PersonalApiToken":[]}]},"post":{"operationId":"create_household","parameters":[],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadOnlyToken"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Household","description":"Creates a household with the supplied name, reporting currency, and timezone, and makes the authenticated user its owner.\n\nThe household is initialized with default categories, preferences, and a manual cash account. Returns the created household, including its ID for subsequent requests and its current access status.","tags":["households"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateHouseholdRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}":{"patch":{"operationId":"update_household","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Household","description":"Updates a household's name, reporting currency, or timezone and returns the updated household. Only the household owner can make this change.\n\nSend only the fields you want to change. Changing the reporting currency affects converted totals; financial accounts retain their native currencies. The timezone determines household-local dates used in reports and recurring transactions.","tags":["households"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateHouseholdRequestPatch"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_household","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}}},"summary":"Delete Household","description":"Permanently deletes the household and its associated financial data for every member. Only the household owner can delete it, including when subscription access has lapsed.\n\nThis operation cannot be undone. Request and download a data export first if you need to retain a copy. Returns `204` with no response body.","tags":["households"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/members":{"get":{"operationId":"get_household_members","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdMembersResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"Get Household Members","description":"Lists the household's current members and pending invitations. Member records include their role and join date; invitation records include the invited role and expiration time.\n\nAvailable to all household roles, including viewers, even when subscription access has lapsed.","tags":["households"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/image":{"put":{"operationId":"upload_household_image","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageUploadResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageInvalidFileType"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"413":{"description":"Content Too Large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageFileTooLarge"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Upload Household Image","description":"Uploads or replaces the household's image and returns its display URL. Only the household owner can change this image.\n\nSend a JPEG, PNG, or WebP image in the `file` field of a `multipart/form-data` request. The limit is 5 MiB (5,242,880 bytes) and 25 million decoded pixels, including all animation frames.","tags":["households"],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"format":"binary","title":"File","type":"string"}},"required":["file"],"title":"FileParams","type":"object"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_household_image","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageNoImage"}}}}},"summary":"Delete Household Image","description":"Removes the household's uploaded image. Only the household owner can make this change; subsequent household responses return `image_url: null`.\n\nReturns `204` with no response body on success, or `no_image` if no image has been uploaded.","tags":["households"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/preferences":{"get":{"operationId":"get_preferences","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdPreferences"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"Get Preferences","description":"Retrieves the household's shared display preferences, including whether recurring suggestions and advanced details are shown.\n\nThese settings apply to the household rather than an individual member. Viewers can read them.","tags":["households"],"security":[{"PersonalApiToken":[]}]},"patch":{"operationId":"update_preferences","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdPreferences"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Preferences","description":"Updates the household's shared display preferences and returns the resulting settings. Requires a member or owner role.\n\nSend only the preferences you want to change; omitted values are preserved. Changes apply to all members of the household.","tags":["households"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdPreferencesPatch"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/merchants":{"post":{"operationId":"create_merchant","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateName"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Merchant","description":"Creates a merchant in the household for use on transactions and recurring series. Returns the merchant with its resolved image URL and usage counts.\n\nThe name must be unique among the household's active merchants. Supply `website` when available to help identify the merchant.","tags":["merchants"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"get":{"operationId":"list_merchants","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"List Merchants","description":"Lists all active merchants in the household, including their display images and counts of visible transactions and recurring series.\n\nThe response is not paginated. Deleted merchants are excluded; merchants with no transactions are still returned.","tags":["merchants"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/merchants/{merchant_id}":{"get":{"operationId":"get_merchant","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"merchant_id","schema":{"title":"Merchant Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantNotFound"}}}}},"summary":"Get Merchant","description":"Retrieves an active household merchant with its website, resolved image URL, and transaction and recurring-series counts.\n\nReturns `merchant_not_found` if the merchant is deleted or does not belong to this household.","tags":["merchants"],"security":[{"PersonalApiToken":[]}]},"put":{"operationId":"update_merchant","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"merchant_id","schema":{"title":"Merchant Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantNotFound"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateName"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Merchant","description":"Replaces a merchant's name and website and returns the updated merchant. Changes are reflected wherever that merchant is displayed in the household.\n\nSupply both fields. Use `website: null` to clear the website. The name must remain unique among active household merchants.","tags":["merchants"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_merchant","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"merchant_id","schema":{"title":"Merchant Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantNotFound"}}}}},"summary":"Delete Merchant","description":"Deletes a merchant and clears its assignment from all associated transactions, including transactions on deleted accounts. The transactions themselves are retained.\n\nAlso permanently removes the merchant's recurring series and dismissed recurring suggestions, and cleans up rules that reference it. Rules left without criteria or actions are deleted. Returns `204` with no response body.","tags":["merchants"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/merchants/{merchant_id}/image":{"put":{"operationId":"upload_merchant_image","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"merchant_id","schema":{"title":"Merchant Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageUploadResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageInvalidFileType"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantNotFound"}}}},"413":{"description":"Content Too Large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageFileTooLarge"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Upload Merchant Image","description":"Uploads or replaces a merchant's custom image and returns its display URL. The custom image takes precedence over any default merchant image.\n\nSend a JPEG, PNG, or WebP image as the multipart `file` field, up to 5 MiB (5,242,880 bytes) and 25 million decoded pixels across all frames.","tags":["merchants"],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"format":"binary","title":"File","type":"string"}},"required":["file"],"title":"FileParams","type":"object"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_merchant_image","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"merchant_id","schema":{"title":"Merchant Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/MerchantNotFound"},{"$ref":"#/components/schemas/ImageNoImage"}],"discriminator":{"propertyName":"code","mapping":{"merchant_not_found":"#/components/schemas/MerchantNotFound","no_image":"#/components/schemas/ImageNoImage"}}}}}}},"summary":"Delete Merchant Image","description":"Removes a merchant's custom image so `image_url` falls back to `default_image_url`, which may be null.\n\nReturns `204` with no response body on success, or `no_image` if the merchant has no custom upload. A default image alone cannot be removed through this endpoint.","tags":["merchants"],"security":[{"PersonalApiToken":[]}]}},"/v1/institutions/connection-status":{"get":{"operationId":"list_connection_status","parameters":[{"in":"query","name":"search","schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"},"required":false},{"in":"query","name":"limit","schema":{"default":20,"maximum":100,"minimum":1,"title":"Limit","type":"integer"},"required":false},{"in":"query","name":"offset","schema":{"default":0,"minimum":0,"title":"Offset","type":"integer"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedConnectionStatusResponse"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"List Connection Status","description":"Lists connection health for Plaid institutions and Apple Card, Cash, and Savings. Starts with a Penny-curated mix of 30 popular Plaid institutions and Apple products, followed by other institutions ordered by name. The popularity_rank field preserves the source ranking separately from this presentation order. Search and offset pagination apply to the combined directory. Login success is a daily Plaid production snapshot with a check timestamp; missing data and snapshots older than 26 hours return null. Apple login success is fixed at 100 percent with no check timestamp. Notices contain open Plaid health incidents from a fresh snapshot; ended or resolved incidents are excluded. has_success_data indicates availability across all matching results, not just this page. Authentication is not required.","tags":["institutions"]}},"/v1/institutions":{"get":{"operationId":"list_institutions","parameters":[{"in":"query","name":"search","schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"},"required":false},{"in":"query","name":"limit","schema":{"default":20,"maximum":100,"minimum":1,"title":"Limit","type":"integer"},"required":false},{"in":"query","name":"offset","schema":{"default":0,"minimum":0,"title":"Offset","type":"integer"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedInstitutionsResponse"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"List Institutions","description":"Searches the financial institution directory by name. Authentication is not required.\n\nResults use offset pagination: `limit` defaults to 20 and accepts 1–100; advance `offset` by the number of results received while `has_more` is true. Apple appears first when it matches the search, followed by stored institutions ordered by name. Each result includes provider metadata and a resolved image URL.","tags":["institutions"]}},"/v1/institutions/curated":{"get":{"operationId":"list_curated_institutions","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CuratedInstitutionsResponse"}}}}},"summary":"List Curated Institutions","description":"Lists the featured financial institutions in their display order, with Apple first. Authentication is not required.\n\nUse this short, unpaginated list for a featured-institution picker. Use the institution search endpoint to browse the full directory.","tags":["institutions"]}},"/v1/households/{household_id}/accounts":{"get":{"operationId":"get_accounts","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupedAccountsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"Get Accounts","description":"Lists the household's non-deleted financial accounts grouped by account type. Account balances retain their native currencies; group and household totals use the household's reporting currency.\n\nClosed accounts remain in the response and contribute zero to displayed balances. Use the deleted-accounts endpoint to find accounts available for restoration.","tags":["accounts"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/accounts/deleted":{"get":{"operationId":"list_deleted_accounts","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedAccountsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"List Deleted Accounts","description":"Lists the household's deleted accounts, most recently deleted first, with their retained balance and transaction metadata.\n\nUse an account's ID with the restore endpoint to make it available again. This response is not paginated.","tags":["accounts"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/accounts/{account_id}":{"put":{"operationId":"update_account","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"account_id","schema":{"title":"Account Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinancialAccountResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Account","description":"Updates the display-name override for a financial account and returns the updated account.\n\nSet `user_name` to null to remove the override and use the account's default display name. The account must belong to the household and must not be deleted.","tags":["accounts"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAccountRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_account","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"account_id","schema":{"title":"Account Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotFound"}}}}},"summary":"Delete Account","description":"Soft-deletes an account, removing it and its transactions from normal household views and reports. The account can be restored while its records are retained.\n\nIf every account on a Plaid connection has been deleted for at least seven days, the connection and its accounts, transactions, and balance history can be permanently removed. Restore before then to keep the account. This cleanup does not apply to Apple or manual accounts, or to Plaid connections with an undeleted account.\n\nAlso removes the account from rule conditions and deletes rules that are left without criteria. Restoring the account does not recreate those rule conditions. Returns `204` with no response body.","tags":["accounts"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/accounts/{account_id}/close":{"post":{"operationId":"close_account","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"account_id","schema":{"title":"Account Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Close Account","description":"Marks an account as closed on `closed_at` while retaining its transaction history. The account remains in the account list, with a displayed balance of zero.\n\nHistorical balances are treated as zero from the closure date onward. This records the account's status in Penny; it does not close the account at the financial institution. Use the reopen endpoint to clear the closure date.","tags":["accounts"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloseAccountRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/accounts/{account_id}/reopen":{"post":{"operationId":"reopen_account","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"account_id","schema":{"title":"Account Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotFound"}}}}},"summary":"Reopen Account","description":"Clears an account's closure date so Penny displays its recorded balance again and stops zeroing its balance history from that date.\n\nThe account must not be deleted. Reopening an already open account succeeds. Returns `204` with no response body.","tags":["accounts"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/accounts/{account_id}/restore":{"post":{"operationId":"restore_account","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"account_id","schema":{"title":"Account Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotFound"}}}}},"summary":"Restore Account","description":"Restores a deleted account and makes its retained transactions eligible for household views and reports again. Accounts permanently removed after an unused Plaid connection's seven-day recovery window cannot be restored.\n\nIndividual transaction deletion and hiding flags are preserved, as is the account's closure status. Returns `account_not_found` if the account is not found or is not currently deleted, or `204` on success.","tags":["accounts"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/accounts/{account_id}/image":{"put":{"operationId":"upload_account_image","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"account_id","schema":{"title":"Account Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageUploadResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageInvalidFileType"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotFound"}}}},"413":{"description":"Content Too Large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageFileTooLarge"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Upload Account Image","description":"Uploads or replaces a financial account's custom image and returns its display URL. This image overrides the account's default institution or provider image.\n\nSend a JPEG, PNG, or WebP image as the multipart `file` field, up to 5 MiB (5,242,880 bytes) and 25 million decoded pixels across all frames. Deleted accounts cannot be updated.","tags":["accounts"],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"file":{"format":"binary","title":"File","type":"string"}},"required":["file"],"title":"FileParams","type":"object"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_account_image","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"account_id","schema":{"title":"Account Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/AccountNotFound"},{"$ref":"#/components/schemas/ImageNoImage"}],"discriminator":{"propertyName":"code","mapping":{"account_not_found":"#/components/schemas/AccountNotFound","no_image":"#/components/schemas/ImageNoImage"}}}}}}},"summary":"Delete Account Image","description":"Removes an account's custom image so its display image falls back to `default_image_url`, which may be null.\n\nReturns `204` with no response body on success, or `no_image` when the account has no custom upload. The account must not be deleted.","tags":["accounts"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/historical-balances":{"get":{"operationId":"list_historical_balances","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Start Date"},"required":false},{"in":"query","name":"end_date","schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"End Date"},"required":false},{"in":"query","name":"account_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoricalBalancesResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"List Historical Balances","description":"Retrieves daily balance history for the household, optionally restricted to specific accounts and an inclusive date range. Daily totals use the household's reporting currency; per-account balances retain their native currencies.\n\nMissing daily values carry forward the last known balance and are marked `is_interpolated`. Closed accounts contribute zero from their closure date, and deleted accounts are excluded. Without date bounds, history runs from the first recorded balance through today in the household's timezone. A supplied end date is capped at tomorrow. The response also includes first-balance and account-closure events.","tags":["historical-balances"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/tags":{"post":{"operationId":"create_tag","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateName"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Tag","description":"Creates a household tag that can be attached to transactions alongside their category. Returns the new tag with a transaction count of zero.\n\nThe name must be unique among active household tags. Supply a color or use null for no custom color.","tags":["tags"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"get":{"operationId":"list_tags","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"List Tags","description":"Lists all active household tags with their colors and visible transaction counts.\n\nThe response is not paginated and includes unused tags. Deleted tags are excluded.","tags":["tags"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/tags/{tag_id}":{"get":{"operationId":"get_tag","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"tag_id","schema":{"title":"Tag Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagNotFound"}}}}},"summary":"Get Tag","description":"Retrieves an active household tag, including its color and visible transaction count.\n\nReturns `tag_not_found` if the tag is deleted or does not belong to this household.","tags":["tags"],"security":[{"PersonalApiToken":[]}]},"put":{"operationId":"update_tag","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"tag_id","schema":{"title":"Tag Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagNotFound"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateName"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Tag","description":"Replaces a tag's name and color and returns the updated tag. Existing transaction assignments are retained.\n\nSupply both fields, using `color: null` to clear the custom color. The name must remain unique among active household tags.","tags":["tags"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_tag","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"tag_id","schema":{"title":"Tag Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagNotFound"}}}}},"summary":"Delete Tag","description":"Deletes a tag and removes it from every associated transaction, including transactions on deleted accounts. The transactions themselves are retained.\n\nAlso removes the tag from rule actions and deletes rules left without actions. Returns `204` with no response body.","tags":["tags"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/rules":{"post":{"operationId":"create_rule","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/AccountNotFound"},{"$ref":"#/components/schemas/CategoryNotFound"},{"$ref":"#/components/schemas/MerchantNotFound"},{"$ref":"#/components/schemas/TagNotFound"},{"$ref":"#/components/schemas/RuleNotFound"}],"discriminator":{"propertyName":"code","mapping":{"account_not_found":"#/components/schemas/AccountNotFound","category_not_found":"#/components/schemas/CategoryNotFound","merchant_not_found":"#/components/schemas/MerchantNotFound","tag_not_found":"#/components/schemas/TagNotFound","rule_not_found":"#/components/schemas/RuleNotFound"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Rule","description":"Creates a transaction rule at the highest priority in the household. Define matching conditions and actions such as assigning a category or merchant, adding tags, or hiding transactions.\n\nSet `apply_to_existing: true` to apply the new rule to existing visible transactions and return `applied_count`; otherwise, existing transactions are unchanged. Explicitly locked category and merchant choices are preserved, and tag actions are additive. Referenced accounts, categories, merchants, and tags must belong to the household.","tags":["rules"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"get":{"operationId":"list_rules","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"List Rules","description":"Lists the household's active transaction rules in priority order, highest priority first, with their conditions and actions.\n\nUse this order when presenting rules for editing or sending the complete list to the reorder endpoint. The response is not paginated.","tags":["rules"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/rules/reorder":{"post":{"operationId":"reorder_rules","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/InvalidRuleIds"},{"$ref":"#/components/schemas/HttpErrorResponse"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Reorder Rules","description":"Replaces the household's rule priority order and returns the rules in their new order. The first ID has the highest priority.\n\nSubmit every active rule ID exactly once. Missing, duplicate, or foreign IDs return `invalid_rule_ids`. Reordering does not reapply rules to existing transactions.","tags":["rules"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderRulesRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/rules/dry-run":{"post":{"operationId":"dry_run","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DryRunResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"anyOf":[{"title":"Response","oneOf":[{"$ref":"#/components/schemas/FiltersChanged"},{"$ref":"#/components/schemas/InvalidCursor"}],"discriminator":{"propertyName":"code","mapping":{"filters_changed":"#/components/schemas/FiltersChanged","invalid_cursor":"#/components/schemas/InvalidCursor"}}},{"$ref":"#/components/schemas/HttpErrorResponse"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Dry Run","description":"Previews which visible transactions match a proposed rule's conditions without saving a rule or changing transactions. Returns overall match and transaction counts, a page of matches, and daily totals.\n\nPass `next_cursor` as `cursor` to continue with the same conditions; changing conditions requires starting without a cursor. Pages keep complete days together, so the number of matches can exceed `min_limit`. This POST endpoint requires a read/write token and a household member or owner role even though it only previews matches.","tags":["rules"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DryRunRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/rules/{rule_id}":{"get":{"operationId":"get_rule","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"rule_id","schema":{"title":"Rule Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleNotFound"}}}}},"summary":"Get Rule","description":"Retrieves an active household rule with its priority, matching conditions, and actions.\n\nReturns `rule_not_found` if the rule is deleted or does not belong to this household. Reading a rule does not evaluate or apply it.","tags":["rules"],"security":[{"PersonalApiToken":[]}]},"put":{"operationId":"update_rule","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"rule_id","schema":{"title":"Rule Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/AccountNotFound"},{"$ref":"#/components/schemas/CategoryNotFound"},{"$ref":"#/components/schemas/MerchantNotFound"},{"$ref":"#/components/schemas/TagNotFound"},{"$ref":"#/components/schemas/RuleNotFound"}],"discriminator":{"propertyName":"code","mapping":{"account_not_found":"#/components/schemas/AccountNotFound","category_not_found":"#/components/schemas/CategoryNotFound","merchant_not_found":"#/components/schemas/MerchantNotFound","tag_not_found":"#/components/schemas/TagNotFound","rule_not_found":"#/components/schemas/RuleNotFound"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Rule","description":"Replaces all matching conditions and actions of an existing rule while preserving its position in the priority order. Omitted fields reset to their schema defaults.\n\nSet `apply_to_existing: true` to apply the updated rule to existing visible transactions and return `applied_count`. Category and merchant choices protected by field locks are preserved, and tag actions add to existing tags. Use the dry-run endpoint to preview matching transactions before updating.","tags":["rules"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_rule","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"rule_id","schema":{"title":"Rule Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleNotFound"}}}}},"summary":"Delete Rule","description":"Deletes a household rule so it is no longer applied to transactions.\n\nChanges previously made by the rule, including assigned categories and tags, are retained. Returns `204` with no response body, or `rule_not_found` if the rule is already deleted or unavailable in this household.","tags":["rules"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/analytics/accumulated-spending":{"get":{"operationId":"get_accumulated_spending","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"format":"date","title":"Start Date","type":"string"},"required":true},{"in":"query","name":"end_date","schema":{"format":"date","title":"End Date","type":"string"},"required":true},{"in":"query","name":"merchant_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Merchant Ids"},"required":false},{"in":"query","name":"tag_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Ids"},"required":false},{"in":"query","name":"category_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Ids"},"required":false},{"in":"query","name":"category_group_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Group Ids"},"required":false},{"in":"query","name":"account_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"required":false},{"in":"query","name":"uncategorized","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Uncategorized"},"required":false},{"in":"query","name":"unknown_merchant","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Unknown Merchant"},"required":false},{"in":"query","name":"need_review","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Need Review"},"required":false},{"in":"query","name":"min_amount","schema":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison.","title":"Min Amount"},"required":false,"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison."},{"in":"query","name":"max_amount","schema":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison.","title":"Max Amount"},"required":false,"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccumulatedSpendingResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Accumulated Spending","description":"Summarizes income and expenses over an inclusive date range, with transaction counts and category breakdowns. Amounts and amount filters use the household's reporting currency.\n\nHidden and deleted transactions, transactions on deleted accounts, split parents, and transfers are excluded; pending transactions are included. Totals are netted within each category, with positive category totals reported as income and negative totals as expenses.","tags":["spending"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/analytics/spending-by-period":{"get":{"operationId":"get_spending_by_period","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"format":"date","title":"Start Date","type":"string"},"required":true},{"in":"query","name":"end_date","schema":{"format":"date","title":"End Date","type":"string"},"required":true},{"in":"query","name":"merchant_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Merchant Ids"},"required":false},{"in":"query","name":"tag_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Ids"},"required":false},{"in":"query","name":"category_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Ids"},"required":false},{"in":"query","name":"category_group_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Group Ids"},"required":false},{"in":"query","name":"account_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"required":false},{"in":"query","name":"uncategorized","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Uncategorized"},"required":false},{"in":"query","name":"unknown_merchant","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Unknown Merchant"},"required":false},{"in":"query","name":"need_review","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Need Review"},"required":false},{"in":"query","name":"min_amount","schema":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison.","title":"Min Amount"},"required":false,"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison."},{"in":"query","name":"max_amount","schema":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison.","title":"Max Amount"},"required":false,"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison."},{"in":"query","name":"time_segment","schema":{"enum":["daily","monthly","quarterly","yearly"],"title":"TimeSegment","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SpendingByPeriodResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Spending By Period","description":"Groups income and expenses into daily, monthly, quarterly, or yearly periods over an inclusive date range. Each period includes totals, counts, and category breakdowns in the household's reporting currency; periods with no activity are returned with zero totals.\n\nCategory totals determine the income or expense side and retain their signs. Hidden and deleted transactions, transactions on deleted accounts, split parents, and transfers are excluded; pending transactions are included. Only transactions within the requested dates contribute, even for partial calendar periods.","tags":["spending"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/analytics/cashflow-by-period":{"get":{"operationId":"get_cashflow_by_period","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"format":"date","title":"Start Date","type":"string"},"required":true},{"in":"query","name":"end_date","schema":{"format":"date","title":"End Date","type":"string"},"required":true},{"in":"query","name":"time_segment","schema":{"enum":["daily","monthly","quarterly","yearly"],"title":"TimeSegment","type":"string"},"required":true},{"in":"query","name":"account_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"required":false},{"in":"query","name":"tag_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Ids"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashflowByPeriodResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Cashflow By Period","description":"Returns income, expenses, and net cashflow for each calendar period intersecting an inclusive date range, optionally filtered by accounts or tags. Amounts use the household's reporting currency: income is positive, expenses are negative, and net is their sum.\n\nEmpty periods have zero totals. Period boundaries cover the full calendar period, but totals include only the requested dates. `is_complete` indicates whether the period has ended in the household's timezone. Hidden and deleted transactions, transactions on deleted accounts, split parents, and transfers are excluded; pending transactions are included.","tags":["spending"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/analytics/merchant-breakdown":{"get":{"operationId":"get_merchant_breakdown","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"format":"date","title":"Start Date","type":"string"},"required":true},{"in":"query","name":"end_date","schema":{"format":"date","title":"End Date","type":"string"},"required":true},{"in":"query","name":"tag_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Ids"},"required":false},{"in":"query","name":"account_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"required":false},{"in":"query","name":"category_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Ids"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantBreakdownResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Merchant Breakdown","description":"Aggregates transactions by merchant over an inclusive date range and returns signed totals in the household's reporting currency with transaction counts. Results are ordered by the absolute value of the total, largest first; unknown merchants appear with null merchant fields.\n\nFilter by accounts, tags, or categories. Hidden and deleted transactions, transactions on deleted accounts, split parents, and transfers are excluded; pending transactions are included.","tags":["spending"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/analytics/category-breakdown":{"get":{"operationId":"get_category_breakdown","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"format":"date","title":"Start Date","type":"string"},"required":true},{"in":"query","name":"end_date","schema":{"format":"date","title":"End Date","type":"string"},"required":true},{"in":"query","name":"tag_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Ids"},"required":false},{"in":"query","name":"account_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FullCategoryBreakdownResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Category Breakdown","description":"Breaks down income and expenses by category group and category over an inclusive date range, with totals and percentage shares. Ungrouped categories and uncategorized transactions are included separately from named groups.\n\nAmounts use the household's reporting currency, with expense amounts presented as positive magnitudes. Filter by accounts or tags. Hidden and deleted transactions, transactions on deleted accounts, split parents, and transfers are excluded; pending transactions are included.","tags":["spending"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/categories":{"post":{"operationId":"create_category","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryGroupNotFound"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/DuplicateName"},{"$ref":"#/components/schemas/CategoryDuplicateEmoji"}],"discriminator":{"propertyName":"code","mapping":{"duplicate_name":"#/components/schemas/DuplicateName","duplicate_emoji":"#/components/schemas/CategoryDuplicateEmoji"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Category","description":"Creates a household category for classifying transactions as income, expense, or transfer.\n\nThe name and emoji must each be unique among active household categories. Supply `group_id` to place the category in a group, whose type determines the category's effective type; use null for an ungrouped category. Returns the created category.","tags":["categories"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertCategoryRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"get":{"operationId":"list_categories","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoriesListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"List Categories","description":"Lists the household's active categories and all category groups in a single response.\n\nMatch each category's group ID to the returned groups to build a grouped category picker. Ungrouped categories have a null group ID. The response is not paginated.","tags":["categories"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/categories/{category_id}":{"get":{"operationId":"get_category","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"category_id","schema":{"title":"Category Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryNotFound"}}}}},"summary":"Get Category","description":"Retrieves an active household category, including its emoji, type, and group assignment.\n\nReturns `category_not_found` if the category is deleted or does not belong to this household.","tags":["categories"],"security":[{"PersonalApiToken":[]}]},"put":{"operationId":"update_category","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"category_id","schema":{"title":"Category Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/CategoryNotFound"},{"$ref":"#/components/schemas/CategoryGroupNotFound"}],"discriminator":{"propertyName":"code","mapping":{"category_not_found":"#/components/schemas/CategoryNotFound","category_group_not_found":"#/components/schemas/CategoryGroupNotFound"}}}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/DuplicateName"},{"$ref":"#/components/schemas/CategoryDuplicateEmoji"}],"discriminator":{"propertyName":"code","mapping":{"duplicate_name":"#/components/schemas/DuplicateName","duplicate_emoji":"#/components/schemas/CategoryDuplicateEmoji"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Category","description":"Replaces a category's name, emoji, type, and group assignment and returns the updated category.\n\nSupply the complete category definition. Set `group_id` to null to remove its group; when a group is supplied, its type determines the category's effective type. The name and emoji must remain unique among active household categories. Changing the type affects how assigned transactions are classified in reports.","tags":["categories"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertCategoryRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_category","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"category_id","schema":{"title":"Category Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryNotFound"}}}}},"summary":"Delete Category","description":"Deletes a category and makes its associated transactions uncategorized, including transactions on deleted accounts. The transactions themselves are retained.\n\nAlso removes the category from rule conditions and actions and deletes rules left without criteria or actions. Returns `204` with no response body.","tags":["categories"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/category-groups":{"post":{"operationId":"create_category_group","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryGroupResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateName"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Category Group","description":"Creates a named category group for income, expense, or transfer categories and returns the new group.\n\nThe group name must be unique within the household. Assign categories to it using the category create or update endpoint; creating the group does not create categories.","tags":["categories"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCategoryGroupRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/category-groups/{group_id}":{"put":{"operationId":"update_category_group","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"group_id","schema":{"title":"Group Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryGroupResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryGroupNotFound"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateName"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Category Group","description":"Renames a category group and returns the updated group. Its type and existing category assignments are preserved.\n\nThe new name must be unique within the household. Returns `category_group_not_found` if the group does not belong to this household.","tags":["categories"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCategoryGroupRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_category_group","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"group_id","schema":{"title":"Group Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CategoryGroupNotFound"}}}}},"summary":"Delete Category Group","description":"Permanently deletes a category group and leaves its categories ungrouped. The categories, their types, and their transaction assignments are retained.\n\nReturns `204` with no response body. To remove a category itself, use the category deletion endpoint.","tags":["categories"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions":{"get":{"operationId":"list_transactions","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"cursor","schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"},"required":false},{"in":"query","name":"min_limit","schema":{"default":50,"maximum":200,"minimum":1,"title":"Min Limit","type":"integer"},"required":false},{"in":"query","name":"min_amount","schema":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison.","title":"Min Amount"},"required":false,"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison."},{"in":"query","name":"max_amount","schema":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison.","title":"Max Amount"},"required":false,"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison."},{"in":"query","name":"amount_equal","schema":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison.","title":"Amount Equal"},"required":false,"description":"Interpreted in the household's currency. Transaction amounts in other currencies are converted before the filter is applied. Amounts and thresholds are rounded to the currency minor unit using half-even rounding for comparison."},{"in":"query","name":"search","schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"},"required":false},{"in":"query","name":"start_date","schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Start Date"},"required":false},{"in":"query","name":"end_date","schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"End Date"},"required":false},{"in":"query","name":"need_review","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Need Review"},"required":false},{"in":"query","name":"pending","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pending"},"required":false},{"in":"query","name":"has_notes","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Notes"},"required":false},{"in":"query","name":"uncategorized","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Uncategorized"},"required":false},{"in":"query","name":"unknown_merchant","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Unknown Merchant"},"required":false},{"in":"query","name":"deleted","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Deleted"},"required":false},{"in":"query","name":"hidden","schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hidden"},"required":false},{"in":"query","name":"merchant_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Merchant Ids"},"required":false,"style":"form","explode":false},{"in":"query","name":"category_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Ids"},"required":false,"style":"form","explode":false},{"in":"query","name":"tag_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Ids"},"required":false,"style":"form","explode":false},{"in":"query","name":"account_ids","schema":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"required":false,"style":"form","explode":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/FiltersChanged"},{"$ref":"#/components/schemas/InvalidCursor"}],"discriminator":{"propertyName":"code","mapping":{"filters_changed":"#/components/schemas/FiltersChanged","invalid_cursor":"#/components/schemas/InvalidCursor"}}}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"List Transactions","description":"Lists household transactions newest date first, with related account, merchant, category, and tag details and daily totals in the household's reporting currency. By default, hidden and deleted transactions, split parents, and transactions on deleted accounts are excluded; pending transactions are included.\n\nSet `hidden=true` or `deleted=true` to browse those transactions; `deleted=true` takes precedence. Date bounds are inclusive, and amount filters use the household's currency. `uncategorized=true` overrides category IDs, and `unknown_merchant=true` overrides merchant IDs.\n\nPass `next_cursor` as `cursor` with the same filters to continue. Pages keep complete days together, so a response can exceed `min_limit`. When filters change, start without a cursor. Daily sums exclude transfers, even when transfer transactions appear in the results.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]},"post":{"operationId":"create_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTransactionResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/AccountNotFound"},{"$ref":"#/components/schemas/CategoryNotFound"},{"$ref":"#/components/schemas/MerchantNotFound"},{"$ref":"#/components/schemas/TagNotFound"}],"discriminator":{"propertyName":"code","mapping":{"account_not_found":"#/components/schemas/AccountNotFound","category_not_found":"#/components/schemas/CategoryNotFound","merchant_not_found":"#/components/schemas/MerchantNotFound","tag_not_found":"#/components/schemas/TagNotFound"}}}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotManual"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Transaction","description":"Creates a posted transaction on a non-deleted manual account in the household. The transaction uses the account's currency; positive amounts represent income and negative amounts represent expenses. Provider-linked accounts reject manual entries with `account_not_manual`.\n\nReferenced categories, merchants, and tags must belong to the household. Household rules run before the created transaction is returned, preserving explicitly supplied category and merchant choices and adding applicable tags.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTransactionRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/bulk-unhide":{"post":{"operationId":"bulk_unhide_transactions","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Unhide Transactions","description":"Clears the hidden flag on matching transaction IDs and returns the affected transactions. Deleted transactions can be unhidden, but remain deleted until restored.\n\nIDs that are missing, already unhidden, or on deleted accounts are skipped. Returns `transaction_not_found` only when no eligible transactions match; compare the returned IDs with your request to identify skipped entries.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/bulk-hide":{"post":{"operationId":"bulk_hide_transactions","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Hide Transactions","description":"Hides the requested visible transactions from normal lists and spending reports and returns the affected transactions.\n\nIDs that are missing or not currently visible, including hidden or deleted transactions and split parents, are skipped. Returns `transaction_not_found` when no eligible transactions match. Compare returned IDs with your request to identify skipped entries.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/bulk-restore":{"post":{"operationId":"bulk_restore_transactions","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Restore Transactions","description":"Clears the deletion flag on matching deleted transactions and returns the affected transactions. Hidden flags are preserved.\n\nIDs that are missing, not deleted, or on deleted accounts are skipped. Returns `transaction_not_found` when no eligible transactions match. Compare returned IDs with your request to identify skipped entries.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/bulk-delete":{"post":{"operationId":"bulk_delete_transactions","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Delete Transactions","description":"Soft-deletes matching transactions and returns the affected transactions. Hidden transactions are eligible; already deleted transactions, split parents, and transactions on deleted accounts are excluded.\n\nMissing or ineligible IDs are skipped, and `transaction_not_found` is returned only if nothing matches. Data is retained for the bulk-restore endpoint. Compare returned IDs with your request to identify skipped entries.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/bulk-add-tags":{"post":{"operationId":"bulk_add_tags","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/TransactionNotFound"},{"$ref":"#/components/schemas/TagNotFound"}],"discriminator":{"propertyName":"code","mapping":{"transaction_not_found":"#/components/schemas/TransactionNotFound","tag_not_found":"#/components/schemas/TagNotFound"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Add Tags","description":"Adds the supplied tags to matching non-deleted transactions without removing existing tags. Hidden transactions are eligible; split parents and transactions on deleted accounts are excluded.\n\nEvery tag ID must identify an active tag in the household. Invalid tags reject the request before any updates. Missing or ineligible transaction IDs are skipped, with `transaction_not_found` returned when none match. Returns the affected transactions.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkAddTagsRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/bulk-review":{"post":{"operationId":"bulk_update_review","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Update Review","description":"Sets `need_review` on matching non-deleted transactions and returns the affected transactions. Set it to false to mark them reviewed, or true to put them back in the review queue.\n\nHidden transactions are eligible; split parents and transactions on deleted accounts are excluded. Missing or ineligible IDs are skipped, with `transaction_not_found` returned when none match.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkReviewRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/bulk-set-category":{"post":{"operationId":"bulk_set_category","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkTransactionsResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/TransactionNotFound"},{"$ref":"#/components/schemas/CategoryNotFound"}],"discriminator":{"propertyName":"code","mapping":{"transaction_not_found":"#/components/schemas/TransactionNotFound","category_not_found":"#/components/schemas/CategoryNotFound"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Set Category","description":"Assigns one household category to matching non-deleted transactions, or clears their category when `household_finance_category_id` is null. The chosen category is protected from automatic overrides, and household rules run again to apply other actions such as adding tags.\n\nHidden transactions are eligible; split parents and transactions on deleted accounts are excluded. Missing or ineligible transaction IDs are skipped; an invalid category rejects the request. Returns the affected transactions, or `transaction_not_found` when none match.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSetCategoryRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/duplicates":{"get":{"operationId":"list_duplicate_groups","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DuplicateGroupsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"List Duplicate Groups","description":"Lists groups of visible transactions flagged as possible duplicates. Each group contains at least two transactions with full transaction details for comparison.\n\nReview these candidates before deleting entries; a duplicate flag does not establish that a transaction should be removed. Use the dismiss endpoint to clear flags when the transactions are distinct. Hidden and deleted transactions are excluded.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}":{"get":{"operationId":"get_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTransactionResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}}},"summary":"Get Transaction","description":"Retrieves a transaction with its account, category, merchant, tags, native amount, and amount converted to the household's reporting currency.\n\nHidden, deleted, and split-parent transactions can be retrieved by ID. Transactions on deleted accounts are unavailable; restore the account before retrieving them.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]},"put":{"operationId":"update_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListTransactionResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/TransactionNotFound"},{"$ref":"#/components/schemas/CategoryNotFound"},{"$ref":"#/components/schemas/MerchantNotFound"},{"$ref":"#/components/schemas/TagNotFound"}],"discriminator":{"propertyName":"code","mapping":{"transaction_not_found":"#/components/schemas/TransactionNotFound","category_not_found":"#/components/schemas/CategoryNotFound","merchant_not_found":"#/components/schemas/MerchantNotFound","tag_not_found":"#/components/schemas/TagNotFound"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Transaction","description":"Replaces a transaction's editable details, including its display name, date, notes, category, merchant, tags, and hidden state. Supply every required field, including nulls for nullable fields; `tags` replaces the existing tag set. The amount and account are not editable through this endpoint.\n\nChanges to the date, merchant, and category are protected from later automatic overrides. When rule-matching inputs change, household rules run again and may add tags or apply other unlocked actions. Returns the resulting transaction.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTransactionRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}}},"summary":"Delete Transaction","description":"Soft-deletes a transaction so it no longer appears in normal lists or spending reports. Its data is retained and can be recovered through the restore endpoint.\n\nDeleting a split parent also removes its children from normal views until the parent is restored. The account must not be deleted. Returns `204` with no response body.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/restore":{"post":{"operationId":"restore_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}}},"summary":"Restore Transaction","description":"Clears a transaction's deletion flag, making it eligible for normal views and spending reports again.\n\nIts hidden state is preserved, so a hidden transaction also needs to be unhidden to appear in normal views. The account must not be deleted. Restoring an already restored transaction succeeds and returns `204` with no response body.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/hide":{"post":{"operationId":"hide_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}}},"summary":"Hide Transaction","description":"Hides a transaction from normal lists and spending reports while retaining its data. Use `hidden=true` on the transaction list to browse hidden transactions.\n\nUse the unhide endpoint to reverse this change. The account must not be deleted. Returns `204` with no response body.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/unhide":{"post":{"operationId":"unhide_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}}},"summary":"Unhide Transaction","description":"Clears a transaction's hidden flag, making it eligible for normal views and spending reports again.\n\nThis does not clear its deletion flag; restore a deleted transaction separately. Unhiding an already unhidden transaction succeeds. Returns `204` with no response body.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/duplicates/dismiss":{"post":{"operationId":"dismiss_duplicates","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Dismiss Duplicates","description":"Clears possible-duplicate flags for the supplied transactions and removes references to them from other transactions. Transaction records and their amounts are retained.\n\nEvery supplied transaction ID must belong to the household and be on a non-deleted account; otherwise the request fails before any flags are cleared. Repeated IDs are handled once. Returns `204` with no response body.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DismissDuplicatesRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/history":{"get":{"operationId":"get_transaction_history","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionHistoryResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}}},"summary":"Get Transaction History","description":"Retrieves the recorded change history for a transaction, including changes made by users, rules, and provider synchronization.\n\nUse the entries to inspect which fields changed and who or what made the change. The transaction may be hidden or deleted, but its account must not be deleted.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/splits":{"get":{"operationId":"list_splits","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListSplitsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotSplit"}}}}},"summary":"List Splits","description":"Retrieves a split transaction's original parent and its child transactions for inspection or editing. Pass either the parent ID or one of its child IDs.\n\nReturns `transaction_not_split` if the transaction is not part of a split. The account must not be deleted.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]},"post":{"operationId":"split_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitTransactionResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"anyOf":[{"title":"Response","oneOf":[{"$ref":"#/components/schemas/SplitTooFew"},{"$ref":"#/components/schemas/SplitSumMismatch"},{"$ref":"#/components/schemas/SplitSignMismatch"},{"$ref":"#/components/schemas/SplitZeroAmount"}],"discriminator":{"propertyName":"code","mapping":{"too_few_splits":"#/components/schemas/SplitTooFew","sum_does_not_match_total":"#/components/schemas/SplitSumMismatch","split_sign_mismatch":"#/components/schemas/SplitSignMismatch","zero_amount_split":"#/components/schemas/SplitZeroAmount"}}},{"$ref":"#/components/schemas/HttpErrorResponse"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/TransactionNotFound"},{"$ref":"#/components/schemas/CategoryNotFound"},{"$ref":"#/components/schemas/MerchantNotFound"},{"$ref":"#/components/schemas/TagNotFound"}],"discriminator":{"propertyName":"code","mapping":{"transaction_not_found":"#/components/schemas/TransactionNotFound","category_not_found":"#/components/schemas/CategoryNotFound","merchant_not_found":"#/components/schemas/MerchantNotFound","tag_not_found":"#/components/schemas/TagNotFound"}}}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/SplitChildCannotSplit"},{"$ref":"#/components/schemas/SplitTransactionDeleted"},{"$ref":"#/components/schemas/SplitTransactionPending"}],"discriminator":{"propertyName":"code","mapping":{"child_cannot_split":"#/components/schemas/SplitChildCannotSplit","transaction_deleted":"#/components/schemas/SplitTransactionDeleted","transaction_pending":"#/components/schemas/SplitTransactionPending"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Split Transaction","description":"Splits a posted transaction into at least two child transactions and returns the new children. Each amount must be nonzero, have the original transaction's sign, and sum exactly to the original amount in its native currency.\n\nThe parent remains stored, while its children appear in normal transaction views and reports. Pending or deleted transactions and split children cannot be split. Calling this endpoint on an existing split replaces all previous children with newly created ones; send the complete desired split each time.","tags":["transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SplitTransactionRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"unsplit_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnsplitChildCannotUnsplit"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotSplit"}}}}},"summary":"Unsplit Transaction","description":"Removes all child transactions from a split parent and clears its split state so the original transaction can appear in normal views again.\n\nPass the parent ID. The children are permanently deleted, including their individual edits. Returns `transaction_not_split` if the parent is not currently split, or `child_cannot_unsplit` if a child ID is supplied. Success returns `204` with no response body.","tags":["transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/images":{"get":{"operationId":"list_transaction_images","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionImageListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}}},"summary":"List Transaction Images","description":"Lists receipt images and other images attached to a transaction, with their IDs and download URLs. An existing transaction without images returns an empty list.\n\nRequires a household member or owner role; viewers cannot access transaction images. The transaction's account must not be deleted. Fetch this endpoint again when you need fresh private image URLs.","tags":["transaction-images"],"security":[{"PersonalApiToken":[]}]},"post":{"operationId":"upload_transaction_images","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionImageListResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ImageInvalidFileType"},{"$ref":"#/components/schemas/HttpErrorResponse"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransactionNotFound"}}}},"413":{"description":"Content Too Large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImageFileTooLarge"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Upload Transaction Images","description":"Attaches images to a transaction and returns only the newly created image records. Existing attachments are retained.\n\nSend files as repeated `files` fields in a `multipart/form-data` request. Each file must be JPEG, PNG, or WebP, at most 5 MiB (5,242,880 bytes) and 25 million decoded pixels across all frames. Every file is validated before any are saved; a validation error rejects the entire batch. Requires a household member or owner role.","tags":["transaction-images"],"requestBody":{"content":{"multipart/form-data":{"schema":{"properties":{"files":{"items":{"format":"binary","type":"string"},"title":"Files","type":"array"}},"required":["files"],"title":"FileParams","type":"object"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/images/bulk-delete":{"post":{"operationId":"bulk_delete_transaction_images","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/TransactionNotFound"},{"$ref":"#/components/schemas/ImageNotFound"}],"discriminator":{"propertyName":"code","mapping":{"transaction_not_found":"#/components/schemas/TransactionNotFound","image_not_found":"#/components/schemas/ImageNotFound"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Bulk Delete Transaction Images","description":"Permanently removes matching image attachments from a transaction. The transaction itself is retained.\n\nIDs not attached to this transaction are skipped. Returns `image_not_found` if none match, or `204` with no response body after deletion. Requires a household member or owner role.","tags":["transaction-images"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteTransactionImagesRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/transactions/{transaction_id}/images/{image_id}":{"delete":{"operationId":"delete_transaction_image","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"transaction_id","schema":{"title":"Transaction Id","type":"string"},"required":true},{"in":"path","name":"image_id","schema":{"title":"Image Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/TransactionNotFound"},{"$ref":"#/components/schemas/ImageNotFound"}],"discriminator":{"propertyName":"code","mapping":{"transaction_not_found":"#/components/schemas/TransactionNotFound","image_not_found":"#/components/schemas/ImageNotFound"}}}}}}},"summary":"Delete Transaction Image","description":"Permanently removes one image attachment from a transaction. The transaction and its other attachments are retained.\n\nThe image must belong to the specified transaction in this household. Returns `204` with no response body on success, or `image_not_found` if the image is unavailable. Requires a household member or owner role.","tags":["transaction-images"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions":{"post":{"operationId":"create_recurring_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/InvalidFrequencyFields"},{"$ref":"#/components/schemas/HttpErrorResponse"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Create Recurring Transaction","description":"Creates a recurring income or expense series for a household merchant. This defines an expected schedule; it does not initiate payments or create financial transactions.\n\nSupply a positive amount and use `type` to distinguish income from expenses. Currency defaults to the household's reporting currency when omitted. Twice-monthly frequencies must omit `start_date` or set it to null; all other frequencies require an anchor date. Returns the new series.","tags":["recurring-transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRecurringTransactionRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"get":{"operationId":"list_recurring_transactions","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"status","schema":{"anyOf":[{"$ref":"#/components/schemas/RecurringTransactionStatus"},{"type":"null"}]},"required":false},{"in":"query","name":"merchant_id","schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Merchant Id"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"List Recurring Transactions","description":"Lists the household's recurring income and expense series ordered by name, optionally filtered by status or merchant.\n\nBoth active and cancelled series are included when status is omitted. The response contains schedule definitions without pagination; use the occurrences endpoints for expected dates and matched transactions.","tags":["recurring-transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions/summary":{"get":{"operationId":"get_summary","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"month","schema":{"title":"Month","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionSummaryResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvalidMonthFormat"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Summary","description":"Summarizes recurring income and expenses for a calendar month supplied as `YYYY-MM`. Returns expected expenses and income, plus expenses paid and income received, as positive magnitudes in the household's reporting currency.\n\nExpected totals follow each series' schedule and active date window. Paid and received totals use matched transactions, so they can differ from expected amounts. This endpoint does not initiate payments.","tags":["recurring-transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions/occurrences":{"get":{"operationId":"get_occurrences","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"format":"date","title":"Start Date","type":"string"},"required":true},{"in":"query","name":"end_date","schema":{"format":"date","title":"End Date","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionOccurrenceListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Occurrences","description":"Lists expected recurring income and expense occurrences within an inclusive date range, with their status and any matched transaction details.\n\nOccurrences are calculated from stored schedules and transaction history; they are not new financial transactions. Cancelled series contribute only through their end date. Use this response to build a recurring calendar and distinguish expected activity from recorded payments.","tags":["recurring-transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions/{recurring_transaction_id}/occurrences":{"get":{"operationId":"get_recurring_transaction_occurrences","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"recurring_transaction_id","schema":{"title":"Recurring Transaction Id","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"format":"date","title":"Start Date","type":"string"},"required":true},{"in":"query","name":"end_date","schema":{"format":"date","title":"End Date","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionOccurrenceListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionNotFound"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Recurring Transaction Occurrences","description":"Lists expected occurrences for one recurring series within an inclusive date range, including their status and matched transaction details.\n\nMatching is coordinated across the household's series, so results agree with the household-wide occurrences endpoint when several series could match the same transaction. Returns `recurring_transaction_not_found` if the series does not belong to this household.","tags":["recurring-transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions/suggestions":{"get":{"operationId":"get_suggestions","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionSuggestionListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}}},"summary":"Get Suggestions","description":"Detects candidate recurring series from the household's transaction history and returns suggested merchants, amounts, frequencies, and supporting details.\n\nSuggestions account for existing tracked series and previous dismissals. They are proposals, not saved recurring transactions. To track a suggestion, create a recurring series with the desired details; to suppress one, use the dismiss endpoint.","tags":["recurring-transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions/suggestions/dismiss":{"post":{"operationId":"dismiss_suggestion","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Dismiss Suggestion","description":"Suppresses one suggested recurring series identified by merchant, amount, currency, and frequency. Existing transactions and saved recurring series are retained.\n\nEach request dismisses one series. Repeating the same request can suppress additional identical series, so this operation is not idempotent. Use the restore-suggestion endpoint to reverse one dismissal. Returns `204` with no response body.","tags":["recurring-transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DismissSuggestionRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions/suggestions/restore":{"post":{"operationId":"restore_suggestion","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"bad_request","message":"Bad Request"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DismissedSuggestionNotFound"}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Restore Suggestion","description":"Reverses one recurring-suggestion dismissal identified by merchant, amount, currency, and frequency. The candidate may appear again if current transaction history still supports it.\n\nEach request restores one dismissed series. Returns `suggestion_not_found` when there is no matching dismissal to reverse, or `204` with no response body on success.","tags":["recurring-transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DismissSuggestionRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/recurring-transactions/{recurring_transaction_id}":{"get":{"operationId":"get_recurring_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"recurring_transaction_id","schema":{"title":"Recurring Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotHouseholdMember"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionNotFound"}}}}},"summary":"Get Recurring Transaction","description":"Retrieves a recurring series with its merchant, amount, currency, frequency, anchor date, status, and notes.\n\nActive and cancelled series can be retrieved. Use the series' occurrences endpoint to inspect expected dates and matched transactions. Returns `recurring_transaction_not_found` for an unavailable series.","tags":["recurring-transactions"],"security":[{"PersonalApiToken":[]}]},"put":{"operationId":"update_recurring_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"recurring_transaction_id","schema":{"title":"Recurring Transaction Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionResponse"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/InvalidFrequencyFields"},{"$ref":"#/components/schemas/HttpErrorResponse"}]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/RecurringTransactionNotFound"},{"$ref":"#/components/schemas/MerchantNotFound"}],"discriminator":{"propertyName":"code","mapping":{"recurring_transaction_not_found":"#/components/schemas/RecurringTransactionNotFound","merchant_not_found":"#/components/schemas/MerchantNotFound"}}}}}},"415":{"description":"Unsupported Media Type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HttpErrorResponse"},"example":{"code":"unsupported_media_type","message":"Unsupported Media Type"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Update Recurring Transaction","description":"Replaces a recurring series' editable details and returns the updated series. Supply its complete definition, including currency, status, and notes. Twice-monthly frequencies require a null or omitted `start_date`; other frequencies require an anchor date.\n\nChanging status to `cancelled` records today in the household's timezone as the end date, preserving an existing end date on later edits. Reactivating clears the end date. These changes affect expected occurrences in Penny; they do not cancel or modify payments at the merchant.","tags":["recurring-transactions"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateRecurringTransactionRequest"}}},"required":true},"security":[{"PersonalApiToken":[]}]},"delete":{"operationId":"delete_recurring_transaction","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"recurring_transaction_id","schema":{"title":"Recurring Transaction Id","type":"string"},"required":true}],"responses":{"204":{"description":"No Content"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"402":{"description":"Payment Required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionRequired"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecurringTransactionNotFound"}}}}},"summary":"Delete Recurring Transaction","description":"Permanently deletes a recurring series and removes its expected occurrences from recurring views. Financial transactions previously matched to the series are retained.\n\nTo stop future occurrences while retaining the series' past schedule, update its status to `cancelled` instead. Returns `204` with no response body. Deleting a series does not cancel payments at the merchant.","tags":["recurring-transactions"],"security":[{"PersonalApiToken":[]}]}},"/v1/securities":{"get":{"operationId":"list_securities","parameters":[],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityListResponse"}}}}},"summary":"List Securities","description":"Lists the securities for which Penny provides benchmark price history, with each security's slug, ticker symbol, and name. Authentication is not required.\n\nUse the returned slug with the security-prices endpoint. This is a fixed catalog of supported benchmarks rather than a household's investment holdings.","tags":["securities"]}},"/v1/securities/{slug}/prices":{"get":{"operationId":"get_security_prices","parameters":[{"in":"path","name":"slug","schema":{"title":"Slug","type":"string"},"required":true},{"in":"query","name":"start_date","schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Start Date"},"required":false},{"in":"query","name":"end_date","schema":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"End Date"},"required":false}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityPriceHistoryResponse"}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityNotFound"}}}},"422":{"description":"Unprocessable Content","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}},"summary":"Get Security Prices","description":"Retrieves stored daily closing prices for a supported security, ordered from oldest to newest. Authentication is not required.\n\nUse a slug returned by the securities list. Optional date bounds are inclusive; omitted bounds leave that end of the range unrestricted. Only dates with stored prices are returned. An unknown slug returns `security_not_found`; a valid security without prices in the range returns an empty list.","tags":["securities"]}},"/v1/households/{household_id}/exports":{"post":{"operationId":"request_export","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataExportResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/ReadOnlyToken"},{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"read_only_token":"#/components/schemas/ReadOnlyToken","not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"409":{"description":"Conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataExportInProgress"}}}}},"summary":"Request Export","description":"Queues a ZIP archive of the household's data and returns `202` with the export record. Only the household owner can request an export, including when subscription access has lapsed.\n\nPoll the export's retrieval endpoint until its status is `completed` or `failed`. A completed export includes a download URL and is retained for seven days. Only one export can be pending or processing per household; another request during that time returns `export_in_progress`.","tags":["exports"],"security":[{"PersonalApiToken":[]}]},"get":{"operationId":"list_exports","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataExportListResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}}},"summary":"List Exports","description":"Lists the household's ten most recent export records, newest first, including their status and download URL when available.\n\nOnly the household owner can access exports, including when subscription access has lapsed. Completed archives expire seven days after completion. This endpoint does not start a new export.","tags":["exports"],"security":[{"PersonalApiToken":[]}]}},"/v1/households/{household_id}/exports/{export_id}":{"get":{"operationId":"get_export","parameters":[{"in":"path","name":"household_id","schema":{"title":"Household Id","type":"string"},"required":true},{"in":"path","name":"export_id","schema":{"title":"Export Id","type":"string"},"required":true}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataExportResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotAuthenticated"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"title":"Response","oneOf":[{"$ref":"#/components/schemas/NotHouseholdMember"},{"$ref":"#/components/schemas/InsufficientHouseholdRole"}],"discriminator":{"propertyName":"code","mapping":{"not_household_member":"#/components/schemas/NotHouseholdMember","insufficient_household_role":"#/components/schemas/InsufficientHouseholdRole"}}}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataExportNotFound"}}}}},"summary":"Get Export","description":"Retrieves an export's current status and, once completed, its download URL, size, completion time, and expiration time. Use this endpoint to poll an export requested earlier.\n\nOnly the household owner can access it, including when subscription access has lapsed. Private download URLs can expire before the archive; retrieve the export again for a fresh URL. Download before `expires_at`; purged exports return `export_not_found`.","tags":["exports"],"security":[{"PersonalApiToken":[]}]}}},"components":{"schemas":{"AuthProvider":{"enum":["apple","google"],"title":"AuthProvider","type":"string"},"HouseholdAccessStatus":{"enum":["available","subscription_required"],"title":"HouseholdAccessStatus","type":"string"},"HouseholdRole":{"enum":["owner","member","viewer"],"title":"HouseholdRole","type":"string"},"HouseholdSummary":{"properties":{"id":{"examples":["Hh4vK8pQ2sLm"],"title":"Id","type":"string"},"name":{"examples":["Chen Household"],"title":"Name","type":"string"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/households/Hh4vK8pQ2sLm.png"],"title":"Image Url"},"role":{"$ref":"#/components/schemas/HouseholdRole"},"finance_account_count":{"examples":[4],"title":"Finance Account Count","type":"integer"},"access_status":{"$ref":"#/components/schemas/HouseholdAccessStatus"}},"required":["id","name","image_url","role","finance_account_count","access_status"],"title":"HouseholdSummary","type":"object"},"SocialAccountResponse":{"properties":{"provider":{"$ref":"#/components/schemas/AuthProvider"}},"required":["provider"],"title":"SocialAccountResponse","type":"object"},"SubscriptionStatus":{"enum":["active","expired","none"],"title":"SubscriptionStatus","type":"string"},"SubscriptionSummary":{"description":"The caller's *own* subscription row, as the app needs to describe it.\n\nRides on `/v1/users/me` and is what the sync returns, so the two writers of\nthe client's copy agree on one shape rather than drifting apart.\n\nThis is not household access: access resolves from the household *owner's* row, which\nfor a member is someone else's; see `household_is_entitled`.\n`HouseholdSummary.access_status` on the same payload is the server-authored\ndecision that actually gates.","properties":{"status":{"$ref":"#/components/schemas/SubscriptionStatus"},"entitlement_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["penny_plus_annual"],"title":"Entitlement Id"}},"required":["status","entitlement_id"],"title":"SubscriptionSummary","type":"object"},"UserWithHouseholdsResponse":{"properties":{"id":{"examples":["Us2mH7qB5kLp"],"title":"Id","type":"string"},"email":{"format":"email","title":"Email","type":"string"},"pending_email":{"anyOf":[{"format":"email","type":"string"},{"type":"null"}],"title":"Pending Email"},"name":{"examples":["Avery Chen"],"title":"Name","type":"string"},"is_email_verified":{"title":"Is Email Verified","type":"boolean"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/users/Us2mH7qB5kLp.png"],"title":"Image Url"},"has_password":{"title":"Has Password","type":"boolean"},"has_completed_onboarding":{"title":"Has Completed Onboarding","type":"boolean"},"marketing_emails_enabled":{"title":"Marketing Emails Enabled","type":"boolean"},"social_accounts":{"items":{"$ref":"#/components/schemas/SocialAccountResponse"},"title":"Social Accounts","type":"array"},"households":{"items":{"$ref":"#/components/schemas/HouseholdSummary"},"title":"Households","type":"array"},"selected_household_id":{"anyOf":[{"examples":["Hh4vK8pQ2sLm"],"type":"string"},{"type":"null"}],"title":"Selected Household Id"},"subscription":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionSummary"},{"type":"null"}]},"accepted_invite_household_id":{"anyOf":[{"examples":["Hh4vK8pQ2sLm"],"type":"string"},{"type":"null"}],"description":"Household selected after handling the invite supplied during authentication. Null when no invite was handled or outside authentication.","title":"Accepted Invite Household Id"}},"required":["id","email","pending_email","name","is_email_verified","image_url","has_password","has_completed_onboarding","marketing_emails_enabled","social_accounts","households","selected_household_id","subscription","accepted_invite_household_id"],"title":"UserWithHouseholdsResponse","type":"object"},"NotAuthenticated":{"properties":{"code":{"const":"not_authenticated","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Authentication required"]}},"required":["code","message"],"title":"NotAuthenticated","type":"object"},"UserResponse":{"properties":{"id":{"examples":["Us2mH7qB5kLp"],"title":"Id","type":"string"},"email":{"format":"email","title":"Email","type":"string"},"pending_email":{"anyOf":[{"format":"email","type":"string"},{"type":"null"}],"title":"Pending Email"},"name":{"examples":["Avery Chen"],"title":"Name","type":"string"},"is_email_verified":{"title":"Is Email Verified","type":"boolean"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/users/Us2mH7qB5kLp.png"],"title":"Image Url"}},"required":["id","email","pending_email","name","is_email_verified","image_url"],"title":"UserResponse","type":"object"},"ReadOnlyToken":{"properties":{"code":{"const":"read_only_token","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["This API token only permits read requests"]}},"required":["code","message"],"title":"ReadOnlyToken","type":"object"},"HttpErrorResponse":{"properties":{"code":{"examples":["bad_request"],"title":"Code","type":"string"},"message":{"examples":["Bad Request"],"title":"Message","type":"string"}},"required":["code","message"],"title":"HttpErrorResponse","type":"object"},"FieldError":{"properties":{"field":{"examples":["currency"],"title":"Field","type":"string"},"code":{"examples":["invalid_currency"],"title":"Code","type":"string"},"message":{"examples":["Input should be a valid ISO 4217 currency code."],"title":"Message","type":"string"},"context":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"examples":[{"expected":"USD","received":"US"}],"title":"Context"}},"required":["field","code","message","context"],"title":"FieldError","type":"object"},"ValidationErrorResponse":{"properties":{"code":{"const":"validation_error","title":"Code","type":"string"},"message":{"examples":["Some fields are invalid."],"title":"Message","type":"string"},"errors":{"items":{"$ref":"#/components/schemas/FieldError"},"title":"Errors","type":"array"}},"required":["code","message","errors"],"title":"ValidationErrorResponse","type":"object"},"UpdateUserRequestPatch":{"properties":{"name":{"examples":["Avery Chen"],"maxLength":100,"title":"Name","type":"string"}},"title":"UpdateUserRequestPatch","type":"object"},"ImageUploadResponse":{"properties":{"image_url":{"examples":["https://cdn.penny.finance/merchants/blue-bottle-coffee.png"],"title":"Image Url","type":"string"}},"required":["image_url"],"title":"ImageUploadResponse","type":"object"},"ImageInvalidFileType":{"properties":{"code":{"const":"invalid_file_type","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["File must be JPEG, PNG, or WebP"]}},"required":["code","message"],"title":"ImageInvalidFileType","type":"object"},"ImageFileTooLarge":{"properties":{"code":{"const":"file_too_large","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["File exceeds maximum size of 5MB"]}},"required":["code","message"],"title":"ImageFileTooLarge","type":"object"},"ImageNoImage":{"properties":{"code":{"const":"no_image","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["No image to delete"]}},"required":["code","message"],"title":"ImageNoImage","type":"object"},"Currency":{"enum":["AED","AFN","ALL","AMD","AOA","ARS","AUD","AWG","AZN","BAM","BBD","BDT","BHD","BIF","BMD","BND","BOB","BOV","BRL","BSD","BTN","BWP","BYN","BZD","CAD","CDF","CHE","CHF","CHW","CLF","CLP","CNY","COP","COU","CRC","CUP","CVE","CZK","DJF","DKK","DOP","DZD","EGP","ERN","ETB","EUR","FJD","FKP","GBP","GEL","GHS","GIP","GMD","GNF","GTQ","GYD","HKD","HNL","HTG","HUF","IDR","ILS","INR","IQD","IRR","ISK","JMD","JOD","JPY","KES","KGS","KHR","KMF","KPW","KRW","KWD","KYD","KZT","LAK","LBP","LKR","LRD","LSL","LYD","MAD","MDL","MGA","MKD","MMK","MNT","MOP","MRU","MUR","MVR","MWK","MXN","MXV","MYR","MZN","NAD","NGN","NIO","NOK","NPR","NZD","OMR","PAB","PEN","PGK","PHP","PKR","PLN","PYG","QAR","RON","RSD","RUB","RWF","SAR","SBD","SCR","SDG","SEK","SGD","SHP","SLE","SOS","SRD","SSP","STN","SVC","SYP","SZL","THB","TJS","TMT","TND","TOP","TRY","TTD","TWD","TZS","UAH","UGX","USD","USN","UYI","UYU","UYW","UZS","VED","VES","VND","VUV","WST","XAD","XAF","XAG","XAU","XBA","XBB","XBC","XBD","XCD","XCG","XDR","XOF","XPD","XPF","XPT","XSU","XTS","XUA","XXX","YER","ZAR","ZMW","ZWG"],"title":"Currency","type":"string"},"HouseholdListResponse":{"properties":{"households":{"items":{"$ref":"#/components/schemas/HouseholdResponse"},"title":"Households","type":"array"}},"required":["households"],"title":"HouseholdListResponse","type":"object"},"HouseholdPreferences":{"properties":{"show_recurring_suggestions":{"title":"Show Recurring Suggestions","type":"boolean"},"show_advanced_details":{"title":"Show Advanced Details","type":"boolean"}},"required":["show_recurring_suggestions","show_advanced_details"],"title":"HouseholdPreferences","type":"object"},"HouseholdResponse":{"properties":{"id":{"examples":["Hh4vK8pQ2sLm"],"title":"Id","type":"string"},"name":{"examples":["Chen Household"],"title":"Name","type":"string"},"currency":{"$ref":"#/components/schemas/Currency"},"timezone":{"examples":["America/Los_Angeles"],"title":"Timezone","type":"string"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/households/Hh4vK8pQ2sLm.png"],"title":"Image Url"},"role":{"$ref":"#/components/schemas/HouseholdRole"},"preferences":{"$ref":"#/components/schemas/HouseholdPreferences"},"access_status":{"$ref":"#/components/schemas/HouseholdAccessStatus"}},"required":["id","name","currency","timezone","image_url","role","preferences","access_status"],"title":"HouseholdResponse","type":"object"},"CreateHouseholdRequest":{"properties":{"name":{"examples":["Chen Household"],"maxLength":255,"title":"Name","type":"string"},"currency":{"$ref":"#/components/schemas/Currency","examples":["USD"]},"timezone":{"examples":["America/Los_Angeles"],"title":"Timezone","type":"string"}},"required":["name","currency","timezone"],"title":"CreateHouseholdRequest","type":"object"},"InsufficientHouseholdRole":{"properties":{"code":{"const":"insufficient_household_role","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Insufficient household role"]}},"required":["code","message"],"title":"InsufficientHouseholdRole","type":"object"},"NotHouseholdMember":{"properties":{"code":{"const":"not_household_member","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Not a member of this household"]}},"required":["code","message"],"title":"NotHouseholdMember","type":"object"},"SubscriptionRequired":{"properties":{"code":{"const":"subscription_required","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["This household's subscription has lapsed"]},"household_id":{"examples":["Hh4vK8pQ2sLm"],"title":"Household Id","type":"string"}},"required":["code","message","household_id"],"title":"SubscriptionRequired","type":"object"},"UpdateHouseholdRequestPatch":{"properties":{"name":{"examples":["Chen Household"],"maxLength":255,"title":"Name","type":"string"},"currency":{"allOf":[{"$ref":"#/components/schemas/Currency"}],"examples":["USD"]},"timezone":{"examples":["America/Los_Angeles"],"title":"Timezone","type":"string"}},"title":"UpdateHouseholdRequestPatch","type":"object"},"HouseholdInviteItemResponse":{"properties":{"id":{"examples":["Iv8qM3cT6nRa"],"title":"Id","type":"string"},"email":{"format":"email","title":"Email","type":"string"},"role":{"$ref":"#/components/schemas/HouseholdRole"},"invited_by_email":{"format":"email","title":"Invited By Email","type":"string"},"expires_at":{"format":"date-time","title":"Expires At","type":"string"}},"required":["id","email","role","invited_by_email","expires_at"],"title":"HouseholdInviteItemResponse","type":"object"},"HouseholdMemberItemResponse":{"properties":{"id":{"examples":["Us2mH7qB5kLp"],"title":"Id","type":"string"},"name":{"examples":["Avery Chen"],"title":"Name","type":"string"},"email":{"format":"email","title":"Email","type":"string"},"role":{"$ref":"#/components/schemas/HouseholdRole"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/users/Us2mH7qB5kLp.png"],"title":"Image Url"},"joined_at":{"format":"date-time","title":"Joined At","type":"string"}},"required":["id","name","email","role","image_url","joined_at"],"title":"HouseholdMemberItemResponse","type":"object"},"HouseholdMembersResponse":{"properties":{"members":{"items":{"$ref":"#/components/schemas/HouseholdMemberItemResponse"},"title":"Members","type":"array"},"invited":{"items":{"$ref":"#/components/schemas/HouseholdInviteItemResponse"},"title":"Invited","type":"array"}},"required":["members","invited"],"title":"HouseholdMembersResponse","type":"object"},"HouseholdPreferencesPatch":{"properties":{"show_recurring_suggestions":{"title":"Show Recurring Suggestions","type":"boolean"},"show_advanced_details":{"title":"Show Advanced Details","type":"boolean"}},"title":"HouseholdPreferencesPatch","type":"object"},"MerchantResponse":{"properties":{"id":{"examples":["Mr9dL3xT6bQa"],"title":"Id","type":"string"},"name":{"examples":["Blue Bottle Coffee"],"title":"Name","type":"string"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://www.bluebottlecoffee.com/"],"title":"Website"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/merchants/blue-bottle-coffee.png"],"title":"Image Url"},"default_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/merchants/default-coffee.png"],"title":"Default Image Url"},"transaction_count":{"examples":[18],"title":"Transaction Count","type":"integer"},"recurring_transaction_count":{"examples":[1],"title":"Recurring Transaction Count","type":"integer"}},"required":["id","name","website","image_url","default_image_url","transaction_count","recurring_transaction_count"],"title":"MerchantResponse","type":"object"},"DuplicateName":{"properties":{"code":{"const":"duplicate_name","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["This name is already in use"]}},"required":["code","message"],"title":"DuplicateName","type":"object"},"MerchantRequest":{"properties":{"name":{"examples":["Blue Bottle Coffee"],"maxLength":255,"title":"Name","type":"string"},"website":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"examples":["https://www.bluebottlecoffee.com/"],"title":"Website"}},"required":["name"],"title":"MerchantRequest","type":"object"},"MerchantListResponse":{"properties":{"merchants":{"items":{"$ref":"#/components/schemas/MerchantResponse"},"title":"Merchants","type":"array"}},"required":["merchants"],"title":"MerchantListResponse","type":"object"},"MerchantNotFound":{"properties":{"code":{"const":"merchant_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Merchant not found"]}},"required":["code","message"],"title":"MerchantNotFound","type":"object"},"AccountProvider":{"enum":["plaid","manual","financekit","apple"],"title":"AccountProvider","type":"string"},"InstitutionConnectionStatus":{"properties":{"id":{"examples":["ins_109508"],"title":"Id","type":"string"},"provider":{"$ref":"#/components/schemas/AccountProvider","examples":["plaid"]},"name":{"examples":["Chase"],"title":"Name","type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://www.chase.com/"],"title":"Url"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/institutions/chase.png"],"title":"Image Url"},"primary_color":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["#117ACA"],"title":"Primary Color"},"popularity_rank":{"anyOf":[{"maximum":30,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Ordinal rank among the top 30 Plaid institutions from Monarch's public popularity order, captured September 14, 2026. Not a Penny usage metric. Null for Apple and institutions outside that snapshot.","examples":[1],"title":"Popularity Rank"},"success":{"anyOf":[{"maximum":100,"minimum":0,"type":"number"},{"type":"null"}],"description":"Login success percentage: reported by Plaid, or fixed at 100 for Apple. Plaid data is null when unavailable or stale.","examples":[98.5],"title":"Success"},"success_checked_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Success Checked At"},"notices":{"items":{"$ref":"#/components/schemas/InstitutionNotice"},"title":"Notices","type":"array"}},"required":["id","provider","name","url","image_url","primary_color","popularity_rank","success","success_checked_at","notices"],"title":"InstitutionConnectionStatus","type":"object"},"InstitutionNotice":{"properties":{"title":{"examples":["Discover Migration to Capital One"],"title":"Title","type":"string"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Migrated accounts need to reconnect."],"title":"Description"},"status":{"enum":["investigating","identified","scheduled","unknown"],"title":"Status","type":"string"},"starts_at":{"format":"date-time","title":"Starts At","type":"string"},"updated_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Updated At"}},"required":["title","description","status","starts_at","updated_at"],"title":"InstitutionNotice","type":"object"},"PaginatedConnectionStatusResponse":{"properties":{"institutions":{"items":{"$ref":"#/components/schemas/InstitutionConnectionStatus"},"title":"Institutions","type":"array"},"has_success_data":{"title":"Has Success Data","type":"boolean"},"total":{"examples":[10131],"title":"Total","type":"integer"},"limit":{"examples":[20],"title":"Limit","type":"integer"},"offset":{"examples":[0],"title":"Offset","type":"integer"},"has_more":{"title":"Has More","type":"boolean"}},"required":["institutions","has_success_data","total","limit","offset","has_more"],"title":"PaginatedConnectionStatusResponse","type":"object"},"InstitutionResponse":{"properties":{"id":{"examples":["ins_109508"],"title":"Id","type":"string"},"provider":{"$ref":"#/components/schemas/AccountProvider","examples":["plaid"]},"name":{"examples":["Chase"],"title":"Name","type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://www.chase.com/"],"title":"Url"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/institutions/chase.png"],"title":"Image Url"},"primary_color":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["#117ACA"],"title":"Primary Color"},"popularity_rank":{"anyOf":[{"maximum":30,"minimum":1,"type":"integer"},{"type":"null"}],"description":"Ordinal rank among the top 30 Plaid institutions from Monarch's public popularity order, captured September 14, 2026. Not a Penny usage metric. Null for Apple and institutions outside that snapshot.","examples":[1],"title":"Popularity Rank"}},"required":["id","provider","name","url","image_url","primary_color","popularity_rank"],"title":"InstitutionResponse","type":"object"},"PaginatedInstitutionsResponse":{"properties":{"institutions":{"items":{"$ref":"#/components/schemas/InstitutionResponse"},"title":"Institutions","type":"array"},"total":{"examples":[12847],"title":"Total","type":"integer"},"limit":{"examples":[25],"title":"Limit","type":"integer"},"offset":{"examples":[25],"title":"Offset","type":"integer"},"has_more":{"title":"Has More","type":"boolean"}},"required":["institutions","total","limit","offset","has_more"],"title":"PaginatedInstitutionsResponse","type":"object"},"CuratedInstitutionsResponse":{"properties":{"institutions":{"items":{"$ref":"#/components/schemas/InstitutionResponse"},"title":"Institutions","type":"array"}},"required":["institutions"],"title":"CuratedInstitutionsResponse","type":"object"},"AccountGroup":{"properties":{"type":{"$ref":"#/components/schemas/AccountType","examples":["depository"]},"accounts":{"items":{"$ref":"#/components/schemas/FinancialAccountResponse"},"title":"Accounts","type":"array"},"total":{"$ref":"#/components/schemas/MoneySchema"}},"required":["type","accounts","total"],"title":"AccountGroup","type":"object"},"AccountType":{"enum":["investment","credit","depository","loan","brokerage","other"],"title":"AccountType","type":"string"},"FinancialAccountResponse":{"properties":{"id":{"examples":["Ac7kP2mN9qRs"],"title":"Id","type":"string"},"mask":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["4821"],"title":"Mask"},"name":{"examples":["Everyday Checking"],"title":"Name","type":"string"},"type":{"$ref":"#/components/schemas/AccountType","examples":["depository"]},"current_balance":{"anyOf":[{"$ref":"#/components/schemas/MoneySchema"},{"type":"null"}]},"currency":{"examples":["USD"],"title":"Currency","type":"string"},"household_id":{"examples":["Hh4vK8pQ2sLm"],"title":"Household Id","type":"string"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Daily spending"],"title":"User Name"},"provider":{"$ref":"#/components/schemas/AccountProvider","examples":["plaid"]},"transaction_count":{"examples":[184],"title":"Transaction Count","type":"integer"},"is_closed":{"examples":[false],"title":"Is Closed","type":"boolean"},"linked_at":{"format":"date-time","title":"Linked At","type":"string"},"last_synced_at":{"format":"date-time","title":"Last Synced At","type":"string"},"added_by_id":{"anyOf":[{"examples":["Us2mH7qB5kLp"],"type":"string"},{"type":"null"}],"title":"Added By Id"},"plaid":{"anyOf":[{"$ref":"#/components/schemas/PlaidInfo"},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/institutions/chase.png"],"title":"Image Url"},"default_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/accounts/checking.png"],"title":"Default Image Url"}},"required":["id","mask","name","type","current_balance","currency","household_id","user_name","provider","transaction_count","is_closed","linked_at","last_synced_at","added_by_id","plaid","image_url","default_image_url"],"title":"FinancialAccountResponse","type":"object"},"GroupedAccountsResponse":{"properties":{"groups":{"items":{"$ref":"#/components/schemas/AccountGroup"},"title":"Groups","type":"array"},"total_balance":{"$ref":"#/components/schemas/MoneySchema"}},"required":["groups","total_balance"],"title":"GroupedAccountsResponse","type":"object"},"MoneySchema":{"properties":{"amount":{"examples":["68.42"],"title":"Amount","type":"string"},"currency":{"examples":["USD"],"title":"Currency","type":"string"}},"required":["amount","currency"],"title":"MoneySchema","type":"object"},"PlaidConnectionStatus":{"enum":["healthy","needs_update","pending_expiration","pending_disconnect","revoked"],"title":"PlaidConnectionStatus","type":"string"},"PlaidInfo":{"properties":{"item_id":{"examples":["item_sandbox_8d4f1c2a"],"title":"Item Id","type":"string"},"connection_status":{"$ref":"#/components/schemas/PlaidConnectionStatus"},"error_code":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["ITEM_LOGIN_REQUIRED"],"title":"Error Code"}},"required":["item_id","connection_status","error_code"],"title":"PlaidInfo","type":"object"},"DeletedAccountsResponse":{"properties":{"accounts":{"items":{"$ref":"#/components/schemas/FinancialAccountResponse"},"title":"Accounts","type":"array"}},"required":["accounts"],"title":"DeletedAccountsResponse","type":"object"},"AccountNotFound":{"properties":{"code":{"const":"account_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Account not found"]}},"required":["code","message"],"title":"AccountNotFound","type":"object"},"UpdateAccountRequest":{"description":"Replaces the account name override; omitted or null user_name clears it.","properties":{"user_name":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"examples":["Daily spending"],"title":"User Name"}},"title":"UpdateAccountRequest","type":"object"},"CloseAccountRequest":{"properties":{"closed_at":{"format":"date","title":"Closed At","type":"string"}},"required":["closed_at"],"title":"CloseAccountRequest","type":"object"},"AccountBalance":{"properties":{"account_id":{"examples":["Ac7kP2mN9qRs"],"title":"Account Id","type":"string"},"balance":{"$ref":"#/components/schemas/MoneySchema"},"is_interpolated":{"title":"Is Interpolated","type":"boolean"}},"required":["account_id","balance","is_interpolated"],"title":"AccountBalance","type":"object"},"AccountEvent":{"properties":{"date":{"format":"date","title":"Date","type":"string"},"account_id":{"examples":["Ac7kP2mN9qRs"],"title":"Account Id","type":"string"},"account_name":{"examples":["Everyday Checking"],"title":"Account Name","type":"string"},"type":{"$ref":"#/components/schemas/AccountEventType"}},"required":["date","account_id","account_name","type"],"title":"AccountEvent","type":"object"},"AccountEventType":{"enum":["first_balance","account_closed"],"title":"AccountEventType","type":"string"},"DailyBalance":{"properties":{"date":{"format":"date","title":"Date","type":"string"},"balance":{"$ref":"#/components/schemas/MoneySchema"},"accounts":{"items":{"$ref":"#/components/schemas/AccountBalance"},"title":"Accounts","type":"array"}},"required":["date","balance","accounts"],"title":"DailyBalance","type":"object"},"HistoricalBalancesResponse":{"properties":{"balances":{"items":{"$ref":"#/components/schemas/DailyBalance"},"title":"Balances","type":"array"},"events":{"items":{"$ref":"#/components/schemas/AccountEvent"},"title":"Events","type":"array"}},"required":["balances","events"],"title":"HistoricalBalancesResponse","type":"object"},"TagResponse":{"properties":{"id":{"examples":["Tg8qN1cK5rWd"],"title":"Id","type":"string"},"name":{"examples":["Work meals"],"title":"Name","type":"string"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["#6D5BD0"],"title":"Color"},"transaction_count":{"examples":[12],"title":"Transaction Count","type":"integer"}},"required":["id","name","color","transaction_count"],"title":"TagResponse","type":"object"},"TagRequest":{"properties":{"name":{"examples":["Work meals"],"maxLength":255,"title":"Name","type":"string"},"color":{"anyOf":[{"maxLength":7,"type":"string"},{"type":"null"}],"examples":["#6D5BD0"],"title":"Color"}},"required":["name"],"title":"TagRequest","type":"object"},"TagListResponse":{"properties":{"tags":{"items":{"$ref":"#/components/schemas/TagResponse"},"title":"Tags","type":"array"}},"required":["tags"],"title":"TagListResponse","type":"object"},"TagNotFound":{"properties":{"code":{"const":"tag_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Tag not found"]}},"required":["code","message"],"title":"TagNotFound","type":"object"},"AmountFilterResponse":{"properties":{"direction":{"$ref":"#/components/schemas/TransactionDirection"},"operator":{"$ref":"#/components/schemas/AmountOperator"},"value":{"examples":["68.42"],"title":"Value","type":"string"},"value_upper":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"examples":["100.00"],"title":"Value Upper"}},"required":["direction","operator","value","value_upper"],"title":"AmountFilterResponse","type":"object"},"AmountOperator":{"enum":["equals","greater_than","less_than","greater_than_or_equal","less_than_or_equal","between"],"title":"AmountOperator","type":"string"},"NameCondition":{"properties":{"pattern":{"examples":["BLUE BOTTLE"],"minLength":1,"title":"Pattern","type":"string"},"mode":{"$ref":"#/components/schemas/NameMatchMode"}},"required":["pattern","mode"],"title":"NameCondition","type":"object"},"NameMatchMode":{"enum":["contains","exact"],"title":"NameMatchMode","type":"string"},"PennyDetailedCategory":{"enum":["RENT_AND_UTILITIES_RENT","RENT_AND_UTILITIES_GAS_AND_ELECTRICITY","RENT_AND_UTILITIES_INTERNET_AND_CABLE","RENT_AND_UTILITIES_SEWAGE_AND_WASTE_MANAGEMENT","RENT_AND_UTILITIES_TELEPHONE","RENT_AND_UTILITIES_WATER","RENT_AND_UTILITIES_OTHER_UTILITIES","TRANSPORTATION_GAS","TRANSPORTATION_PUBLIC_TRANSIT","TRANSPORTATION_TAXIS_AND_RIDE_SHARES","TRANSPORTATION_TOLLS","TRANSPORTATION_PARKING","TRANSPORTATION_OTHER_TRANSPORTATION","FOOD_AND_DRINK_RESTAURANT","FOOD_AND_DRINK_FAST_FOOD","FOOD_AND_DRINK_COFFEE","FOOD_AND_DRINK_GROCERIES","FOOD_AND_DRINK_BEER_WINE_AND_LIQUOR","FOOD_AND_DRINK_OTHER_FOOD_AND_DRINK","MEDICAL_DENTAL_CARE","MEDICAL_EYE_CARE","MEDICAL_PRIMARY_CARE","MEDICAL_PHARMACIES_AND_SUPPLEMENTS","MEDICAL_VETERINARY_SERVICES","MEDICAL_NURSING_CARE","MEDICAL_OTHER_MEDICAL","ENTERTAINMENT_TV_AND_MOVIES","ENTERTAINMENT_VIDEO_GAMES","ENTERTAINMENT_SPORTING_EVENTS_AMUSEMENT_PARKS_AND_MUSEUMS","ENTERTAINMENT_MUSIC_AND_AUDIO","ENTERTAINMENT_CASINOS_AND_GAMBLING","ENTERTAINMENT_OTHER_ENTERTAINMENT","TRAVEL_FLIGHTS","TRAVEL_LODGING","TRAVEL_RENTAL_CARS","TRAVEL_OTHER_TRAVEL","GENERAL_MERCHANDISE_PET_SUPPLIES","GENERAL_MERCHANDISE_CLOTHING_AND_ACCESSORIES","GENERAL_MERCHANDISE_ONLINE_MARKETPLACES","GENERAL_MERCHANDISE_DEPARTMENT_STORES","GENERAL_MERCHANDISE_DISCOUNT_STORES","GENERAL_MERCHANDISE_SPORTING_GOODS","GENERAL_MERCHANDISE_ELECTRONICS","GENERAL_MERCHANDISE_BOOKSTORES_AND_NEWSSTANDS","GENERAL_MERCHANDISE_GIFTS_AND_NOVELTIES","GENERAL_MERCHANDISE_OFFICE_SUPPLIES","GENERAL_MERCHANDISE_TOBACCO_AND_VAPE","GENERAL_MERCHANDISE_SUPERSTORES","GENERAL_MERCHANDISE_CONVENIENCE_STORES","GENERAL_MERCHANDISE_OTHER_GENERAL_MERCHANDISE","PERSONAL_CARE_HAIR_AND_BEAUTY","PERSONAL_CARE_GYMS_AND_FITNESS_CENTERS","PERSONAL_CARE_LAUNDRY_AND_DRY_CLEANING","PERSONAL_CARE_OTHER_PERSONAL_CARE","INCOME_SALARY","INCOME_CONTRACTOR","INCOME_GIG_ECONOMY","INCOME_MILITARY","INCOME_DIVIDENDS","INCOME_INTEREST_EARNED","INCOME_RETIREMENT_PENSION","INCOME_TAX_REFUND","INCOME_UNEMPLOYMENT","INCOME_LONG_TERM_DISABILITY","INCOME_CHILD_SUPPORT","INCOME_RENTAL","INCOME_OTHER","TRANSFER_IN_DEPOSIT","TRANSFER_IN_INVESTMENT_AND_RETIREMENT_FUNDS","TRANSFER_IN_SAVINGS","TRANSFER_IN_ACCOUNT_TRANSFER","TRANSFER_IN_WIRE","TRANSFER_IN_TRANSFER_IN_FROM_APPS","TRANSFER_IN_OTHER_TRANSFER_IN","TRANSFER_OUT_WITHDRAWAL","TRANSFER_OUT_INVESTMENT_AND_RETIREMENT_FUNDS","TRANSFER_OUT_SAVINGS","TRANSFER_OUT_ACCOUNT_TRANSFER","TRANSFER_OUT_WIRE","TRANSFER_OUT_CRYPTO","TRANSFER_OUT_TRANSFER_OUT_FROM_APPS","TRANSFER_OUT_OTHER_TRANSFER_OUT","LOAN_DISBURSEMENTS_AUTO","LOAN_DISBURSEMENTS_CASH_ADVANCES","LOAN_DISBURSEMENTS_EWA","LOAN_DISBURSEMENTS_MORTGAGE","LOAN_DISBURSEMENTS_PERSONAL","LOAN_DISBURSEMENTS_STUDENT","LOAN_DISBURSEMENTS_OTHER_DISBURSEMENT","LOAN_PAYMENTS_CREDIT_CARD_PAYMENT","LOAN_PAYMENTS_CAR_PAYMENT","LOAN_PAYMENTS_MORTGAGE_PAYMENT","LOAN_PAYMENTS_STUDENT_LOAN_PAYMENT","LOAN_PAYMENTS_PERSONAL_LOAN_PAYMENT","LOAN_PAYMENTS_BNPL","LOAN_PAYMENTS_CASH_ADVANCES","LOAN_PAYMENTS_EWA","LOAN_PAYMENTS_OTHER_PAYMENT","BANK_FEES_ATM_FEES","BANK_FEES_FOREIGN_TRANSACTION_FEES","BANK_FEES_INSUFFICIENT_FUNDS","BANK_FEES_INTEREST_CHARGE","BANK_FEES_OVERDRAFT_FEES","BANK_FEES_LATE_FEES","BANK_FEES_CASH_ADVANCE","BANK_FEES_OTHER_BANK_FEES","GOVERNMENT_AND_NON_PROFIT_DONATIONS","GOVERNMENT_AND_NON_PROFIT_TAX_PAYMENT","GOVERNMENT_AND_NON_PROFIT_GOVERNMENT_DEPARTMENTS_AND_AGENCIES","GOVERNMENT_AND_NON_PROFIT_OTHER_GOVERNMENT_AND_NON_PROFIT","HOME_IMPROVEMENT_FURNITURE","HOME_IMPROVEMENT_HARDWARE","HOME_IMPROVEMENT_REPAIR_AND_MAINTENANCE","HOME_IMPROVEMENT_OTHER_HOME_IMPROVEMENT","GENERAL_SERVICES_ACCOUNTING_AND_FINANCIAL_PLANNING","GENERAL_SERVICES_AUTOMOTIVE","GENERAL_SERVICES_CHILDCARE","GENERAL_SERVICES_CONSULTING_AND_LEGAL","GENERAL_SERVICES_EDUCATION","GENERAL_SERVICES_INSURANCE","GENERAL_SERVICES_POSTAGE_AND_SHIPPING","GENERAL_SERVICES_STORAGE","GENERAL_SERVICES_OTHER_GENERAL_SERVICES"],"title":"PennyDetailedCategory","type":"string"},"RuleResponse":{"properties":{"id":{"examples":["Rl9cF3nV7sQa"],"title":"Id","type":"string"},"priority":{"examples":[1],"title":"Priority","type":"integer"},"account_ids":{"anyOf":[{"items":{"examples":["Ac7kP2mN9qRs"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"merchant_ids":{"anyOf":[{"items":{"examples":["Mr9dL3xT6bQa"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Merchant Ids"},"category_ids":{"anyOf":[{"items":{"examples":["Ct5nR8wY1jFu"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Ids"},"amount_filter":{"anyOf":[{"$ref":"#/components/schemas/AmountFilterResponse"},{"type":"null"}]},"penny_detailed_categories":{"anyOf":[{"items":{"$ref":"#/components/schemas/PennyDetailedCategory"},"type":"array"},{"type":"null"}],"title":"Penny Detailed Categories"},"name_conditions":{"anyOf":[{"items":{"$ref":"#/components/schemas/NameCondition"},"type":"array"},{"type":"null"}],"title":"Name Conditions"},"filter_uncategorized":{"title":"Filter Uncategorized","type":"boolean"},"set_category_id":{"anyOf":[{"examples":["Ct5nR8wY1jFu"],"type":"string"},{"type":"null"}],"title":"Set Category Id"},"set_merchant_id":{"anyOf":[{"examples":["Mr9dL3xT6bQa"],"type":"string"},{"type":"null"}],"title":"Set Merchant Id"},"apply_tag_ids":{"items":{"examples":["Tg8qN1cK5rWd"],"type":"string"},"title":"Apply Tag Ids","type":"array"},"set_hidden":{"title":"Set Hidden","type":"boolean"},"set_needs_review":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Set Needs Review"},"applied_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"examples":[18],"title":"Applied Count"}},"required":["id","priority","account_ids","merchant_ids","category_ids","amount_filter","penny_detailed_categories","name_conditions","filter_uncategorized","set_category_id","set_merchant_id","apply_tag_ids","set_hidden","set_needs_review","applied_count"],"title":"RuleResponse","type":"object"},"TransactionDirection":{"description":"Which side of the ledger an amount falls on.\n\nShared by categorization-rule amount filters and recurring-transaction\ntypes, which are the same income/expense distinction under two names.","enum":["income","expense"],"title":"TransactionDirection","type":"string"},"CategoryNotFound":{"properties":{"code":{"const":"category_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Category not found"]}},"required":["code","message"],"title":"CategoryNotFound","type":"object"},"RuleNotFound":{"properties":{"code":{"const":"rule_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Rule not found"]}},"required":["code","message"],"title":"RuleNotFound","type":"object"},"AmountFilter":{"properties":{"direction":{"$ref":"#/components/schemas/TransactionDirection"},"operator":{"$ref":"#/components/schemas/AmountOperator"},"value":{"examples":["68.42"],"title":"Value","type":"string"},"value_upper":{"anyOf":[{"examples":["68.42"],"type":"string"},{"type":"null"}],"examples":["100.00"],"title":"Value Upper"}},"required":["direction","operator","value"],"title":"AmountFilter","type":"object"},"RuleRequest":{"properties":{"filter_uncategorized":{"default":false,"title":"Filter Uncategorized","type":"boolean"},"account_ids":{"anyOf":[{"items":{"examples":["Ac7kP2mN9qRs"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"merchant_ids":{"anyOf":[{"items":{"examples":["Mr9dL3xT6bQa"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Merchant Ids"},"category_ids":{"anyOf":[{"items":{"examples":["Ct5nR8wY1jFu"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Ids"},"amount_filter":{"anyOf":[{"$ref":"#/components/schemas/AmountFilter"},{"type":"null"}]},"penny_detailed_categories":{"anyOf":[{"items":{"$ref":"#/components/schemas/PennyDetailedCategory"},"type":"array"},{"type":"null"}],"title":"Penny Detailed Categories"},"name_conditions":{"anyOf":[{"items":{"$ref":"#/components/schemas/NameCondition"},"type":"array"},{"type":"null"}],"title":"Name Conditions"},"set_category_id":{"anyOf":[{"examples":["Ct5nR8wY1jFu"],"type":"string"},{"type":"null"}],"title":"Set Category Id"},"set_merchant_id":{"anyOf":[{"examples":["Mr9dL3xT6bQa"],"type":"string"},{"type":"null"}],"title":"Set Merchant Id"},"apply_tag_ids":{"anyOf":[{"items":{"examples":["Tg8qN1cK5rWd"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Apply Tag Ids"},"set_hidden":{"default":false,"title":"Set Hidden","type":"boolean"},"set_needs_review":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Set Needs Review"},"apply_to_existing":{"default":false,"title":"Apply To Existing","type":"boolean"}},"title":"RuleRequest","type":"object"},"RuleListResponse":{"properties":{"rules":{"items":{"$ref":"#/components/schemas/RuleResponse"},"title":"Rules","type":"array"}},"required":["rules"],"title":"RuleListResponse","type":"object"},"InvalidRuleIds":{"properties":{"code":{"const":"invalid_rule_ids","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Rule IDs must match exactly all rules in the household"]}},"required":["code","message"],"title":"InvalidRuleIds","type":"object"},"ReorderRulesRequest":{"properties":{"rule_ids":{"items":{"examples":["Rl9cF3nV7sQa"],"type":"string"},"title":"Rule Ids","type":"array"}},"required":["rule_ids"],"title":"ReorderRulesRequest","type":"object"},"AccountSummaryResponse":{"properties":{"id":{"examples":["Ac7kP2mN9qRs"],"title":"Id","type":"string"},"mask":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["4821"],"title":"Mask"},"name":{"examples":["Everyday Checking"],"title":"Name","type":"string"},"type":{"$ref":"#/components/schemas/AccountType","examples":["depository"]},"current_balance":{"anyOf":[{"$ref":"#/components/schemas/MoneySchema"},{"type":"null"}]},"currency":{"examples":["USD"],"title":"Currency","type":"string"},"household_id":{"examples":["Hh4vK8pQ2sLm"],"title":"Household Id","type":"string"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Daily spending"],"title":"User Name"}},"required":["id","mask","name","type","current_balance","currency","household_id","user_name"],"title":"AccountSummaryResponse","type":"object"},"CategoryResponse":{"properties":{"id":{"examples":["Ct5nR8wY1jFu"],"title":"Id","type":"string"},"name":{"examples":["Coffee & Dining"],"title":"Name","type":"string"},"emoji":{"examples":["☕️"],"title":"Emoji","type":"string"},"category_type":{"$ref":"#/components/schemas/CategoryType"},"group_id":{"anyOf":[{"examples":["Cg2mV7pL4zXe"],"type":"string"},{"type":"null"}],"title":"Group Id"}},"required":["id","name","emoji","category_type","group_id"],"title":"CategoryResponse","type":"object"},"CategoryType":{"enum":["income","transfer","expense"],"title":"CategoryType","type":"string"},"DailySumResponse":{"properties":{"date":{"format":"date","title":"Date","type":"string"},"amount":{"$ref":"#/components/schemas/MoneySchema"}},"required":["date","amount"],"title":"DailySumResponse","type":"object"},"DryRunResponse":{"properties":{"matched_count":{"examples":[18],"title":"Matched Count","type":"integer"},"total_transactions":{"examples":[436],"title":"Total Transactions","type":"integer"},"matches":{"items":{"$ref":"#/components/schemas/ListTransactionResponse"},"title":"Matches","type":"array"},"daily_sums":{"items":{"$ref":"#/components/schemas/DailySumResponse"},"title":"Daily Sums","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["eyJkYXRlIjoiMjAyNi0wOC0xMyIsImlkIjoiVHg4YVEya0w1blJlIn0"],"title":"Next Cursor"},"has_more":{"title":"Has More","type":"boolean"}},"required":["matched_count","total_transactions","matches","daily_sums","next_cursor","has_more"],"title":"DryRunResponse","type":"object"},"ListTransactionResponse":{"properties":{"id":{"examples":["Tx3fJ9mS6vBa"],"title":"Id","type":"string"},"original_name":{"examples":["BLUE BOTTLE COFFEE #047"],"title":"Original Name","type":"string"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Morning coffee"],"title":"User Name"},"amount":{"$ref":"#/components/schemas/MoneySchema"},"native_amount":{"$ref":"#/components/schemas/MoneySchema"},"lat":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[37.7764],"title":"Lat"},"lon":{"anyOf":[{"type":"number"},{"type":"null"}],"examples":[-122.4231],"title":"Lon"},"pending":{"examples":[false],"title":"Pending","type":"boolean"},"penny_taxonomy":{"anyOf":[{"$ref":"#/components/schemas/PennyDetailedCategory"},{"type":"null"}],"examples":["FOOD_AND_DRINK_COFFEE"]},"account":{"$ref":"#/components/schemas/AccountSummaryResponse"},"household_finance_category":{"anyOf":[{"$ref":"#/components/schemas/CategoryResponse"},{"type":"null"}]},"merchant":{"anyOf":[{"$ref":"#/components/schemas/MerchantWithTransactionCountResponse"},{"type":"null"}]},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/merchants/blue-bottle-coffee.png"],"title":"Image Url"},"image_kind":{"$ref":"#/components/schemas/TransactionImageKind"},"tags":{"items":{"$ref":"#/components/schemas/TagSummaryResponse"},"title":"Tags","type":"array"},"is_deleted":{"examples":[false],"title":"Is Deleted","type":"boolean"},"is_hidden":{"examples":[false],"title":"Is Hidden","type":"boolean"},"pending_transaction_id":{"anyOf":[{"examples":["Tx3fJ9mS6vBa"],"type":"string"},{"type":"null"}],"title":"Pending Transaction Id"},"date":{"format":"date","title":"Date","type":"string"},"need_review":{"examples":[false],"title":"Need Review","type":"boolean"},"possible_duplicate_ids":{"items":{"examples":["Tx3fJ9mS6vBa"],"type":"string"},"title":"Possible Duplicate Ids","type":"array"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee with Sam before work"],"title":"Notes"},"created_at":{"format":"date-time","title":"Created At","type":"string"},"updated_at":{"format":"date-time","title":"Updated At","type":"string"},"name":{"examples":["Morning coffee"],"title":"Name","type":"string"},"split_from_transaction_id":{"anyOf":[{"examples":["Tx3fJ9mS6vBa"],"type":"string"},{"type":"null"}],"title":"Split From Transaction Id"},"split_child_ids":{"items":{"examples":["Tx3fJ9mS6vBa"],"type":"string"},"title":"Split Child Ids","type":"array"},"is_recurring":{"examples":[false],"title":"Is Recurring","type":"boolean"}},"required":["id","original_name","user_name","amount","native_amount","lat","lon","pending","penny_taxonomy","account","household_finance_category","merchant","image_url","image_kind","tags","is_deleted","is_hidden","pending_transaction_id","date","need_review","possible_duplicate_ids","notes","created_at","updated_at","name","split_from_transaction_id","split_child_ids","is_recurring"],"title":"ListTransactionResponse","type":"object"},"MerchantWithTransactionCountResponse":{"properties":{"id":{"examples":["Mr9dL3xT6bQa"],"title":"Id","type":"string"},"name":{"examples":["Blue Bottle Coffee"],"title":"Name","type":"string"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://www.bluebottlecoffee.com/"],"title":"Website"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/merchants/blue-bottle-coffee.png"],"title":"Image Url"},"default_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/merchants/default-coffee.png"],"title":"Default Image Url"},"transaction_count":{"examples":[18],"title":"Transaction Count","type":"integer"}},"required":["id","name","website","image_url","default_image_url","transaction_count"],"title":"MerchantWithTransactionCountResponse","type":"object"},"TagSummaryResponse":{"properties":{"id":{"examples":["Tg8qN1cK5rWd"],"title":"Id","type":"string"},"name":{"examples":["Work meals"],"title":"Name","type":"string"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["#6D5BD0"],"title":"Color"}},"required":["id","name","color"],"title":"TagSummaryResponse","type":"object"},"TransactionImageKind":{"enum":["merchant","account"],"title":"TransactionImageKind","type":"string"},"FiltersChanged":{"properties":{"code":{"const":"filters_changed","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Filters have changed since the cursor was created. Please start a new query."]}},"required":["code","message"],"title":"FiltersChanged","type":"object"},"InvalidCursor":{"properties":{"code":{"const":"invalid_cursor","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Invalid pagination cursor. Please start a new query."]}},"required":["code","message"],"title":"InvalidCursor","type":"object"},"DryRunRequest":{"properties":{"filter_uncategorized":{"default":false,"title":"Filter Uncategorized","type":"boolean"},"account_ids":{"anyOf":[{"items":{"examples":["Ac7kP2mN9qRs"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Account Ids"},"merchant_ids":{"anyOf":[{"items":{"examples":["Mr9dL3xT6bQa"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Merchant Ids"},"category_ids":{"anyOf":[{"items":{"examples":["Ct5nR8wY1jFu"],"type":"string"},"type":"array"},{"type":"null"}],"title":"Category Ids"},"amount_filter":{"anyOf":[{"$ref":"#/components/schemas/AmountFilter"},{"type":"null"}]},"penny_detailed_categories":{"anyOf":[{"items":{"$ref":"#/components/schemas/PennyDetailedCategory"},"type":"array"},{"type":"null"}],"title":"Penny Detailed Categories"},"name_conditions":{"anyOf":[{"items":{"$ref":"#/components/schemas/NameCondition"},"type":"array"},{"type":"null"}],"title":"Name Conditions"},"cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["eyJkYXRlIjoiMjAyNi0wOC0xNCIsImlkIjoiVHgzZko5bVM2dkJhIn0"],"title":"Cursor"},"min_limit":{"default":50,"maximum":200,"minimum":1,"title":"Min Limit","type":"integer"}},"title":"DryRunRequest","type":"object"},"AccumulatedSpendingResponse":{"properties":{"income":{"$ref":"#/components/schemas/SpendingSideResponse"},"expenses":{"$ref":"#/components/schemas/SpendingSideResponse"}},"required":["income","expenses"],"title":"AccumulatedSpendingResponse","type":"object"},"SpendingCategoryBreakdownResponse":{"properties":{"category_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Ct5nR8wY1jFu"],"title":"Category Id"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee & Dining"],"title":"Category Name"},"total":{"$ref":"#/components/schemas/MoneySchema"},"count":{"examples":[18],"title":"Count","type":"integer"},"emoji":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["☕️"],"title":"Emoji"}},"required":["category_id","category_name","total","count","emoji"],"title":"SpendingCategoryBreakdownResponse","type":"object"},"SpendingSideResponse":{"properties":{"total":{"$ref":"#/components/schemas/MoneySchema"},"count":{"examples":[42],"title":"Count","type":"integer"},"category_breakdown":{"items":{"$ref":"#/components/schemas/SpendingCategoryBreakdownResponse"},"title":"Category Breakdown","type":"array"}},"required":["total","count","category_breakdown"],"title":"SpendingSideResponse","type":"object"},"SpendingByPeriodResponse":{"properties":{"periods":{"items":{"$ref":"#/components/schemas/SpendingPeriodResponse"},"title":"Periods","type":"array"}},"required":["periods"],"title":"SpendingByPeriodResponse","type":"object"},"SpendingPeriodResponse":{"properties":{"period":{"examples":["2026-08"],"title":"Period","type":"string"},"income":{"$ref":"#/components/schemas/SpendingSideResponse"},"expenses":{"$ref":"#/components/schemas/SpendingSideResponse"}},"required":["period","income","expenses"],"title":"SpendingPeriodResponse","type":"object"},"CashflowByPeriodResponse":{"properties":{"periods":{"items":{"$ref":"#/components/schemas/CashflowPeriodResponse"},"title":"Periods","type":"array"}},"required":["periods"],"title":"CashflowByPeriodResponse","type":"object"},"CashflowPeriodResponse":{"properties":{"start_date":{"format":"date","title":"Start Date","type":"string"},"end_date":{"format":"date","title":"End Date","type":"string"},"income":{"$ref":"#/components/schemas/MoneySchema"},"expenses":{"$ref":"#/components/schemas/MoneySchema"},"net":{"$ref":"#/components/schemas/MoneySchema"},"is_complete":{"title":"Is Complete","type":"boolean"}},"required":["start_date","end_date","income","expenses","net","is_complete"],"title":"CashflowPeriodResponse","type":"object"},"MerchantBreakdownResponse":{"properties":{"merchants":{"items":{"$ref":"#/components/schemas/MerchantItemResponse"},"title":"Merchants","type":"array"}},"required":["merchants"],"title":"MerchantBreakdownResponse","type":"object"},"MerchantItemResponse":{"properties":{"merchant_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Mr9dL3xT6bQa"],"title":"Merchant Id"},"merchant_name":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Blue Bottle Coffee"],"title":"Merchant Name"},"amount":{"$ref":"#/components/schemas/MoneySchema"},"transaction_count":{"examples":[18],"title":"Transaction Count","type":"integer"}},"required":["merchant_id","merchant_name","amount","transaction_count"],"title":"MerchantItemResponse","type":"object"},"CategoryItemResponse":{"properties":{"category_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Ct5nR8wY1jFu"],"title":"Category Id"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee & Dining"],"title":"Category Name"},"emoji":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["☕️"],"title":"Emoji"},"amount":{"$ref":"#/components/schemas/MoneySchema"},"percentage":{"examples":["68.42"],"title":"Percentage","type":"string"}},"required":["category_id","category_name","emoji","amount","percentage"],"title":"CategoryItemResponse","type":"object"},"FullCategoryBreakdownResponse":{"properties":{"income":{"$ref":"#/components/schemas/GroupTypeBreakdownResponse"},"expenses":{"$ref":"#/components/schemas/GroupTypeBreakdownResponse"},"start_date":{"format":"date","title":"Start Date","type":"string"},"end_date":{"format":"date","title":"End Date","type":"string"}},"required":["income","expenses","start_date","end_date"],"title":"FullCategoryBreakdownResponse","type":"object"},"GroupItemResponse":{"properties":{"group_id":{"examples":["Cg2mV7pL4zXe"],"title":"Group Id","type":"string"},"group_name":{"examples":["Everyday Expenses"],"title":"Group Name","type":"string"},"amount":{"$ref":"#/components/schemas/MoneySchema"},"percentage":{"examples":["68.42"],"title":"Percentage","type":"string"},"categories":{"items":{"$ref":"#/components/schemas/CategoryItemResponse"},"title":"Categories","type":"array"}},"required":["group_id","group_name","amount","percentage","categories"],"title":"GroupItemResponse","type":"object"},"GroupTypeBreakdownResponse":{"properties":{"group_type":{"$ref":"#/components/schemas/CategoryType"},"total":{"$ref":"#/components/schemas/MoneySchema"},"groups":{"items":{"$ref":"#/components/schemas/GroupItemResponse"},"title":"Groups","type":"array"},"uncategorized":{"items":{"$ref":"#/components/schemas/CategoryItemResponse"},"title":"Uncategorized","type":"array"}},"required":["group_type","total","groups","uncategorized"],"title":"GroupTypeBreakdownResponse","type":"object"},"CategoryGroupNotFound":{"properties":{"code":{"const":"category_group_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Category group not found"]}},"required":["code","message"],"title":"CategoryGroupNotFound","type":"object"},"CategoryDuplicateEmoji":{"properties":{"code":{"const":"duplicate_emoji","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Category with this emoji already exists"]}},"required":["code","message"],"title":"CategoryDuplicateEmoji","type":"object"},"UpsertCategoryRequest":{"description":"On PUT, replaces category details; omitted group_id clears the group.","properties":{"name":{"examples":["Coffee & Dining"],"maxLength":255,"title":"Name","type":"string"},"emoji":{"examples":["☕️"],"maxLength":50,"title":"Emoji","type":"string"},"category_type":{"$ref":"#/components/schemas/CategoryType"},"group_id":{"anyOf":[{"examples":["Cg2mV7pL4zXe"],"type":"string"},{"type":"null"}],"title":"Group Id"}},"required":["name","emoji","category_type"],"title":"UpsertCategoryRequest","type":"object"},"CategoriesListResponse":{"properties":{"categories":{"items":{"$ref":"#/components/schemas/CategoryResponse"},"title":"Categories","type":"array"},"groups":{"items":{"$ref":"#/components/schemas/CategoryGroupResponse"},"title":"Groups","type":"array"}},"required":["categories","groups"],"title":"CategoriesListResponse","type":"object"},"CategoryGroupResponse":{"properties":{"id":{"examples":["Cg2mV7pL4zXe"],"title":"Id","type":"string"},"name":{"examples":["Everyday Expenses"],"title":"Name","type":"string"},"group_type":{"$ref":"#/components/schemas/CategoryType"}},"required":["id","name","group_type"],"title":"CategoryGroupResponse","type":"object"},"CreateCategoryGroupRequest":{"properties":{"name":{"examples":["Everyday Expenses"],"maxLength":255,"title":"Name","type":"string"},"group_type":{"$ref":"#/components/schemas/CategoryType"}},"required":["name","group_type"],"title":"CreateCategoryGroupRequest","type":"object"},"UpdateCategoryGroupRequest":{"properties":{"name":{"examples":["Everyday Expenses"],"maxLength":255,"title":"Name","type":"string"}},"required":["name"],"title":"UpdateCategoryGroupRequest","type":"object"},"PaginatedTransactionsResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/ListTransactionResponse"},"title":"Transactions","type":"array"},"daily_sums":{"items":{"$ref":"#/components/schemas/DailySumResponse"},"title":"Daily Sums","type":"array"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["eyJkYXRlIjoiMjAyNi0wOC0xMyIsImlkIjoiVHg4YVEya0w1blJlIn0"],"title":"Next Cursor"},"has_more":{"title":"Has More","type":"boolean"}},"required":["transactions","daily_sums","next_cursor","has_more"],"title":"PaginatedTransactionsResponse","type":"object"},"AccountNotManual":{"properties":{"code":{"const":"account_not_manual","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Transactions can only be created for manually-added accounts."]}},"required":["code","message"],"title":"AccountNotManual","type":"object"},"CreateTransactionRequest":{"properties":{"account_id":{"examples":["Ac7kP2mN9qRs"],"title":"Account Id","type":"string"},"name":{"examples":["Blue Bottle Coffee"],"maxLength":255,"minLength":1,"title":"Name","type":"string"},"amount":{"examples":["68.42"],"title":"Amount","type":"string"},"date":{"format":"date","title":"Date","type":"string"},"household_finance_category_id":{"anyOf":[{"examples":["Ct5nR8wY1jFu"],"type":"string"},{"type":"null"}],"title":"Household Finance Category Id"},"merchant_id":{"anyOf":[{"examples":["Mr9dL3xT6bQa"],"type":"string"},{"type":"null"}],"title":"Merchant Id"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee with Sam before work"],"title":"Notes"},"tags":{"default":[],"items":{"examples":["Tg8qN1cK5rWd"],"type":"string"},"title":"Tags","type":"array"}},"required":["account_id","name","amount","date"],"title":"CreateTransactionRequest","type":"object"},"BulkTransactionsResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/ListTransactionResponse"},"title":"Transactions","type":"array"}},"required":["transactions"],"title":"BulkTransactionsResponse","type":"object"},"TransactionNotFound":{"properties":{"code":{"const":"transaction_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Transaction not found"]}},"required":["code","message"],"title":"TransactionNotFound","type":"object"},"BulkTransactionsRequest":{"properties":{"transaction_ids":{"items":{"examples":["Tx3fJ9mS6vBa"],"type":"string"},"maxItems":1000,"minItems":1,"title":"Transaction Ids","type":"array"}},"required":["transaction_ids"],"title":"BulkTransactionsRequest","type":"object"},"BulkAddTagsRequest":{"properties":{"transaction_ids":{"items":{"examples":["Tx3fJ9mS6vBa"],"type":"string"},"maxItems":1000,"minItems":1,"title":"Transaction Ids","type":"array"},"tag_ids":{"items":{"examples":["Tg8qN1cK5rWd"],"type":"string"},"maxItems":1000,"minItems":1,"title":"Tag Ids","type":"array"}},"required":["transaction_ids","tag_ids"],"title":"BulkAddTagsRequest","type":"object"},"BulkReviewRequest":{"properties":{"transaction_ids":{"items":{"examples":["Tx3fJ9mS6vBa"],"type":"string"},"maxItems":1000,"minItems":1,"title":"Transaction Ids","type":"array"},"need_review":{"title":"Need Review","type":"boolean"}},"required":["transaction_ids","need_review"],"title":"BulkReviewRequest","type":"object"},"BulkSetCategoryRequest":{"properties":{"transaction_ids":{"items":{"examples":["Tx3fJ9mS6vBa"],"type":"string"},"maxItems":1000,"minItems":1,"title":"Transaction Ids","type":"array"},"household_finance_category_id":{"anyOf":[{"examples":["Ct5nR8wY1jFu"],"type":"string"},{"type":"null"}],"title":"Household Finance Category Id"}},"required":["transaction_ids"],"title":"BulkSetCategoryRequest","type":"object"},"DuplicateGroupResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/ListTransactionResponse"},"title":"Transactions","type":"array"}},"required":["transactions"],"title":"DuplicateGroupResponse","type":"object"},"DuplicateGroupsResponse":{"properties":{"groups":{"items":{"$ref":"#/components/schemas/DuplicateGroupResponse"},"title":"Groups","type":"array"}},"required":["groups"],"title":"DuplicateGroupsResponse","type":"object"},"UpdateTransactionRequest":{"description":"Replaces editable details. Omitted nullable fields are cleared; date, tags and is_hidden are required.","properties":{"name":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"examples":["Morning coffee"],"title":"Name"},"household_finance_category_id":{"anyOf":[{"examples":["Ct5nR8wY1jFu"],"type":"string"},{"type":"null"}],"title":"Household Finance Category Id"},"merchant_id":{"anyOf":[{"examples":["Mr9dL3xT6bQa"],"type":"string"},{"type":"null"}],"title":"Merchant Id"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee with Sam before work"],"title":"Notes"},"date":{"format":"date","title":"Date","type":"string"},"tags":{"items":{"examples":["Tg8qN1cK5rWd"],"type":"string"},"title":"Tags","type":"array"},"is_hidden":{"description":"Required on PUT; send the desired visibility explicitly.","examples":[false],"title":"Is Hidden","type":"boolean"}},"required":["date","tags","is_hidden"],"title":"UpdateTransactionRequest","type":"object"},"DismissDuplicatesRequest":{"properties":{"transaction_ids":{"items":{"examples":["Tx3fJ9mS6vBa"],"type":"string"},"maxItems":1000,"title":"Transaction Ids","type":"array"}},"required":["transaction_ids"],"title":"DismissDuplicatesRequest","type":"object"},"ChangeSource":{"enum":["user","plaid","financekit","rules","system"],"title":"ChangeSource","type":"string"},"FieldChange":{"properties":{"field":{"examples":["household_finance_category"],"title":"Field","type":"string"},"before":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee Shops"],"title":"Before"},"after":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee & Dining"],"title":"After"},"before_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Ct3dM7qA9sXe"],"title":"Before Id"},"after_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Ct5nR8wY1jFu"],"title":"After Id"},"before_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["USD"],"title":"Before Currency"},"after_currency":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["CAD"],"title":"After Currency"}},"required":["field","before","after","before_id","after_id","before_currency","after_currency"],"title":"FieldChange","type":"object"},"HistoryType":{"enum":["created","updated","deleted"],"title":"HistoryType","type":"string"},"TransactionHistoryEntryResponse":{"properties":{"history_id":{"examples":["hist_7pLm3xQ9vK2d"],"title":"History Id","type":"string"},"history_date":{"format":"date-time","title":"History Date","type":"string"},"history_type":{"$ref":"#/components/schemas/HistoryType"},"change_source":{"anyOf":[{"$ref":"#/components/schemas/ChangeSource"},{"type":"null"}]},"change_source_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Us2mH7qB5kLp"],"title":"Change Source Id"},"action_id":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["8e394bc8-d5cc-4c48-a2fd-58c37c9838f6"],"title":"Action Id"},"initiated_by":{"anyOf":[{"$ref":"#/components/schemas/TransactionHistoryUserResponse"},{"type":"null"}]},"user":{"anyOf":[{"$ref":"#/components/schemas/TransactionHistoryUserResponse"},{"type":"null"}]},"rule":{"anyOf":[{"$ref":"#/components/schemas/TransactionHistoryRuleResponse"},{"type":"null"}]},"changes":{"items":{"$ref":"#/components/schemas/FieldChange"},"title":"Changes","type":"array"}},"required":["history_id","history_date","history_type","change_source","change_source_id","action_id","initiated_by","user","rule","changes"],"title":"TransactionHistoryEntryResponse","type":"object"},"TransactionHistoryResponse":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/TransactionHistoryEntryResponse"},"title":"Entries","type":"array"}},"required":["entries"],"title":"TransactionHistoryResponse","type":"object"},"TransactionHistoryRuleResponse":{"properties":{"id":{"examples":["Rl9cF3nV7sQa"],"title":"Id","type":"string"}},"required":["id"],"title":"TransactionHistoryRuleResponse","type":"object"},"TransactionHistoryUserResponse":{"properties":{"id":{"examples":["Us2mH7qB5kLp"],"title":"Id","type":"string"},"name":{"examples":["Avery Chen"],"title":"Name","type":"string"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/users/Us2mH7qB5kLp.png"],"title":"Image Url"}},"required":["id","name","image_url"],"title":"TransactionHistoryUserResponse","type":"object"},"ListSplitsResponse":{"properties":{"parent":{"$ref":"#/components/schemas/ListTransactionResponse"},"children":{"items":{"$ref":"#/components/schemas/ListTransactionResponse"},"title":"Children","type":"array"}},"required":["parent","children"],"title":"ListSplitsResponse","type":"object"},"TransactionNotSplit":{"properties":{"code":{"const":"transaction_not_split","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Transaction is not currently split."]}},"required":["code","message"],"title":"TransactionNotSplit","type":"object"},"SplitTransactionResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/ListTransactionResponse"},"title":"Transactions","type":"array"}},"required":["transactions"],"title":"SplitTransactionResponse","type":"object"},"SplitChildCannotSplit":{"properties":{"code":{"const":"child_cannot_split","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Cannot split a transaction that is already a child of another split."]}},"required":["code","message"],"title":"SplitChildCannotSplit","type":"object"},"SplitTransactionDeleted":{"properties":{"code":{"const":"transaction_deleted","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Cannot split a deleted transaction."]}},"required":["code","message"],"title":"SplitTransactionDeleted","type":"object"},"SplitTransactionPending":{"properties":{"code":{"const":"transaction_pending","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Cannot split a pending transaction."]}},"required":["code","message"],"title":"SplitTransactionPending","type":"object"},"SplitSignMismatch":{"properties":{"code":{"const":"split_sign_mismatch","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Each split's sign must match the original transaction."]}},"required":["code","message"],"title":"SplitSignMismatch","type":"object"},"SplitSumMismatch":{"properties":{"code":{"const":"sum_does_not_match_total","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["The sum of the split amounts must equal the original transaction amount."]}},"required":["code","message"],"title":"SplitSumMismatch","type":"object"},"SplitTooFew":{"properties":{"code":{"const":"too_few_splits","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["A split must contain at least two parts."]}},"required":["code","message"],"title":"SplitTooFew","type":"object"},"SplitZeroAmount":{"properties":{"code":{"const":"zero_amount_split","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Split amounts must not be zero."]}},"required":["code","message"],"title":"SplitZeroAmount","type":"object"},"SplitItemRequest":{"properties":{"amount":{"examples":["68.42"],"title":"Amount","type":"string"},"household_finance_category_id":{"anyOf":[{"examples":["Ct5nR8wY1jFu"],"type":"string"},{"type":"null"}],"title":"Household Finance Category Id"},"merchant_id":{"anyOf":[{"examples":["Mr9dL3xT6bQa"],"type":"string"},{"type":"null"}],"title":"Merchant Id"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["Coffee and pastry"],"title":"Notes"},"tag_ids":{"default":[],"items":{"examples":["Tg8qN1cK5rWd"],"type":"string"},"title":"Tag Ids","type":"array"},"date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Date"},"user_name":{"anyOf":[{"maxLength":255,"type":"string"},{"type":"null"}],"examples":["Coffee portion"],"title":"User Name"}},"required":["amount"],"title":"SplitItemRequest","type":"object"},"SplitTransactionRequest":{"properties":{"splits":{"items":{"$ref":"#/components/schemas/SplitItemRequest"},"maxItems":52,"title":"Splits","type":"array"}},"required":["splits"],"title":"SplitTransactionRequest","type":"object"},"UnsplitChildCannotUnsplit":{"properties":{"code":{"const":"child_cannot_unsplit","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Cannot unsplit a child of a split; pass the parent transaction id."]}},"required":["code","message"],"title":"UnsplitChildCannotUnsplit","type":"object"},"TransactionImageListResponse":{"properties":{"images":{"items":{"$ref":"#/components/schemas/TransactionImageResponse"},"title":"Images","type":"array"}},"required":["images"],"title":"TransactionImageListResponse","type":"object"},"TransactionImageResponse":{"properties":{"id":{"examples":["Im4nD8qR2sVk"],"title":"Id","type":"string"},"image_url":{"examples":["https://cdn.penny.finance/transactions/Tx3fJ9mS6vBa/receipt.png"],"title":"Image Url","type":"string"},"created_at":{"format":"date-time","title":"Created At","type":"string"}},"required":["id","image_url","created_at"],"title":"TransactionImageResponse","type":"object"},"ImageNotFound":{"properties":{"code":{"const":"image_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Image not found."]}},"required":["code","message"],"title":"ImageNotFound","type":"object"},"BulkDeleteTransactionImagesRequest":{"properties":{"image_ids":{"items":{"examples":["Im4nD8qR2sVk"],"type":"string"},"maxItems":1000,"minItems":1,"title":"Image Ids","type":"array"}},"required":["image_ids"],"title":"BulkDeleteTransactionImagesRequest","type":"object"},"MerchantSummaryResponse":{"properties":{"id":{"examples":["Mr9dL3xT6bQa"],"title":"Id","type":"string"},"name":{"examples":["Blue Bottle Coffee"],"title":"Name","type":"string"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://www.bluebottlecoffee.com/"],"title":"Website"},"image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/merchants/blue-bottle-coffee.png"],"title":"Image Url"},"default_image_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://cdn.penny.finance/merchants/default-coffee.png"],"title":"Default Image Url"}},"required":["id","name","website","image_url","default_image_url"],"title":"MerchantSummaryResponse","type":"object"},"RecurringFrequency":{"enum":["every_week","every_2_weeks","every_4_weeks","twice_monthly_1st_15th","twice_monthly_15th_last","every_month","every_2_months","every_3_months","every_4_months","every_6_months","every_year"],"title":"RecurringFrequency","type":"string"},"RecurringTransactionResponse":{"properties":{"id":{"examples":["Rt6wP4dM8xNc"],"title":"Id","type":"string"},"merchant":{"$ref":"#/components/schemas/MerchantSummaryResponse"},"name":{"examples":["Netflix"],"title":"Name","type":"string"},"amount":{"$ref":"#/components/schemas/MoneySchema"},"type":{"$ref":"#/components/schemas/TransactionDirection"},"frequency":{"$ref":"#/components/schemas/RecurringFrequency"},"start_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Start Date"},"status":{"$ref":"#/components/schemas/RecurringTransactionStatus"},"end_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"End Date"},"notes":{"examples":["Standard monthly plan"],"title":"Notes","type":"string"}},"required":["id","merchant","name","amount","type","frequency","start_date","status","end_date","notes"],"title":"RecurringTransactionResponse","type":"object"},"RecurringTransactionStatus":{"enum":["active","cancelled"],"title":"RecurringTransactionStatus","type":"string"},"InvalidFrequencyFields":{"properties":{"code":{"const":"invalid_frequency_fields","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Invalid frequency fields: twice-monthly frequencies must omit start_date; all other frequencies require start_date"]}},"required":["code","message"],"title":"InvalidFrequencyFields","type":"object"},"CreateRecurringTransactionRequest":{"properties":{"merchant_id":{"examples":["Mr9dL3xT6bQa"],"title":"Merchant Id","type":"string"},"name":{"examples":["Netflix"],"title":"Name","type":"string"},"amount":{"examples":["68.42"],"title":"Amount","type":"string"},"currency":{"anyOf":[{"$ref":"#/components/schemas/Currency","examples":["USD"]},{"type":"null"}],"description":"ISO 4217 currency code. Defaults to the household's currency on create. PUT requires an explicit currency."},"type":{"allOf":[{"$ref":"#/components/schemas/TransactionDirection"}],"default":"expense"},"frequency":{"$ref":"#/components/schemas/RecurringFrequency"},"start_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Start Date"},"notes":{"default":"","examples":["Standard monthly plan"],"title":"Notes","type":"string"}},"required":["merchant_id","name","amount","frequency"],"title":"CreateRecurringTransactionRequest","type":"object"},"RecurringTransactionListResponse":{"properties":{"recurring_transactions":{"items":{"$ref":"#/components/schemas/RecurringTransactionResponse"},"title":"Recurring Transactions","type":"array"}},"required":["recurring_transactions"],"title":"RecurringTransactionListResponse","type":"object"},"RecurringTransactionSummaryResponse":{"properties":{"total_recurring_expense":{"$ref":"#/components/schemas/MoneySchema"},"total_recurring_income":{"$ref":"#/components/schemas/MoneySchema"},"paid_expense":{"$ref":"#/components/schemas/MoneySchema"},"received_income":{"$ref":"#/components/schemas/MoneySchema"}},"required":["total_recurring_expense","total_recurring_income","paid_expense","received_income"],"title":"RecurringTransactionSummaryResponse","type":"object"},"InvalidMonthFormat":{"properties":{"code":{"const":"invalid_month_format","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["month must be in YYYY-MM format"]}},"required":["code","message"],"title":"InvalidMonthFormat","type":"object"},"OccurrenceStatus":{"enum":["paid","missed","upcoming"],"title":"OccurrenceStatus","type":"string"},"RecurringTransactionOccurrence":{"properties":{"recurring_transaction_id":{"examples":["Rt6wP4dM8xNc"],"title":"Recurring Transaction Id","type":"string"},"name":{"examples":["Netflix"],"title":"Name","type":"string"},"expected_date":{"format":"date","title":"Expected Date","type":"string"},"expected_amount":{"$ref":"#/components/schemas/MoneySchema"},"type":{"$ref":"#/components/schemas/TransactionDirection"},"status":{"$ref":"#/components/schemas/OccurrenceStatus"},"transaction_id":{"anyOf":[{"examples":["Tx3fJ9mS6vBa"],"type":"string"},{"type":"null"}],"title":"Transaction Id"},"transaction_amount":{"anyOf":[{"$ref":"#/components/schemas/MoneySchema"},{"type":"null"}]},"merchant":{"$ref":"#/components/schemas/MerchantSummaryResponse"}},"required":["recurring_transaction_id","name","expected_date","expected_amount","type","status","transaction_id","transaction_amount","merchant"],"title":"RecurringTransactionOccurrence","type":"object"},"RecurringTransactionOccurrenceListResponse":{"properties":{"occurrences":{"items":{"$ref":"#/components/schemas/RecurringTransactionOccurrence"},"title":"Occurrences","type":"array"}},"required":["occurrences"],"title":"RecurringTransactionOccurrenceListResponse","type":"object"},"RecurringTransactionNotFound":{"properties":{"code":{"const":"recurring_transaction_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Recurring transaction not found"]}},"required":["code","message"],"title":"RecurringTransactionNotFound","type":"object"},"RecurringTransactionSuggestion":{"properties":{"merchant":{"$ref":"#/components/schemas/MerchantSummaryResponse"},"suggested_name":{"examples":["Netflix"],"title":"Suggested Name","type":"string"},"suggested_amount":{"$ref":"#/components/schemas/MoneySchema"},"display_amount":{"$ref":"#/components/schemas/MoneySchema"},"suggested_type":{"$ref":"#/components/schemas/TransactionDirection"},"suggested_frequency":{"$ref":"#/components/schemas/RecurringFrequency"},"suggested_start_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Suggested Start Date"},"confidence":{"examples":[0.94],"title":"Confidence","type":"number"},"matching_transactions":{"items":{"$ref":"#/components/schemas/ListTransactionResponse"},"title":"Matching Transactions","type":"array"}},"required":["merchant","suggested_name","suggested_amount","display_amount","suggested_type","suggested_frequency","suggested_start_date","confidence","matching_transactions"],"title":"RecurringTransactionSuggestion","type":"object"},"RecurringTransactionSuggestionListResponse":{"properties":{"suggestions":{"items":{"$ref":"#/components/schemas/RecurringTransactionSuggestion"},"title":"Suggestions","type":"array"}},"required":["suggestions"],"title":"RecurringTransactionSuggestionListResponse","type":"object"},"DismissSuggestionAmount":{"properties":{"amount":{"examples":["68.42"],"title":"Amount","type":"string"},"currency":{"examples":["USD"],"title":"Currency","type":"string"}},"required":["amount","currency"],"title":"DismissSuggestionAmount","type":"object"},"DismissSuggestionRequest":{"properties":{"merchant_id":{"examples":["Mr9dL3xT6bQa"],"title":"Merchant Id","type":"string"},"amount":{"$ref":"#/components/schemas/DismissSuggestionAmount"},"frequency":{"$ref":"#/components/schemas/RecurringFrequency"}},"required":["merchant_id","amount","frequency"],"title":"DismissSuggestionRequest","type":"object"},"DismissedSuggestionNotFound":{"properties":{"code":{"const":"suggestion_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Dismissed suggestion not found"]}},"required":["code","message"],"title":"DismissedSuggestionNotFound","type":"object"},"UpdateRecurringTransactionRequest":{"description":"Replaces recurring details. Omitted start_date clears it; all other fields are required.","properties":{"merchant_id":{"examples":["Mr9dL3xT6bQa"],"title":"Merchant Id","type":"string"},"name":{"examples":["Netflix"],"title":"Name","type":"string"},"amount":{"examples":["68.42"],"title":"Amount","type":"string"},"currency":{"$ref":"#/components/schemas/Currency","description":"Required on PUT; send the desired currency explicitly.","examples":["USD"]},"type":{"$ref":"#/components/schemas/TransactionDirection"},"frequency":{"$ref":"#/components/schemas/RecurringFrequency"},"start_date":{"anyOf":[{"format":"date","type":"string"},{"type":"null"}],"title":"Start Date"},"status":{"$ref":"#/components/schemas/RecurringTransactionStatus"},"notes":{"examples":["Standard monthly plan"],"title":"Notes","type":"string"}},"required":["merchant_id","name","amount","currency","type","frequency","status","notes"],"title":"UpdateRecurringTransactionRequest","type":"object"},"SecurityListResponse":{"properties":{"securities":{"items":{"$ref":"#/components/schemas/SecurityResponse"},"title":"Securities","type":"array"}},"required":["securities"],"title":"SecurityListResponse","type":"object"},"SecurityResponse":{"properties":{"slug":{"examples":["apple"],"title":"Slug","type":"string"},"symbol":{"examples":["AAPL"],"title":"Symbol","type":"string"},"name":{"examples":["Apple Inc."],"title":"Name","type":"string"}},"required":["slug","symbol","name"],"title":"SecurityResponse","type":"object"},"SecurityDailyPriceEntry":{"properties":{"date":{"format":"date","title":"Date","type":"string"},"close_price":{"examples":["68.42"],"title":"Close Price","type":"string"}},"required":["date","close_price"],"title":"SecurityDailyPriceEntry","type":"object"},"SecurityPriceHistoryResponse":{"properties":{"slug":{"examples":["apple"],"title":"Slug","type":"string"},"symbol":{"examples":["AAPL"],"title":"Symbol","type":"string"},"name":{"examples":["Apple Inc."],"title":"Name","type":"string"},"prices":{"items":{"$ref":"#/components/schemas/SecurityDailyPriceEntry"},"title":"Prices","type":"array"}},"required":["slug","symbol","name","prices"],"title":"SecurityPriceHistoryResponse","type":"object"},"SecurityNotFound":{"properties":{"code":{"const":"security_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Security not found"]}},"required":["code","message"],"title":"SecurityNotFound","type":"object"},"DataExportResponse":{"properties":{"id":{"examples":["Ex7mQ2vK9pLd"],"title":"Id","type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"requested_by_email":{"anyOf":[{"format":"email","type":"string"},{"type":"null"}],"title":"Requested By Email"},"file_size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"examples":[2487316],"title":"File Size Bytes"},"download_url":{"anyOf":[{"type":"string"},{"type":"null"}],"examples":["https://downloads.penny.finance/exports/Ex7mQ2vK9pLd.zip"],"title":"Download Url"},"expires_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Expires At"},"completed_at":{"anyOf":[{"format":"date-time","type":"string"},{"type":"null"}],"title":"Completed At"},"created_at":{"format":"date-time","title":"Created At","type":"string"}},"required":["id","status","requested_by_email","file_size_bytes","download_url","expires_at","completed_at","created_at"],"title":"DataExportResponse","type":"object"},"JobStatus":{"description":"Lifecycle of an asynchronous, client-pollable job.","enum":["pending","processing","completed","failed"],"title":"JobStatus","type":"string"},"DataExportInProgress":{"properties":{"code":{"const":"export_in_progress","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["An export is already being prepared for this household"]}},"required":["code","message"],"title":"DataExportInProgress","type":"object"},"DataExportListResponse":{"properties":{"exports":{"items":{"$ref":"#/components/schemas/DataExportResponse"},"title":"Exports","type":"array"}},"required":["exports"],"title":"DataExportListResponse","type":"object"},"DataExportNotFound":{"properties":{"code":{"const":"export_not_found","description":"Stable, machine-readable error code. Branch on this value rather than on `message`.","title":"Code","type":"string"},"message":{"description":"Human-readable explanation of the error. The wording can change, so don't parse it.","title":"Message","type":"string","examples":["Export not found"]}},"required":["code","message"],"title":"DataExportNotFound","type":"object"}},"securitySchemes":{"PersonalApiToken":{"type":"http","scheme":"bearer","bearerFormat":"Personal API token","description":"Use your personal API token (penny_pat_…) as the bearer credential. Enter the token only; the client adds the Bearer prefix. Read-only tokens permit read requests. Read/write tokens remain limited by your current household membership and role. See https://penny.finance/docs/api#authentication for setup."}}},"servers":[{"url":"https://api.penny.finance","description":"Production"}],"tags":[{"name":"users","description":"Your profile and account preferences."},{"name":"households","description":"The shared container that owns every other resource."},{"name":"accounts","description":"Connected and manual financial accounts, and their balances."},{"name":"transactions","description":"Reading, editing, splitting, tagging, and hiding transactions."},{"name":"transaction-images","description":"Receipts and other images attached to a transaction."},{"name":"categories","description":"Household categories and the groups they roll up into."},{"name":"merchants","description":"Merchant records, logos, and merges."},{"name":"tags","description":"Free-form labels that cut across categories."},{"name":"rules","description":"Categorization rules, their ordering, and dry runs."},{"name":"recurring-transactions","description":"Recurring series, occurrences, and detected suggestions."},{"name":"spending","description":"Aggregated cashflow, category, and merchant breakdowns."},{"name":"historical-balances","description":"Balance history behind the net worth chart."},{"name":"securities","description":"Holdings and security prices on investment accounts."},{"name":"institutions","description":"Financial institution metadata and logos."},{"name":"exports","description":"Household data exports and their download links."}]}