openapi: 3.0.3 info: title: Expenses Service version: "1.0.0" description: OpenAPI-first service for tracking expenses and cashflow. paths: /expenses: post: operationId: create_expense summary: Create a new expense or income entry requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ExpenseInput" responses: "201": description: Expense created content: application/json: schema: $ref: "#/components/schemas/Expense" get: operationId: list_expenses summary: List expenses parameters: - name: from in: query schema: type: string format: date-time - name: to in: query schema: type: string format: date-time responses: "200": description: List of expenses content: application/json: schema: type: array items: $ref: "#/components/schemas/Expense" /expenses/{expense_id}: get: operationId: get_expense summary: Get expense by ID parameters: - name: expense_id in: path required: true schema: type: string responses: "200": description: Expense found content: application/json: schema: $ref: "#/components/schemas/Expense" "404": description: Expense not found /accounts: post: operationId: create_account summary: Create an account requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AccountCreate" responses: "201": description: Account created content: application/json: schema: $ref: "#/components/schemas/Account" get: operationId: list_accounts summary: List accounts responses: "200": description: List of accounts content: application/json: schema: type: array items: $ref: "#/components/schemas/Account" /accounts/{account_id}: get: operationId: get_account summary: Get account by ID parameters: - name: account_id in: path required: true schema: type: string responses: "200": description: Account found content: application/json: schema: $ref: "#/components/schemas/Account" "404": description: Account not found put: operationId: update_account summary: Update an account parameters: - name: account_id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AccountUpdate" responses: "200": description: Account updated content: application/json: schema: $ref: "#/components/schemas/Account" "404": description: Account not found delete: operationId: delete_account summary: Delete an account parameters: - name: account_id in: path required: true schema: type: string responses: "204": description: Account deleted "404": description: Account not found /tags: post: operationId: create_tag summary: Create a tag requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TagCreate" responses: "201": description: Tag created content: application/json: schema: $ref: "#/components/schemas/Tag" get: operationId: list_tags summary: List tags responses: "200": description: List of tags content: application/json: schema: type: array items: $ref: "#/components/schemas/Tag" /tags/{tag_id}: get: operationId: get_tag summary: Get tag by ID parameters: - name: tag_id in: path required: true schema: type: string responses: "200": description: Tag found content: application/json: schema: $ref: "#/components/schemas/Tag" "404": description: Tag not found put: operationId: update_tag summary: Update a tag parameters: - name: tag_id in: path required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/TagUpdate" responses: "200": description: Tag updated content: application/json: schema: $ref: "#/components/schemas/Tag" "404": description: Tag not found delete: operationId: delete_tag summary: Delete a tag parameters: - name: tag_id in: path required: true schema: type: string responses: "204": description: Tag deleted "404": description: Tag not found components: schemas: PublicUser: type: object required: [id, username] properties: id: type: string username: type: string email: type: string format: email PayeeType: type: string enum: [merchant, person, transfer, other] Payee: type: object required: [type, name] properties: type: $ref: "#/components/schemas/PayeeType" name: type: string AccountType: type: string enum: [cash, bank, credit_card, wallet, other] Account: type: object required: [id, name, type, currency] properties: id: type: string name: type: string type: $ref: "#/components/schemas/AccountType" currency: type: string is_active: type: boolean AccountCreate: type: object required: [name, type, currency] properties: name: type: string type: $ref: "#/components/schemas/AccountType" currency: type: string is_active: type: boolean AccountUpdate: allOf: - $ref: "#/components/schemas/AccountCreate" Tag: type: object required: [id, name] properties: id: type: string name: type: string parent_id: type: string nullable: true TagCreate: type: object required: [name] properties: name: type: string parent_id: type: string nullable: true TagUpdate: allOf: - $ref: "#/components/schemas/TagCreate" ExpenseInput: type: object required: - payor - payee - amount - account - occurred_at properties: payor: type: string payee: $ref: "#/components/schemas/Payee" amount: type: number format: float account: type: string tags: type: array items: type: string occurred_at: type: string format: date-time Expense: type: object required: - id - payor - payee - amount - account - occurred_at - created_at properties: id: type: string payor: $ref: "#/components/schemas/PublicUser" payee: $ref: "#/components/schemas/Payee" amount: type: number format: float account: $ref: "#/components/schemas/Account" tags: type: array items: $ref: "#/components/schemas/Tag" occurred_at: type: string format: date-time created_at: type: string format: date-time