{
  "openapi": "3.1.0",
  "info": {
    "title": "Weel OpenAPI",
    "version": "v1",
    "termsOfService": "https://letsweel.com/terms/",
    "contact": {
      "name": "Contact our support",
      "email": "help@letsweel.com",
      "url": "https://help.letsweel.com"
    },
    "description": "The Weel OpenAPI empowers businesses with seamless expense management and real-time insights. Our platform makes it easy to integrate and automate expense workflows, manage receipts, and keep track of spending across your organization.\n"
  },
  "servers": [
    {
      "url": "https://public.letsweel.com"
    }
  ],
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "x-tagGroups": [
    {
      "name": "Users",
      "tags": [
        "Invites",
        "Users",
        "Roles"
      ]
    },
    {
      "name": "Transactions",
      "tags": [
        "Transactions"
      ]
    },
    {
      "name": "Budgets",
      "tags": [
        "Budgets",
        "Budget Members",
        "Budget Owners",
        "Budget Topups"
      ]
    },
    {
      "name": "Statements",
      "tags": [
        "Statements"
      ]
    },
    {
      "name": "Custom Fields",
      "tags": [
        "Custom Fields",
        "Custom Field Options",
        "Custom Field Budgets"
      ]
    },
    {
      "name": "Chart of Accounts",
      "tags": [
        "Accounting Codes",
        "Categories"
      ]
    }
  ],
  "tags": [
    {
      "name": "Transactions",
      "description": "This group of endpoints allows you to retrieve and manage transaction data, including listing transactions with various filters and fetching individual transaction details."
    },
    {
      "name": "Users",
      "description": "This group of endpoints allows you to retrieve and manage user data, including listing users and fetching individual user details."
    },
    {
      "name": "Invites",
      "description": "This group of endpoints allows you to create, list, and cancel pending user invitations. An invite exists until the recipient accepts it, at which point they appear as a user in the Users endpoints."
    },
    {
      "name": "Roles",
      "description": "This group of endpoints allows you to retrieve the roles available within a business and the permissions assigned to each role."
    },
    {
      "name": "Budgets",
      "description": "This group of endpoints allows you to retrieve and manage budget data, including listing budgets and fetching individual budget details.\n\nBudgets are organised in a hierarchy where a budget can have multiple members. Each member is associated with a user. Funds can be allocated at the budget level or at the member level, using the flag `has_member_limits`.\n\n![Budget Hierachy](assets/budget-hierarchy.png)\n"
    },
    {
      "name": "Budget Members",
      "description": "This group of endpoints allows you to retrieve and manage budget member data, including listing budget members and fetching individual budget member details."
    },
    {
      "name": "Budget Owners",
      "description": "This group of endpoints allows you to retrieve and manage budget owners. A budget owner is a user (or pending invite) who can approve spend, top up, and otherwise manage the budget.\n\nA budget must always have at least one active owner — deleting the last remaining owner is not permitted. Adding an owner who was previously removed will reinstate the original record rather than create a duplicate.\n"
    },
    {
      "name": "Budget Topups",
      "description": "This group of endpoints allows you to retrieve and create budget topups. Topups are used to increase or decrease the available amount of a budget or budget member.\n\nTopups will be automatically approved, unless a Workflow or Policy has been configured in Weel for that requires approval for budget topups.\n\nThere are two types of topups:\n  - Budget topups are used to increase or decrease the available amount of a budget. This is only permitted when `has_member_limits` is `false` for the budget.\n  - Budget member topups are used to increase or decrease the available amount of a budget member. This is only permitted when `has_member_limits` is `true` for the budget.\n\n`has_member_limits` is set to `true` when this toggle is enabled in the budget creation form.\n  ![Has Member Limits is true](assets/has-member-limits-true.png)\n"
    },
    {
      "name": "Statements",
      "description": "This group of endpoints allows you to retrieve a list of balances for the required period for a given business."
    },
    {
      "name": "Custom Fields",
      "description": "This group of endpoints allows you to create and manage custom fields (dimensions/cost centres) for your business.\n\nCustom fields can be of type `LIST` (with predefined options) or `FREE_TEXT`. Custom fields created via the Public API have a `created_by` value of `PUBLIC_API`.\n\nCustom fields created by accounting integrations (Xero, MYOB, QuickBooks, NetSuite, Business Central) have restrictions: their name and type cannot be modified via the Public API.\n"
    },
    {
      "name": "Custom Field Options",
      "description": "This group of endpoints allows you to manage the list options for a `LIST` type custom field. Options created via the Public API can be disabled or deleted."
    },
    {
      "name": "Custom Field Budgets",
      "description": "This group of endpoints allows you to link custom fields to budgets, controlling which budgets have a custom field assigned."
    },
    {
      "name": "Accounting Codes",
      "description": "This group of endpoints allows you to manage GL codes (accounting codes) for your business.\n\nGL codes are used to classify expenses for bookkeeping export. Businesses with a connected accounting integration (Xero, MYOB, NetSuite, QuickBooks, Business Central) cannot create or delete GL codes via the API — those are managed by the integration sync. Businesses with a manual integration or no integration can freely create, update, and delete GL codes. A manual integration is automatically created on the first POST if none exists.\n"
    },
    {
      "name": "Categories",
      "description": "This group of endpoints allow you to manage expense categories for your business.\n\nCategories classify transactions. System-defined categories (`custom: false`) can only have their `enabled` state toggled. Custom categories (`custom: true`) can have their `name` updated and can be deleted.\n"
    }
  ],
  "components": {
    "securitySchemes": {
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer"
      }
    },
    "parameters": {
      "PaginationOffset": {
        "name": "offset",
        "in": "query",
        "description": "Offset to retrieve items from.",
        "schema": {
          "type": "integer",
          "default": 0,
          "example": 50
        }
      },
      "PaginationLimit": {
        "name": "limit",
        "in": "query",
        "description": "Number of items per page.",
        "schema": {
          "type": "integer",
          "default": 50,
          "maximum": 500,
          "example": 50
        }
      },
      "ClientId": {
        "name": "client_id",
        "in": "path",
        "description": "The ID of the business.",
        "required": true,
        "schema": {
          "type": "integer",
          "example": 123
        }
      },
      "IsDeleted": {
        "name": "is_deleted",
        "in": "query",
        "description": "Whether the resource is deleted.",
        "schema": {
          "type": "boolean",
          "example": false
        }
      },
      "TransactionId": {
        "name": "transaction_id",
        "in": "path",
        "description": "The ID of the transaction.",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "UserId": {
        "name": "user_id",
        "in": "path",
        "description": "The ID of the user.",
        "required": true,
        "schema": {
          "type": "integer"
        }
      },
      "BudgetId": {
        "name": "budget_id",
        "in": "path",
        "description": "The ID of the budget.",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "BudgetMemberId": {
        "name": "budget_member_id",
        "in": "path",
        "description": "The ID of the budget member.",
        "required": true,
        "schema": {
          "type": "integer"
        }
      },
      "BudgetOwnerId": {
        "name": "budget_owner_id",
        "in": "path",
        "description": "The ID of the budget owner.",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "CustomFieldId": {
        "name": "custom_field_id",
        "in": "path",
        "description": "The ID of the custom field.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid",
          "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
        }
      },
      "CustomFieldOptionId": {
        "name": "option_id",
        "in": "path",
        "description": "The ID of the custom field option.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid",
          "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
        }
      },
      "InviteId": {
        "name": "invite_id",
        "in": "path",
        "description": "The ID of the invite.",
        "required": true,
        "schema": {
          "type": "integer"
        }
      },
      "AccountingCodeId": {
        "name": "accounting_code_id",
        "in": "path",
        "description": "The ID of the accounting code (GL code).",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid",
          "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
        }
      },
      "CategoryId": {
        "name": "category_id",
        "in": "path",
        "description": "The ID of the category.",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid",
          "example": "7cb19e45-1234-5678-abcd-ef9876543210"
        }
      }
    },
    "schemas": {
      "StatementListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of daily balance records for the given period.",
            "example": 100
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of daily balance records.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of daily balance records.",
            "example": "offset=0&limit=50"
          },
          "start_date": {
            "type": "string",
            "format": "date",
            "description": "The start date for this statement in UTC.",
            "example": "2024-01-01"
          },
          "end_date": {
            "type": "string",
            "format": "date",
            "description": "The end date for this statement in UTC.",
            "example": "2024-01-31"
          },
          "currency": {
            "type": "string",
            "description": "The currency of the statement.",
            "example": "AUD"
          },
          "opening_balance": {
            "type": "number",
            "description": "The opening balance of the statement.",
            "example": 1000
          },
          "closing_balance": {
            "type": "number",
            "description": "The closing balance of the statement.",
            "example": 1000
          },
          "daily_balances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DailyBalance"
            }
          }
        }
      },
      "DailyBalance": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date",
            "description": "The date of the daily balance.",
            "example": "2024-01-01"
          },
          "opening_balance": {
            "type": "number",
            "description": "The opening balance of this date.",
            "example": 1000
          },
          "closing_balance": {
            "type": "number",
            "description": "The closing balance of this date.",
            "example": 1000
          },
          "id": {
            "type": "string",
            "description": "The ID of the daily balance.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the balance was generated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the balance was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          }
        }
      },
      "TransactionListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of transactions that match the query.",
            "example": 100
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of transactions.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of transactions.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Transaction"
            }
          }
        }
      },
      "Transaction": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the transaction.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "cleared_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The date the transaction was cleared in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "auth_date": {
            "type": "string",
            "format": "date-time",
            "description": "The date the transaction was authorised in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "merchant_name": {
            "type": "string",
            "description": "The name of the merchant.",
            "example": "Bunnings Warehouse"
          },
          "attendees": {
            "type": "array",
            "description": "The names of the attendees of the transaction.",
            "items": {
              "type": "string",
              "description": "The name of the attendee.",
              "example": "Jane Doe"
            }
          },
          "budget": {
            "$ref": "#/components/schemas/TransactionBudget",
            "description": "The budget associated with the transaction."
          },
          "currency": {
            "type": "string",
            "description": "The currency of the transaction.",
            "example": "AUD"
          },
          "custom_fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomFieldValue"
            }
          },
          "fx_amount": {
            "type": "number",
            "description": "The foreign currency amount of the transaction.",
            "example": 100
          },
          "amount": {
            "type": "number",
            "description": "The amount of the transaction in AUD (positive for credits, negative for debits).",
            "example": -100
          },
          "gst": {
            "type": "number",
            "description": "The GST amount of the transaction.",
            "example": 9.09
          },
          "expense_status": {
            "type": "string",
            "description": "The expense completion status of the transaction.",
            "enum": [
              "COMPLETE",
              "INCOMPLETE_EXPENSE"
            ],
            "example": "COMPLETE"
          },
          "status": {
            "type": "string",
            "description": "The status of the transaction.",
            "enum": [
              "CLEARED",
              "AUTHED"
            ],
            "example": "CLEARED"
          },
          "transaction_type": {
            "type": "string",
            "description": "The type of transaction.",
            "enum": [
              "CARD_TRANSACTION",
              "CHARGE",
              "DEPOSIT_DIRECT_CREDIT",
              "DEPOSIT_DIRECT_DEBIT",
              "BILL",
              "REIMBURSEMENT",
              "EXTERNAL_TRANSFER",
              "MANUAL_TRANSFER",
              "CREDIT"
            ],
            "example": "CARD_TRANSACTION"
          },
          "user": {
            "description": "The user who made the transaction.",
            "$ref": "#/components/schemas/SubUser"
          },
          "line_items": {
            "type": "array",
            "description": "The line items of the transaction.",
            "items": {
              "$ref": "#/components/schemas/LineItem"
            }
          },
          "receipt_urls": {
            "type": "array",
            "description": "The URLs of the receipts for the transaction.",
            "items": {
              "type": "string",
              "example": "https://divipay-user-production.s3.amazonaws.com/123/68eae8f6-cb90-4403-ba76-a2cc12c3979j.png"
            }
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the transaction was created in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the transaction was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          }
        }
      },
      "TransactionBudget": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the budget.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "name": {
            "type": "string",
            "description": "The name of the budget.",
            "example": "Sales Team"
          },
          "budget_type": {
            "type": "string",
            "description": "The type of budget.",
            "enum": [
              "BUDGET",
              "SUBSCRIPTION"
            ],
            "example": "BUDGET"
          }
        }
      },
      "LineItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the line item.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "amount": {
            "type": "number",
            "description": "The amount of the line item in AUD.",
            "example": 100
          },
          "gst_amount": {
            "type": "number",
            "description": "The GST amount of the line item.",
            "example": 9.09
          },
          "category": {
            "$ref": "#/components/schemas/LineItemCategory"
          },
          "custom_fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomFieldValue"
            }
          },
          "description": {
            "type": "string",
            "description": "The description of the line item.",
            "example": "Building supplies"
          }
        }
      },
      "CustomFieldValue": {
        "type": "object",
        "properties": {
          "field_name": {
            "type": "string",
            "description": "The name of the custom field.",
            "example": "Project"
          },
          "entry_text": {
            "type": "string",
            "description": "The text value of the custom field.",
            "example": "Project 1"
          }
        }
      },
      "InviteListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of invites that match the query.",
            "example": 10
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "The URL to the next page of invites.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": [
              "string",
              "null"
            ],
            "description": "The URL to the previous page of invites.",
            "example": null
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Invite"
            }
          }
        }
      },
      "Invite": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The ID of the invite.",
            "example": 99
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "The email address the invite was sent to.",
            "example": "jane.doe@example.com"
          },
          "role_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the role assigned to the invitee.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "role": {
            "type": "string",
            "description": "The name of the role assigned to the invitee.",
            "example": "Team Member"
          },
          "payment_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "bills",
                "cards",
                "reimbursements"
              ]
            },
            "description": "The payment types the invitee will have access to.",
            "example": [
              "cards",
              "reimbursements"
            ]
          },
          "used": {
            "type": "boolean",
            "description": "Whether the invite has been accepted.",
            "example": false
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time the invite was created in UTC.",
            "example": "2026-05-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time the invite was last updated in UTC.",
            "example": "2026-05-01T00:00:00Z"
          }
        }
      },
      "InviteCreateRequest": {
        "type": "object",
        "required": [
          "email",
          "role_id",
          "payment_types"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "description": "The email address to send the invite to.",
            "example": "jane.doe@example.com"
          },
          "role_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the role to assign to the invitee. Must belong to the business.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "payment_types": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "string",
              "enum": [
                "bills",
                "cards",
                "reimbursements"
              ]
            },
            "description": "The payment types the invitee will have access to. Must be a non-empty list.",
            "example": [
              "cards",
              "reimbursements"
            ]
          }
        }
      },
      "UserListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of users that match the query.",
            "example": 100
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of users.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of users.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/User"
            }
          }
        }
      },
      "RoleListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of roles for the business.",
            "example": 5
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of roles.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of roles.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Role"
            }
          }
        }
      },
      "Role": {
        "type": "object",
        "required": [
          "id",
          "name",
          "is_deletable",
          "permissions"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the role.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "name": {
            "type": "string",
            "description": "The name of the role.",
            "example": "Team Member"
          },
          "is_deletable": {
            "type": "boolean",
            "description": "Whether the role can be deleted.",
            "example": false
          },
          "permissions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Permission"
            }
          }
        }
      },
      "Permission": {
        "type": "object",
        "required": [
          "resource",
          "action"
        ],
        "properties": {
          "resource": {
            "type": "string",
            "description": "The resource the action applies to.",
            "example": "transactions"
          },
          "action": {
            "type": "string",
            "description": "The action permitted on the resource.",
            "enum": [
              "create",
              "read",
              "update",
              "delete"
            ],
            "example": "read"
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "The ID of the user.",
            "example": 123
          },
          "first_name": {
            "type": "string",
            "description": "The first name of the user.",
            "example": "John"
          },
          "last_name": {
            "type": "string",
            "description": "The last name of the user.",
            "example": "Doe"
          },
          "name": {
            "type": "string",
            "description": "The full name of the user or the display name if the user has set one.",
            "example": "John Doe"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "The email of the user.",
            "example": "john.doe@example.com"
          },
          "role": {
            "type": "string",
            "description": "The role of the user.",
            "example": "Team Member"
          },
          "role_id": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the user's role.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "is_deleted": {
            "type": "boolean",
            "description": "Whether the user is deleted.",
            "example": false
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the user was created in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the user was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "expense_delegate": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": "integer"
            },
            "description": "The user IDs of this user's expense assistants (who can act on their expenses). Null if the business does not have the expense assistant feature.",
            "example": [
              456,
              789
            ]
          }
        }
      },
      "UserUpdate": {
        "type": "object",
        "description": "Fields that may be updated on an active employee. All optional.",
        "properties": {
          "role_id": {
            "type": "string",
            "format": "uuid",
            "description": "The role to assign to the user. Must belong to the same business.",
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          "payment_types": {
            "type": "array",
            "description": "The payment types the user can transact with.",
            "items": {
              "type": "string",
              "enum": [
                "bills",
                "cards",
                "reimbursements"
              ]
            },
            "example": [
              "cards"
            ]
          },
          "out_of_office_mode": {
            "type": "boolean",
            "description": "Whether the user is out of office. When true, both start and end dates are required.",
            "example": true
          },
          "out_of_office_start_date": {
            "type": "string",
            "format": "date",
            "description": "First day of the out-of-office period (inclusive).",
            "example": "2026-06-01"
          },
          "out_of_office_end_date": {
            "type": "string",
            "format": "date",
            "description": "Last day of the out-of-office period (inclusive). Must be on or after the start date.",
            "example": "2026-06-15"
          },
          "delegate_approver": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The user ID to delegate approvals to while out of office. Must belong to the same business and have no overlapping out-of-office period.",
            "example": 789
          },
          "expense_delegate": {
            "type": "array",
            "items": {
              "type": "integer"
            },
            "description": "Replaces the user's full set of expense assistants with these user IDs. A user can have at most 3 expense assistants. Each ID must belong to the same business, must be a different user (a user cannot be their own expense assistant), and must not be repeated. Expense assistants cannot be chained. A user who is themselves an expense assistant cannot be given assistants, and a user who already has assistants cannot be assigned as one. Omit this field to leave the current assistants unchanged, or send an empty array to remove them all.",
            "example": [
              456,
              789
            ]
          }
        }
      },
      "UserDetail": {
        "description": "Full user record returned from update operations.",
        "allOf": [
          {
            "$ref": "#/components/schemas/User"
          },
          {
            "type": "object",
            "properties": {
              "role_id": {
                "type": "string",
                "format": "uuid",
                "description": "The ID of the role assigned to the user.",
                "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
              },
              "payment_types": {
                "type": "array",
                "description": "The payment types the user can transact with.",
                "items": {
                  "type": "string",
                  "enum": [
                    "bills",
                    "cards",
                    "reimbursements"
                  ]
                },
                "example": [
                  "cards"
                ]
              },
              "out_of_office_mode": {
                "type": "boolean",
                "description": "Whether the user is out of office.",
                "example": true
              },
              "out_of_office_start_date": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date",
                "description": "First day of the out-of-office period (inclusive).",
                "example": "2026-06-01"
              },
              "out_of_office_end_date": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date",
                "description": "Last day of the out-of-office period (inclusive).",
                "example": "2026-06-15"
              },
              "delegate_approver": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "The user ID to delegate approvals to while out of office.",
                "example": 789
              }
            }
          }
        ]
      },
      "SubUser": {
        "type": [
          "object",
          "null"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "The ID of the user.",
            "example": 123
          },
          "first_name": {
            "type": "string",
            "description": "The first name of the user.",
            "example": "John"
          },
          "last_name": {
            "type": "string",
            "description": "The last name of the user.",
            "example": "Doe"
          },
          "name": {
            "type": "string",
            "description": "The full name of the user or the display name if the user has set one.",
            "example": "John Doe"
          }
        }
      },
      "UserBudget": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the budget.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "name": {
            "type": "string",
            "description": "The name of the budget.",
            "example": "Sales Team"
          },
          "budget_type": {
            "type": "string",
            "description": "The type of budget.",
            "enum": [
              "BUDGET",
              "SUBSCRIPTION"
            ],
            "example": "BUDGET"
          }
        }
      },
      "UserBudgetMember": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the budget member.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "budget": {
            "description": "The budget for the budget member.",
            "$ref": "#/components/schemas/UserBudget"
          },
          "available_amount": {
            "type": "number",
            "description": "The available amount of the budget member.",
            "example": 800
          },
          "spent_amount": {
            "type": "number",
            "description": "The amount of the budget that has been spent by the budget member.",
            "example": 200
          },
          "reset_amount": {
            "type": "number",
            "description": "The reset amount of the budget member.",
            "example": 1000
          },
          "is_deleted": {
            "type": "boolean",
            "description": "Whether the budget member is deleted.",
            "example": false
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget member was created in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget member was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          }
        }
      },
      "UserBudgetMemberListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of budget members for the user.",
            "example": 100
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of budget members.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of budget members.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserBudgetMember"
            }
          }
        }
      },
      "Budget": {
        "type": "object",
        "required": [
          "id",
          "name",
          "budget_type",
          "available_amount",
          "spent_amount",
          "reset_amount",
          "reset_period",
          "current_period_start",
          "current_period_end",
          "has_member_limits",
          "rollover_funds",
          "limit_categories",
          "categories",
          "custom_fields",
          "is_deleted",
          "created",
          "updated"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the budget.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "name": {
            "type": "string",
            "description": "The name of the budget.",
            "example": "Sales Team"
          },
          "budget_type": {
            "type": "string",
            "description": "The type of budget.",
            "enum": [
              "BUDGET",
              "SUBSCRIPTION"
            ],
            "example": "BUDGET"
          },
          "available_amount": {
            "type": "number",
            "description": "The available amount of the budget.",
            "example": 800
          },
          "spent_amount": {
            "type": "number",
            "description": "The amount of the budget that has been spent.",
            "example": 200
          },
          "reset_amount": {
            "type": "number",
            "description": "The reset amount of the budget.",
            "example": 1000
          },
          "reset_period": {
            "$ref": "#/components/schemas/BudgetResetPeriod"
          },
          "current_period_start": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The start date of the current period in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "current_period_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "The end date of the current period in UTC.",
            "example": "2024-01-31T23:59:59Z"
          },
          "has_member_limits": {
            "type": "boolean",
            "description": "Whether the budget has member limits.",
            "example": false
          },
          "rollover_funds": {
            "type": "boolean",
            "description": "When true, unspent balance rolls over to the next period instead of resetting.",
            "example": false
          },
          "limit_categories": {
            "type": "boolean",
            "description": "When true, only categories listed in `categories` are visible on\nthe budget. When false, all enabled business categories are visible.\n",
            "example": false
          },
          "categories": {
            "type": "array",
            "description": "Categories currently visible on the budget. Returns an empty array\nwhen `limit_categories` is false (no restriction in force).\n",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "example": "7f183748-c7fb-428a-9b2a-603a03dcabdb"
                },
                "name": {
                  "type": "string",
                  "example": "Travel"
                }
              }
            }
          },
          "custom_fields": {
            "type": "array",
            "description": "Custom fields attached to this budget.",
            "items": {
              "type": "object",
              "required": [
                "id",
                "name",
                "allow_options"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "format": "uuid",
                  "description": "The id of the custom field.",
                  "example": "44b2add5-eeb2-456c-8918-9bb362b0e896"
                },
                "name": {
                  "type": "string",
                  "example": "Department"
                },
                "allow_options": {
                  "type": [
                    "array",
                    "null"
                  ],
                  "description": "For LIST-type custom fields, the list-item ids selectable on\nthis budget. `null` means no per-budget restriction (all\nenabled options are selectable). An empty array means no\noptions are selectable on this budget. Always `null` for\nFREE_TEXT custom fields.\n",
                  "items": {
                    "type": "string",
                    "format": "uuid"
                  }
                }
              }
            }
          },
          "is_deleted": {
            "type": "boolean",
            "description": "Whether the budget is deleted.",
            "example": false
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget was created in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          }
        }
      },
      "BudgetListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of budgets that match the query.",
            "example": 100
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of budgets.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of budgets.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Budget"
            }
          }
        }
      },
      "BudgetResetPeriod": {
        "type": "string",
        "description": "The reset cadence for the budget. JULY_FINANCIAL_YEAR resets on 1 July;\nAPRIL_FINANCIAL_YEAR resets on 1 April.\n",
        "enum": [
          "DAILY",
          "WEEKLY",
          "FORTNIGHTLY",
          "MONTHLY",
          "QUARTERLY",
          "ANNUALLY",
          "JULY_FINANCIAL_YEAR",
          "APRIL_FINANCIAL_YEAR",
          "NEVER"
        ],
        "example": "MONTHLY"
      },
      "BudgetUserRef": {
        "type": "object",
        "description": "Reference to an existing Weel user by id.",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "integer",
            "description": "The id of the user.",
            "example": 12345
          }
        }
      },
      "BudgetInviteRef": {
        "type": "object",
        "description": "Reference to an outstanding invite by id.",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The id of the invite.",
            "example": "f4c1e25a-2a78-4f4f-9d3e-1c3a96cf21b1"
          }
        }
      },
      "BudgetMemberInput": {
        "type": "object",
        "description": "A member to attach to the budget. Provide exactly one of `user` or\n`invite`. `reset_amount` is required when `has_member_limits` is true\nand must be omitted otherwise; the sum of member `reset_amount` values\nmust equal the budget's `reset_amount`.\n",
        "properties": {
          "user": {
            "$ref": "#/components/schemas/BudgetUserRef"
          },
          "invite": {
            "$ref": "#/components/schemas/BudgetInviteRef"
          },
          "reset_amount": {
            "type": "number",
            "description": "The per-member spending cap when has_member_limits is true.",
            "example": 250
          }
        },
        "oneOf": [
          {
            "required": [
              "user"
            ]
          },
          {
            "required": [
              "invite"
            ]
          }
        ]
      },
      "BudgetOwnerInput": {
        "type": "object",
        "description": "An owner (budget approver) to attach to the budget. Provide exactly\none of `user` or `invite`.\n",
        "properties": {
          "user": {
            "$ref": "#/components/schemas/BudgetUserRef"
          },
          "invite": {
            "$ref": "#/components/schemas/BudgetInviteRef"
          }
        },
        "oneOf": [
          {
            "required": [
              "user"
            ]
          },
          {
            "required": [
              "invite"
            ]
          }
        ]
      },
      "BudgetCustomFieldInput": {
        "type": "object",
        "description": "A custom field to attach to the budget. `allow_options` restricts the\nvisible list items for LIST-type custom fields. Pass `[]` to detach\nall options; omit the key to leave existing options unchanged.\n`null` is not accepted.\n",
        "required": [
          "id"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The id of the custom field.",
            "example": "a2b1d8c0-9a4e-4b8a-bf24-90af44a98e2f"
          },
          "allow_options": {
            "type": "array",
            "description": "List item ids that should remain selectable on this budget.",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          }
        }
      },
      "BudgetCreateRequest": {
        "type": "object",
        "required": [
          "name",
          "reset_amount",
          "reset_period",
          "has_member_limits",
          "rollover_funds",
          "members",
          "owners"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 128,
            "description": "The name of the budget.",
            "example": "Sales Team"
          },
          "reset_amount": {
            "type": "number",
            "description": "The amount the budget resets to each period.",
            "example": 1000
          },
          "reset_period": {
            "$ref": "#/components/schemas/BudgetResetPeriod"
          },
          "has_member_limits": {
            "type": "boolean",
            "description": "When true, each member has its own `reset_amount` cap and the sum\nof member caps must equal the budget `reset_amount`. When false,\nmembers share the budget's pot.\n",
            "example": false
          },
          "rollover_funds": {
            "type": "boolean",
            "description": "When true, unspent balance rolls over to the next period.",
            "example": false
          },
          "members": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/BudgetMemberInput"
            }
          },
          "owners": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/BudgetOwnerInput"
            }
          },
          "limit_categories": {
            "type": "boolean",
            "description": "When true, only the categories listed in `categories` are visible\non the budget. When false, all business categories are visible.\n",
            "default": false,
            "example": false
          },
          "categories": {
            "type": "array",
            "description": "Category ids that should be visible on the budget.",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "custom_fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BudgetCustomFieldInput"
            }
          }
        }
      },
      "BudgetUpdateRequest": {
        "type": "object",
        "description": "Partial update of a budget's configuration. To change members or\nowners, use their respective endpoints —\n[budget members](#tag/Budget-Members) and\n[budget owners](#tag/Budget-Owners). Toggling `has_member_limits`\ncascades onto existing members (equal split on false→true).\n",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 128,
            "example": "Sales Team"
          },
          "reset_amount": {
            "type": "number",
            "example": 1500
          },
          "reset_period": {
            "$ref": "#/components/schemas/BudgetResetPeriod"
          },
          "has_member_limits": {
            "type": "boolean",
            "example": true
          },
          "rollover_funds": {
            "type": "boolean",
            "example": true
          },
          "limit_categories": {
            "type": "boolean",
            "example": true
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid"
            }
          },
          "custom_fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BudgetCustomFieldInput"
            }
          }
        }
      },
      "BudgetMember": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the budget member.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "user": {
            "description": "The user for the budget member. Only present if the user has accepted their invite to Weel.",
            "$ref": "#/components/schemas/SubUser"
          },
          "invite": {
            "description": "The invite for the budget member. Only present if the user has not  accepted their invite to Weel.",
            "$ref": "#/components/schemas/Invite"
          },
          "available_amount": {
            "type": "number",
            "description": "The available amount of the budget member.",
            "example": 800
          },
          "spent_amount": {
            "type": "number",
            "description": "The amount of the budget that has been spent by the budget member.",
            "example": 200
          },
          "reset_amount": {
            "type": "number",
            "description": "The reset amount of the budget member.",
            "example": 1000
          },
          "is_deleted": {
            "type": "boolean",
            "description": "Whether the budget member is deleted.",
            "example": false
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget member was created in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget member was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          }
        }
      },
      "BudgetMemberListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of budget members that match the query.",
            "example": 100
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of budget members.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of budget members.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BudgetMember"
            }
          }
        }
      },
      "CreateBudgetMemberRequest": {
        "type": "object",
        "description": "Provide exactly one of `user` or `invite`. `reset_amount` is required\nwhen the budget has `has_member_limits=true` and must be omitted\notherwise.\n",
        "properties": {
          "user": {
            "type": "object",
            "description": "An accepted user in this business.",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The user's ID.",
                "example": 123
              }
            },
            "required": [
              "id"
            ]
          },
          "invite": {
            "type": "object",
            "description": "A pending invite in this business.",
            "properties": {
              "id": {
                "type": "string",
                "description": "The invite's ID.",
                "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
              }
            },
            "required": [
              "id"
            ]
          },
          "reset_amount": {
            "type": "number",
            "description": "The member's spending limit. Required when the budget has\n`has_member_limits=true`. Must be omitted when `has_member_limits=false`\n(the member inherits the budget's `reset_amount`).\n",
            "example": 500
          }
        },
        "oneOf": [
          {
            "required": [
              "user"
            ]
          },
          {
            "required": [
              "invite"
            ]
          }
        ]
      },
      "UpdateBudgetMemberRequest": {
        "type": "object",
        "description": "Updates the member's `reset_amount`. Only valid when the budget has\n`has_member_limits=true`.\n",
        "properties": {
          "reset_amount": {
            "type": "number",
            "description": "The new per-member spending limit.",
            "example": 750
          }
        },
        "required": [
          "reset_amount"
        ]
      },
      "BudgetOwner": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the budget owner.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "user": {
            "description": "The user for the budget owner. Only present once the underlying invite has been accepted.",
            "$ref": "#/components/schemas/SubUser"
          },
          "invite": {
            "description": "The pending invite for the budget owner. Only present while the user has not yet accepted their invite.",
            "$ref": "#/components/schemas/Invite"
          },
          "is_deleted": {
            "type": "boolean",
            "description": "Whether the budget owner has been removed from the budget.",
            "example": false
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget owner was created in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the budget owner was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          }
        }
      },
      "BudgetOwnerListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of budget owners that match the query.",
            "example": 3
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of budget owners.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of budget owners.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BudgetOwner"
            }
          }
        }
      },
      "CreateBudgetOwnerRequest": {
        "type": "object",
        "description": "Provide exactly one of `user` or `invite`. If the invite has already\nbeen accepted by the time the request is processed, the response will\ncontain `user` rather than `invite`.\n",
        "properties": {
          "user": {
            "type": "object",
            "description": "An accepted user in this business.",
            "properties": {
              "id": {
                "type": "integer",
                "description": "The user's ID.",
                "example": 123
              }
            },
            "required": [
              "id"
            ]
          },
          "invite": {
            "type": "object",
            "description": "A pending invite in this business.",
            "properties": {
              "id": {
                "type": "string",
                "description": "The invite's ID.",
                "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
              }
            },
            "required": [
              "id"
            ]
          }
        },
        "oneOf": [
          {
            "required": [
              "user"
            ]
          },
          {
            "required": [
              "invite"
            ]
          }
        ]
      },
      "BudgetTopup": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the topup.",
            "example": "e33b7c61-5124-4ba0-b238-e4c573133715"
          },
          "amount": {
            "type": "number",
            "description": "Positive values increase the available amount, negative values decrease it.",
            "example": 100
          },
          "description": {
            "type": "string",
            "description": "The description of the topup.",
            "example": "Additional funds for travel"
          },
          "status": {
            "type": "string",
            "description": "The status of the topup.",
            "enum": [
              "APPROVED",
              "CANCELLED",
              "DECLINED",
              "PENDING"
            ],
            "example": "APPROVED"
          },
          "requested_by": {
            "description": "The user who requested the topup.",
            "$ref": "#/components/schemas/SubUser"
          },
          "actioned_by": {
            "description": "The user who actioned an approval or decline of the topup.",
            "$ref": "#/components/schemas/SubUser"
          },
          "actioned_on": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the topup was actioned in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the topup was created in UTC.",
            "example": "2024-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when the topup was last updated in UTC.",
            "example": "2024-01-01T00:00:00Z"
          }
        }
      },
      "BudgetTopupListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "The total number of topups that match the query.",
            "example": 100
          },
          "next": {
            "type": "string",
            "description": "The URL to the next page of topups.",
            "example": "offset=50&limit=50"
          },
          "previous": {
            "type": "string",
            "description": "The URL to the previous page of topups.",
            "example": "offset=0&limit=50"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BudgetTopup"
            }
          }
        }
      },
      "BudgetTopupCreate": {
        "type": "object",
        "required": [
          "amount",
          "description"
        ],
        "properties": {
          "amount": {
            "type": "number",
            "description": "Positive values increase the available amount, negative values decrease it.",
            "example": 100
          },
          "description": {
            "type": "string",
            "description": "The description of the topup.",
            "example": "Additional funds for travel"
          },
          "auto_approve": {
            "type": "boolean",
            "description": "By default, topups require approval before being added to the budget. Set this to `true` to automatically add the topup to the budget.",
            "example": true
          }
        }
      },
      "LineItemCategory": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The ID of the category.",
            "example": "f2c9897d-62fb-4d64-9647-3e6bf62d07c2"
          },
          "name": {
            "type": "string",
            "description": "The name of the category in Weel.",
            "example": "Accommodation"
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "description": "The accounting code of the category, if any.",
            "example": "6668"
          }
        }
      },
      "Balance": {
        "type": "object",
        "properties": {
          "balance": {
            "type": "number",
            "description": "Account balance amount as a decimal number",
            "example": 123.45
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217 currency code",
            "example": "AUD"
          }
        },
        "required": [
          "balance",
          "currency"
        ]
      },
      "CustomField": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier for this custom field.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "name": {
            "type": "string",
            "description": "The display name of the custom field.",
            "example": "Project Code"
          },
          "field_type": {
            "type": "string",
            "description": "The type of the custom field.",
            "enum": [
              "LIST",
              "FREE_TEXT"
            ],
            "example": "LIST"
          },
          "budget_setting": {
            "type": "string",
            "description": "Controls which budgets this custom field is assigned to.",
            "enum": [
              "NONE",
              "SOME",
              "ALL_CURRENT_AND_NEW"
            ],
            "example": "NONE"
          },
          "is_manager_only": {
            "type": "boolean",
            "description": "Whether this custom field is visible only to managers. Cannot be changed after creation.",
            "example": false
          },
          "created_by": {
            "type": "string",
            "description": "The source that created this custom field.",
            "enum": [
              "MANUAL",
              "PUBLIC_API",
              "XERO",
              "MYOB",
              "QUICKBOOKS",
              "NETSUITE",
              "BUSINESS_CENTRAL"
            ],
            "example": "PUBLIC_API"
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when this custom field was created.",
            "example": "2024-01-15T09:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when this custom field was last updated.",
            "example": "2024-01-15T09:00:00Z"
          }
        }
      },
      "CustomFieldListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Total number of custom fields.",
            "example": 10
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the next page.",
            "example": "limit=50&offset=50"
          },
          "previous": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the previous page.",
            "example": null
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomField"
            }
          }
        }
      },
      "CreateCustomFieldRequest": {
        "type": "object",
        "required": [
          "name",
          "field_type"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "The display name for the custom field. Must be unique within the business.",
            "example": "Project Code"
          },
          "field_type": {
            "type": "string",
            "description": "The type of the custom field.",
            "enum": [
              "LIST",
              "FREE_TEXT"
            ],
            "example": "LIST"
          },
          "budget_setting": {
            "type": "string",
            "description": "Controls which budgets this custom field is assigned to.",
            "enum": [
              "NONE",
              "SOME",
              "ALL_CURRENT_AND_NEW"
            ],
            "default": "ALL_CURRENT_AND_NEW",
            "example": "NONE"
          }
        }
      },
      "UpdateCustomFieldRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "The new display name. Not permitted for fields created by accounting integrations. Cannot set to a name already in use by another custom field in the business.",
            "example": "Cost Centre"
          },
          "field_type": {
            "type": "string",
            "description": "The type of the custom field. Not permitted for fields created by accounting integrations.",
            "enum": [
              "LIST",
              "FREE_TEXT"
            ],
            "example": "LIST"
          },
          "is_manager_only": {
            "type": "boolean",
            "description": "Cannot be changed after creation — always returns 400 if a different value is sent.",
            "example": false
          },
          "budget_setting": {
            "type": "string",
            "description": "Controls which budgets this custom field is assigned to.",
            "enum": [
              "NONE",
              "SOME",
              "ALL_CURRENT_AND_NEW"
            ],
            "example": "SOME"
          }
        }
      },
      "CustomFieldOption": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier for this option.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "text": {
            "type": "string",
            "description": "The display text of this option.",
            "example": "Project Alpha"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether this option is available for selection.",
            "example": true
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when this option was created.",
            "example": "2024-01-15T09:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "The date and time when this option was last updated.",
            "example": "2024-01-15T09:00:00Z"
          }
        }
      },
      "CustomFieldOptionListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Total number of options for this custom field (including disabled).",
            "example": 5
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the next page.",
            "example": "limit=50&offset=50"
          },
          "previous": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the previous page.",
            "example": null
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomFieldOption"
            }
          }
        }
      },
      "CreateCustomFieldOptionRequest": {
        "type": "object",
        "required": [
          "text"
        ],
        "properties": {
          "text": {
            "type": "string",
            "description": "The display text for this option.",
            "example": "Project Alpha"
          }
        }
      },
      "UpdateCustomFieldOptionRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "description": "The new display text. Only permitted for options belonging to non-accounting-integration custom fields.",
            "example": "Project Beta"
          },
          "enabled": {
            "type": "boolean",
            "description": "Enable or disable this option. Only permitted for options belonging to accounting integration custom fields (Xero, MYOB, QuickBooks, NetSuite, Business Central).",
            "example": false
          }
        }
      },
      "CustomFieldBudget": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier of the linked budget.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "name": {
            "type": "string",
            "description": "The name of the linked budget.",
            "example": "Marketing Q1"
          }
        }
      },
      "CustomFieldBudgetListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Total number of budgets linked to this custom field.",
            "example": 3
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the next page.",
            "example": "limit=50&offset=50"
          },
          "previous": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the previous page.",
            "example": null
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomFieldBudget"
            }
          }
        }
      },
      "CreateCustomFieldBudgetRequest": {
        "type": "object",
        "required": [
          "budget"
        ],
        "properties": {
          "budget": {
            "type": "string",
            "format": "uuid",
            "description": "The ID of the budget to link to this custom field.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          }
        }
      },
      "AccountingCode": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier for this GL code.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "code": {
            "type": "string",
            "description": "The GL code string used for bookkeeping export.",
            "example": "4000"
          },
          "name": {
            "type": "string",
            "description": "The display name of the GL code.",
            "example": "Office Expenses"
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "When this GL code was created in UTC.",
            "example": "2026-01-15T10:30:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "When this GL code was last updated in UTC.",
            "example": "2026-01-15T10:30:00Z"
          }
        }
      },
      "AccountingCodeListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Total number of GL codes.",
            "example": 100
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the next page.",
            "example": "limit=50&offset=50"
          },
          "previous": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the previous page.",
            "example": null
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AccountingCode"
            }
          }
        }
      },
      "CreateAccountingCodeRequest": {
        "type": "object",
        "required": [
          "code",
          "name"
        ],
        "properties": {
          "code": {
            "type": "string",
            "maxLength": 128,
            "description": "The GL code string. Used as the upsert key — if a code with this value already exists it will be updated.",
            "example": "4000"
          },
          "name": {
            "type": "string",
            "maxLength": 150,
            "description": "The display name of the GL code.",
            "example": "Office Expenses"
          }
        }
      },
      "Category": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The unique identifier for this category.",
            "example": "7cb19e45-1234-5678-abcd-ef9876543210"
          },
          "name": {
            "type": "string",
            "description": "The display name of the category.",
            "example": "Travel"
          },
          "custom": {
            "type": "boolean",
            "description": "Whether this is a custom category created by the business. System-defined categories have `custom: false`.",
            "example": false
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether this category is available for use on transactions.",
            "example": true
          },
          "accounting_code_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The ID of the GL code mapped to this category, or `null` if no mapping exists.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          },
          "created": {
            "type": "string",
            "format": "date-time",
            "description": "When this category was created in UTC.",
            "example": "2025-01-01T00:00:00Z"
          },
          "updated": {
            "type": "string",
            "format": "date-time",
            "description": "When this category was last updated in UTC.",
            "example": "2025-01-01T00:00:00Z"
          }
        }
      },
      "CategoryListResponse": {
        "type": "object",
        "properties": {
          "count": {
            "type": "integer",
            "description": "Total number of categories.",
            "example": 10
          },
          "next": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the next page.",
            "example": "limit=50&offset=50"
          },
          "previous": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pagination cursor for the previous page.",
            "example": null
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Category"
            }
          }
        }
      },
      "CreateCategoryRequest": {
        "type": "object",
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 128,
            "description": "The display name for the new custom category. Must be unique within the business.",
            "example": "Internal Events"
          },
          "accounting_code_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The ID of a GL code to map to this category. Must belong to the same business. Omit to create without a mapping.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          }
        }
      },
      "UpdateCategoryRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 128,
            "description": "New display name. Only accepted for custom categories (`custom: true`). Returns 400 for system categories.",
            "example": "Updated Category Name"
          },
          "enabled": {
            "type": "boolean",
            "description": "Whether this category is available for use. Only accepted for system categories (`custom: false`). Returns 400 for custom categories.",
            "example": false
          },
          "accounting_code_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The ID of a GL code to map to this category. Pass `null` to remove an existing mapping. Must belong to the same business.",
            "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
          }
        }
      }
    }
  },
  "paths": {
    "/v2/businesses/{client_id}/transactions": {
      "get": {
        "operationId": "listTransactions",
        "tags": [
          "Transactions"
        ],
        "summary": "List transactions",
        "description": "This endpoint allows you to retrieve a list of transactions for a given business. You can filter the transactions by date range, status, and expense completion status.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "name": "min_auth_date",
            "in": "query",
            "required": false,
            "description": "The minimum authorised date for the transactions in UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "max_auth_date",
            "in": "query",
            "required": false,
            "description": "The maximum authorised date for the transactions in UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "min_cleared_date",
            "in": "query",
            "required": false,
            "description": "The minimum cleared date for the transactions in UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "max_cleared_date",
            "in": "query",
            "required": false,
            "description": "The maximum cleared date for the transactions in UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "expense_status",
            "in": "query",
            "required": false,
            "description": "The expense completion status of the transactions.",
            "schema": {
              "type": "string",
              "enum": [
                "COMPLETE",
                "INCOMPLETE_EXPENSE"
              ],
              "example": "COMPLETE"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TransactionListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v2/businesses/{client_id}/transactions/{transaction_id}": {
      "get": {
        "operationId": "getTransaction",
        "tags": [
          "Transactions"
        ],
        "summary": "Get transaction",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/TransactionId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Transaction"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/statements": {
      "get": {
        "operationId": "listStatements",
        "description": "This endpoint allows you to retrieve a list of balances for the required period for a given business.",
        "tags": [
          "Statements"
        ],
        "summary": "List statements",
        "parameters": [
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "name": "start_date",
            "in": "query",
            "required": true,
            "description": "The start date for this statement in UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "end_date",
            "in": "query",
            "required": true,
            "description": "The end date for this statement in UTC.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatementListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/users": {
      "get": {
        "operationId": "listUsers",
        "description": "This endpoint allows you to retrieve a list of users for a given business.",
        "tags": [
          "Users"
        ],
        "summary": "List users",
        "parameters": [
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/roles": {
      "get": {
        "operationId": "listRoles",
        "description": "Returns the available roles that can be assigned to users within a business.",
        "tags": [
          "Roles"
        ],
        "summary": "List roles",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RoleListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/users/{user_id}": {
      "get": {
        "operationId": "getUser",
        "description": "This endpoint allows you to retrieve a user by their ID.",
        "tags": [
          "Users"
        ],
        "summary": "Get user",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateUser",
        "description": "Update role, payment types, and/or delegation settings for an active employee.\nAll fields in the request body are optional.\n",
        "tags": [
          "Users"
        ],
        "summary": "Update user",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserDetail"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteUser",
        "description": "Deletes an active employee.",
        "tags": [
          "Users"
        ],
        "summary": "Delete user",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          },
          "503": {
            "description": "Service Unavailable"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/invites": {
      "get": {
        "operationId": "listInvites",
        "description": "Returns a paginated list of invites for the given business. Includes both pending and accepted invites; excludes cancelled invites.",
        "tags": [
          "Invites"
        ],
        "summary": "List invites",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InviteListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createInvite",
        "description": "Creates and sends an invite to the given email address. Returns the created invite, including its ID for use in the cancel endpoint.",
        "tags": [
          "Invites"
        ],
        "summary": "Create invite",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InviteCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Invite"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/invites/{invite_id}": {
      "delete": {
        "operationId": "cancelInvite",
        "description": "Cancels a pending invite. Returns 400 if the invite has already been accepted.",
        "tags": [
          "Invites"
        ],
        "summary": "Cancel invite",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/InviteId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request — invite has already been accepted"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/users/{user_id}/budget-members": {
      "get": {
        "operationId": "listBudgetMembersByUser",
        "description": "This endpoint allows you to retrieve budget members by their user ID.",
        "tags": [
          "Users"
        ],
        "summary": "List budget members by user ID",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserBudgetMemberListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets": {
      "get": {
        "operationId": "listBudgets",
        "tags": [
          "Budgets"
        ],
        "summary": "List budgets",
        "parameters": [
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/IsDeleted"
          },
          {
            "name": "budget_type",
            "in": "query",
            "required": false,
            "description": "The type of budget.",
            "schema": {
              "type": "string",
              "enum": [
                "BUDGET",
                "SUBSCRIPTION"
              ],
              "example": "BUDGET"
            }
          },
          {
            "name": "has_member_limits",
            "in": "query",
            "required": false,
            "description": "Whether the budget has member limits.",
            "schema": {
              "type": "boolean",
              "example": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createBudget",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "tags": [
          "Budgets"
        ],
        "summary": "Create a budget",
        "description": "Creates a budget with the given configuration, initial members, and\nowners. All top-level configuration fields are required — no silent\ndefaults.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BudgetCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Budget"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "429": {
            "description": "Too Many Requests"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets/{budget_id}": {
      "get": {
        "operationId": "getBudget",
        "tags": [
          "Budgets"
        ],
        "summary": "Get budget",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Budget"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateBudget",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "tags": [
          "Budgets"
        ],
        "summary": "Update a budget",
        "description": "Updates a budget's top-level configuration. To change members or\nowners, use their respective endpoints —\n[budget members](#tag/Budget-Members) and\n[budget owners](#tag/Budget-Owners).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BudgetUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Budget"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteBudget",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "tags": [
          "Budgets"
        ],
        "summary": "Delete a budget",
        "description": "Deletes a budget. Cascades to members and owners.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets/{budget_id}/topups": {
      "get": {
        "operationId": "listBudgetTopups",
        "tags": [
          "Budget Topups"
        ],
        "summary": "List budget topups",
        "description": "List the topups for a budget.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetTopupListResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createBudgetTopup",
        "tags": [
          "Budget Topups"
        ],
        "summary": "Create budget topup",
        "description": "Increase or decrease the available amount of a budget. Only permitted when `has_member_limits` is `false` for the budget.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BudgetTopupCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetTopup"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "non_field_errors": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "example": "Cannot topup budget with member limits"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets/{budget_id}/members": {
      "get": {
        "operationId": "listBudgetMembers",
        "tags": [
          "Budget Members"
        ],
        "summary": "List budget members",
        "description": "A budget member is a user who has been invited to a budget.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "$ref": "#/components/parameters/IsDeleted"
          },
          {
            "name": "user_id",
            "in": "query",
            "required": false,
            "description": "The ID of the user to filter by.",
            "schema": {
              "type": "integer",
              "example": 123
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetMemberListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createBudgetMember",
        "tags": [
          "Budget Members"
        ],
        "summary": "Add budget member",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Adds a user (or pending invite) as a member of the budget. Provide\nexactly one of `user` or `invite`. If an invite has already been\naccepted, the response will contain `user` rather than `invite`.\n\n**Side effect:** On budgets with per-member limits, adding a member\nincreases the budget's total limit and available amount by the new\nmember's `reset_amount`. Re-fetch the budget if you need the\nupdated totals. Shared-pot budgets are unaffected.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBudgetMemberRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetMember"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets/{budget_id}/members/{budget_member_id}": {
      "get": {
        "operationId": "getBudgetMember",
        "tags": [
          "Budget Members"
        ],
        "summary": "Get budget member",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/BudgetMemberId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetMember"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateBudgetMember",
        "tags": [
          "Budget Members"
        ],
        "summary": "Update budget member",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Updates a budget member's `reset_amount`. Only valid when the budget has\n`has_member_limits=true` and `reset_period` is not `NEVER`.\n\n**Side effect:** The budget's total limit changes by the difference\nbetween the old and new `reset_amount`. The budget's available amount\nis not touched — use [topups](#tag/Budget-Topups/operation/createBudgetMemberTopup)\nto change live balances.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/BudgetMemberId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateBudgetMemberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetMember"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteBudgetMember",
        "tags": [
          "Budget Members"
        ],
        "summary": "Remove budget member",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Deletes the budget member. If the member has an associated card,\nthe card is revoked asynchronously. A budget must retain at least one\nmember.\n\n**Side effect:** On budgets with per-member limits, removing a member\nreduces the budget's total limit and available amount by the member's\nshare.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/BudgetMemberId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets/{budget_id}/owners": {
      "get": {
        "operationId": "listBudgetOwners",
        "tags": [
          "Budget Owners"
        ],
        "summary": "List budget owners",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Lists owners of the budget.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "$ref": "#/components/parameters/IsDeleted"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetOwnerListResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createBudgetOwner",
        "tags": [
          "Budget Owners"
        ],
        "summary": "Add budget owner",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Adds a user (or pending invite) as an owner of the budget. Provide\nexactly one of `user` or `invite`. If an invite has already been\naccepted, the response will contain `user` rather than `invite`.\n\nIf the same user or invite was previously removed from this budget,\nthe original record is reinstated rather than a new one created — the\nreturned `id` will match the original owner's `id`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBudgetOwnerRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetOwner"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets/{budget_id}/owners/{budget_owner_id}": {
      "delete": {
        "operationId": "deleteBudgetOwner",
        "tags": [
          "Budget Owners"
        ],
        "summary": "Remove budget owner",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Removes the owner from the budget. A budget must retain at least one active owner.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/BudgetOwnerId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/budgets/{budget_id}/members/{budget_member_id}/topups": {
      "get": {
        "operationId": "listBudgetMemberTopups",
        "tags": [
          "Budget Topups"
        ],
        "summary": "List budget member topups",
        "description": "List the topups for a budget member.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/BudgetMemberId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetTopupListResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "createBudgetMemberTopup",
        "tags": [
          "Budget Topups"
        ],
        "summary": "Create budget member topup",
        "description": "Increase or decrease the available amount of a budget member. Only permitted when `has_member_limits` is `true` for the budget.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          },
          {
            "$ref": "#/components/parameters/BudgetMemberId"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BudgetTopupCreate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BudgetTopup"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "non_field_errors": {
                      "type": "array",
                      "items": {
                        "type": "string",
                        "example": "Cannot topup budget member when budget does not have member limits"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/balance": {
      "get": {
        "operationId": "listBalances",
        "tags": [
          "Statements"
        ],
        "summary": "Get account balances",
        "description": "Retrieve real-time account balances for all currencies associated with your business. This endpoint returns the current balance for each currency wallet associated with your business account.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/Balance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/custom-fields": {
      "get": {
        "operationId": "listCustomFields",
        "tags": [
          "Custom Fields"
        ],
        "summary": "List custom fields",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Returns a paginated list of custom fields for the given business.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createCustomField",
        "tags": [
          "Custom Fields"
        ],
        "summary": "Create a custom field",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Creates a new custom field for the given business. The `created_by` value will be set to `PUBLIC_API`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomFieldRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomField"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/custom-fields/{custom_field_id}": {
      "get": {
        "operationId": "getCustomField",
        "tags": [
          "Custom Fields"
        ],
        "summary": "Get a custom field",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Returns a single custom field by ID.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomField"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "patch": {
        "operationId": "updateCustomField",
        "tags": [
          "Custom Fields"
        ],
        "summary": "Update a custom field",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Partially updates a custom field.\n\n**Restrictions for accounting integration fields** (created by Xero, MYOB, QuickBooks, NetSuite, or Business Central): the `name` field cannot be changed. Only `budget_setting` can be updated.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomFieldRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomField"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteCustomField",
        "tags": [
          "Custom Fields"
        ],
        "summary": "Delete a custom field",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Deletes a custom field. This also removes all associated options and budget links.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/custom-fields/{custom_field_id}/options": {
      "get": {
        "operationId": "listCustomFieldOptions",
        "tags": [
          "Custom Field Options"
        ],
        "summary": "List custom field options",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Returns a paginated list of all options for the given custom field, including disabled ones.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldOptionListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createCustomFieldOption",
        "tags": [
          "Custom Field Options"
        ],
        "summary": "Create a custom field option",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Adds a new option to a `LIST` type custom field.\n\nNot permitted for `FREE_TEXT` custom fields or custom fields created by accounting integrations.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomFieldOptionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldOption"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/custom-fields/{custom_field_id}/options/{option_id}": {
      "patch": {
        "operationId": "updateCustomFieldOption",
        "tags": [
          "Custom Field Options"
        ],
        "summary": "Update a custom field option",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Partially updates a custom field option.\n\n**Accounting integration fields** (Xero, MYOB, QuickBooks, NetSuite, Business Central): only `enabled` can be changed. The `text` field cannot be modified.\n\n**Non-accounting-integration fields** (MANUAL, PUBLIC_API): only `text` can be changed. The `enabled` field cannot be modified — delete and recreate options instead.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldOptionId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomFieldOptionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldOption"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteCustomFieldOption",
        "tags": [
          "Custom Field Options"
        ],
        "summary": "Delete a custom field option",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Permanently deletes a custom field option.\n\nNot permitted for options belonging to custom fields created by accounting integrations.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldOptionId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/custom-fields/{custom_field_id}/budgets": {
      "get": {
        "operationId": "listCustomFieldBudgets",
        "tags": [
          "Custom Field Budgets"
        ],
        "summary": "List budgets linked to a custom field",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Returns a paginated list of budgets that have this custom field assigned.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldBudgetListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "linkCustomFieldBudget",
        "tags": [
          "Custom Field Budgets"
        ],
        "summary": "Link a budget to a custom field",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Assigns a custom field to a budget. The budget must belong to the same business. Only permitted when the custom field's `budget_setting` is `SOME`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomFieldBudgetRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomFieldBudget"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/custom-fields/{custom_field_id}/budgets/{budget_id}": {
      "delete": {
        "operationId": "unlinkCustomFieldBudget",
        "tags": [
          "Custom Field Budgets"
        ],
        "summary": "Unlink a budget from a custom field",
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "description": "Removes the link between a custom field and a budget.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CustomFieldId"
          },
          {
            "$ref": "#/components/parameters/BudgetId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/accounting-codes": {
      "get": {
        "operationId": "listAccountingCodes",
        "tags": [
          "Accounting Codes"
        ],
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "summary": "List accounting codes",
        "description": "Returns a paginated list of GL codes for the given business.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountingCodeListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "upsertAccountingCode",
        "tags": [
          "Accounting Codes"
        ],
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "summary": "Create or update an accounting code",
        "description": "Creates or updates a GL code for the business (upsert by `code`).\n\n- If a GL code with the given `code` already exists, its `name` is updated.\n- If a previously soft-deleted GL code with that `code` exists, it is restored.\n- Otherwise a new record is created.\n\nOnly available for businesses with a manual integration or no integration. If no integration exists, a manual integration is automatically created. Returns `400` if the business has a connected accounting provider (Xero, MYOB, NetSuite, QuickBooks, Business Central).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAccountingCodeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK (existing code updated or restored)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountingCode"
                }
              }
            }
          },
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountingCode"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/accounting-codes/{accounting_code_id}": {
      "delete": {
        "operationId": "deleteAccountingCode",
        "tags": [
          "Accounting Codes"
        ],
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "summary": "Delete an accounting code",
        "description": "Soft-deletes a GL code. Only available for businesses with a manual integration.\n\nAny category mapped to this GL code will have its mapping cleared. Business admins and accountants will receive an `ACCOUNTING_CODE_DELETED` notification.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/AccountingCodeId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request (e.g. business has a non-manual accounting integration)"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/categories": {
      "get": {
        "operationId": "listCategories",
        "tags": [
          "Categories"
        ],
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "summary": "List categories",
        "description": "Returns a paginated list of expense categories for the given business.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/PaginationOffset"
          },
          {
            "$ref": "#/components/parameters/PaginationLimit"
          },
          {
            "name": "custom",
            "in": "query",
            "required": false,
            "description": "Filter by category type. `true` returns only custom categories; `false` returns only system-defined categories. Omit to return all.",
            "schema": {
              "type": "boolean"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CategoryListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "post": {
        "operationId": "createCategory",
        "tags": [
          "Categories"
        ],
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "summary": "Create a category",
        "description": "Creates a new custom category (`custom: true`) for the business. The name must be unique within the business.",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCategoryRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Category"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    },
    "/v1/businesses/{client_id}/categories/{category_id}": {
      "patch": {
        "operationId": "updateCategory",
        "tags": [
          "Categories"
        ],
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "summary": "Update a category",
        "description": "Updates an existing category. Accepted fields depend on the category type:\n\n- Custom categories (`custom: true`): `name` and `accounting_code_id` are mutable; `enabled` returns 400.\n- System categories (`custom: false`): `enabled` and `accounting_code_id` are mutable; `name` returns 400.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CategoryId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCategoryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Category"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      },
      "delete": {
        "operationId": "deleteCategory",
        "tags": [
          "Categories"
        ],
        "x-badges": [
          {
            "name": "Beta",
            "color": "orange"
          }
        ],
        "summary": "Delete a category",
        "description": "Soft-deletes a custom category. Returns `400` if the category is system-defined (`custom: false`).",
        "parameters": [
          {
            "$ref": "#/components/parameters/ClientId"
          },
          {
            "$ref": "#/components/parameters/CategoryId"
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "description": "Bad Request (system categories cannot be deleted)"
          },
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "404": {
            "description": "Not Found"
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ]
      }
    }
  }
}