List expenses with comprehensive filtering. Use this for both personal expense queries and company-wide financial analysis.
IMPORTANT
- For large datasets (50+ expenses): If your environment supports downloading files from URLs, consider using start_expense_download for CSV export instead to avoid loading hundreds of records into conversation context. This tool returns paginated results suitable for smaller queries and interactive workflows.
IMPORTANT
- How to scope expense queries with expense_owner:
🔍 The primary users of this tool are admins and finance operators, so the DEFAULT SCOPE is company-wide. Only narrow to the caller when the user explicitly says so.
IMPORTANT DEFAULT BEHAVIOR: When the query is ambiguous or phrased generically (no possessive "my"/"mine" and no subject "I"), OMIT expense_owner. This returns all expenses across the organization, which is what admins asking questions like "show expenses over $500", "find expenses missing receipts", "which expenses are declined" expect.
⚠️ Do NOT treat "show me X" as a personal-scope signal. "me" is just the indirect object of "show" — it does NOT imply the user owns the expenses. Only the possessive "my"/"mine" or the subject "I" indicate personal scope.
Personal queries ONLY when the user explicitly refers to themselves (use expense_owner: "ME"):
- Possessive: "my expenses", "my receipts", "my reimbursements", "my card transactions", "which of my expenses..."
- Subject "I": "how much have I spent", "what did I spend on...", "am I spending more on..."
- Do NOT infer personal scope from: "show expenses", "find expenses", "list expenses", "which expenses", "show me expenses", "expenses over $X", "expenses from [merchant]"
→ SET expense_owner: "ME" ONLY when the user message contains "my", "mine", or "I" as a subject referring to the caller
Company-wide queries (OMIT expense_owner — this is the default):
- Any request without a first-person pronoun: "show expenses", "find expenses missing receipts", "which expenses are flagged", "list card expenses over $500"
- Explicit company language: "our burn rate", "we spent", "company expenses", "overall spending", "analyze all card transactions", "total reimbursements"
→ OMIT expense_owner to return all expenses across the organization
Team queries (use expense_owner: "DIRECT_REPORTS" or "ALL_REPORTS"):
- "my team's expenses", "direct reports' spending"
- "expenses from all my reports"
→ Use DIRECT_REPORTS for immediate reports only, or ALL_REPORTS for nested reports
Specific user queries (use user_ids):
- "show John's expenses", "Alice's reimbursements"
→ First call list_users_by_name_or_email to get user ID, then pass user_ids parameter
IMPORTANT
- Location and travel data:
🌍 Location and travel data are ALWAYS null by default unless you explicitly request them via additional_fields.
When user asks about WHERE an expense occurred (location, city, country, address):
- Query asks: "Where was that expense?", "What city was this from?", "Show me the location"
→ You MUST include additional_fields: ["LOCATION"]
When user asks about travel details (flights, hotels, car rentals):
- Query asks: "Was this a flight?", "Show me travel expenses", "Which hotel?"
→ You MUST include additional_fields: ["TRAVEL_METADATA"]
⚠️ A null location does NOT mean "no location exists" - it means you did not request it in additional_fields.
expense types (BILLPAY, CARD, CLAWBACK, REIMBURSEMENT),
Filter Usage Best Practices:
- For CARD expense queries, always include date filters (purchased_at_start/purchased_at_end) for reliable results
- When using min_amount/max_amount filters, combine with date filters for better performance
Timezone:
- timezone: IANA timezone string (e.g., "America/Los_Angeles", "America/New_York", "Europe/London", "Asia/Tokyo").
Pass the user's timezone from your system context if available. If not provided, defaults to UTC.
IMPORTANT
- Transparency: When presenting results, ALWAYS tell the user which timezone was used for the query:
- If timezone was provided: "Based on your Pacific Time zone, here are expenses from May 6, 2026..."
- If timezone was NOT provided (UTC default): "Note: dates are interpreted in UTC. If you'd like results in your local timezone, let me know your timezone."
Why this matters: When a user says "show this week's expenses", they mean their local week. The timezone parameter ensures date filters match the user's local calendar days. Without it, dates are treated as UTC which may not match the user's intent.
Date Filtering (only one type can be used at a time): IMPORTANT
- Default to purchased_at for ALL time-based queries. The purchased_at filter covers when the transaction actually occurred and is the correct filter for general date queries like "this week", "last month", "recent", "posted this week", etc. Only use posted_at when the user explicitly needs the bank settlement/accounting posting date for reconciliation purposes.
- Purchase Date (DEFAULT): purchased_at_start/purchased_at_end
- Filter by when expense was purchased/transacted. Use this for all general date queries. Pass dates/datetimes in the user's local timezone (will be converted to UTC automatically).
- Posted Date (accounting only): posted_at_start/posted_at_end
- Filter by bank settlement/posting date. Only use when user specifically needs accounting posting dates. Pass dates/datetimes in the user's local timezone (will be converted to UTC automatically).
- Reimbursement Submission Date: reimbursement_submitted_at_start/reimbursement_submitted_at_end
- Filter by when reimbursement was submitted (only works with REIMBURSEMENT type). Pass dates/datetimes in the user's local timezone (will be converted to UTC automatically).
- Assigned Date: assigned_at_start/assigned_at_end
- Filter by when expense was assigned for review. Pass dates/datetimes in the user's local timezone (will be converted to UTC automatically).
Amount Filtering (all amounts in USD):
- min_amount: Filter expenses with amount greater than or equal to this value (in USD, supports decimals with up to 2 places)
- max_amount: Filter expenses with amount less than or equal to this value (in USD, supports decimals with up to 2 places)
Text Search:
- search: Search expenses by merchant name, memo, or other text fields (e.g., "nike", "lunch")
Limit Filtering:
- limit_ids: Filter expenses by spend limit IDs (e.g., ["limit_123", "limit_456"])
CRITICAL: This parameter ONLY accepts limit IDs (like "spl_abc123"). It does NOT accept limit names (like "Tony's T&E"). If the user mentions a limit by name, you MUST first call list_my_limits to resolve the name to an ID, then pass that ID here. NEVER pass a limit name directly to this parameter - it will not work correctly.
Expense ID Filtering:
- expense_ids: Filter by specific expense IDs (e.g., ["expense_123", "expense_456"])
Additional Fields:
- additional_fields: Array of optional fields to include in response. Supported values:
- "TRAVEL_METADATA"
- Includes flight, car rental, lodging, and train travel data
- "LOCATION"
- Includes expense location details (country, city, coordinates, etc.)
Note: Location and travel data are NOT returned by default. If the response has null location/travel and the user is asking about it, re-call with the relevant additional_fields value.
Expense records include associated card details (card ID, status, last four digits) when available - you do not need to separately look up cards to answer questions about expenses on specific cards.
IMPORTANT: expense_owner and user_ids are mutually exclusive. Use expense_owner for role-based scoping or user_ids for specific user IDs, but not both.
Expand (receipt details):
- expand: Use ["RECEIPTS"] to include full receipt details. WITHOUT expand, receipts only contain IDs.
WITH expand: ["RECEIPTS"], each receipt includes:
- asset_id
- FileStore asset ID for the receipt file
- download_uri
- URL to download the receipt file/image
- content.is_real_receipt - whether the file is classified as a real receipt
- content.merchant_name - merchant name parsed from the receipt
- content.purchased_at - purchase date parsed from the receipt
- content.amount - amount parsed from the receipt
- content.line_items - itemized charges from the receipt (name, quantity, unit_price, total)
⚠️ When the user asks about receipt line items, itemized charges, "what did I buy", receipt content, receipt images/downloads, or parsed receipt data → you MUST include expand: ["RECEIPTS"]. A receipt with only an ID and no content/download_uri means expand was NOT used — re-call with expand: ["RECEIPTS"].
Status Filters:
- approval_statuses: Filter by approval status. Dashboard-exposed values: APPROVED, CANCELED, OUT_OF_POLICY, SUBMITTED.
- pending_approvals: FROM_ME (pending your approval) or FROM_OTHERS (pending another approval).
- payment_statuses: Payment lifecycle state (NOT_STARTED, SCHEDULED, PROCESSING, CANCELED, CLEARED, DECLINED, REFUNDING, REFUNDED, CASH_ADVANCE, CREDITED, AWAITING_PAYMENT).
- dispute_statuses: Dashboard-exposed values: DISPUTE_STATUS_IN_PROGRESS, DISPUTE_STATUS_CLOSED.
- reimbursement_export_statuses: EXPORTED or NOT_EXPORTED (reimbursement export state).
- user_status: Filter by spender's user status. Dashboard-exposed: ACTIVE, DELETED, DISABLED.
Reimbursement-only filters (require types: ["REIMBURSEMENT"]):
- reimbursement_types: MILEAGE, OUT_OF_POCKET, PER_DIEM.
- reimbursement_payment_method: MONEY_MOVEMENT (paid on Brex) or TRACKING (paid outside of Brex).
Travel filters:
- travel_provider: BREX_TRAVEL (only Brex Travel) or NON_BREX_TRAVEL (exclude Brex Travel).
- trip_ids: Filter by trip IDs — use list_active_and_upcoming_travel_trips to discover IDs.
Compliance Filters (matches dashboard labels):
- compliance_statuses: Overall compliance status (DOCUMENTATION_DUE, REVIEW_DUE, COMPLETED). Matches the 'Compliance status' filter in the Brex dashboard.
- documentation_statuses: Documentation deadline status (DUE, OVERDUE, COMPLETED). Matches the 'Documentation status' filter in the Brex dashboard. Use [DUE, OVERDUE] to find expenses missing required documentation.
- receipt_status: RECEIPT_PRESENT or RECEIPT_ABSENT.
- memo_status: MEMO_PRESENT or MEMO_ABSENT.
- require_review_reasons: MEALS, CAR_RENTAL (Rides), FLIGHTS, LODGING, TRAINS, MILEAGE, MERCHANT_OR_CATEGORY, AMOUNT, OTHERS.
- government_attendees_status: GOVERNMENT_OFFICIAL_PRESENT or GOVERNMENT_OFFICIAL_ABSENT.
- expense_policy_ids: Filter by policy IDs — use get_expense_policy to inspect a specific policy.
- bill_invoice_numbers: Filter Bill Pay expenses by invoice number (free text).
Approver / Approval filters:
- approver_user_ids: Filter by approvers in the approval chain — resolve user IDs via list_users_by_name_or_email.
- next_approver_user_ids: Filter by the next approver in the chain — resolve user IDs via list_users_by_name_or_email.
Organization Filters:
- department_ids: Filter by department IDs — use list_departments to discover IDs.
- card_ids: Filter by card IDs (use this when the user mentions a card by last-4).
- vendor_ids: Bill Pay vendor IDs — use list_vendors to discover.
- merchant_ids: Card merchant IDs — use list_merchants to discover.
- merchant_category_ids: Merchant category IDs — use list_merchant_categories to discover.
Accounting Filters:
- billing_entity_ids: Filter by billing (funding) legal entity IDs. Also called 'billed entity' in the Dashboard.
- spending_entity_ids: Filter by spending legal entity IDs.
- cost_center_ids: Filter by cost center IDs.
- expense_category_ids: Filter by expense category IDs — use list_expense_categories to discover IDs.
- erp_debit_gl_account_field_key + erp_debit_gl_account_option_ids: Filter by ERP debit GL account. These two parameters MUST be sent together. Workflow: (1) call list_gl_accounts, (2) copy gl_account_field.key into erp_debit_gl_account_field_key, (3) copy the desired accounts[].identifier values (not id, not value) into erp_debit_gl_account_option_ids. Never guess the field_key — it is dynamic per accounting integration.
Risk Filter:
- high_risk_flagged: When true, only returns expenses flagged as HIGH risk. Omit (or false) to not filter by risk tier.
Date Filters (use only ONE of purchased/posted/reimbursement_submitted at a time; assigned_at is independent):
- assigned_at_start / assigned_at_end: Date expense was assigned to the caller for review.
Understanding Expense Lifecycle and Compliance Status:
Expense Lifecycle: 1. New expense created (card transaction or reimbursement submitted) 2. Documentation phase: System checks if documentation is required (receipts, memo, attendees, etc.) 3. Spender submits documentation if needed 4. Review phase: System checks if approval/review is required based on company policy 5. Reviewer reviews and approves/rejects if necessary 6. Expense is finalized
Each expense returns TWO sets of compliance-related fields:
A. DOCUMENTATION COMPLIANCE (for spenders - receipts, memo, attendees):
- documentationComplianceStatus: Status of documentation requirements that the spender must fulfill
- "NOT_REQUIRED"
- Company policy does not require any documentation for this expense. Empty receipts/memo are acceptable.
- "COMPLETED"
- All required documentation has been provided according to policy.
- "DUE"
- Documentation is required by policy but not yet provided. Check missingDocumentations field for specifics.
- "OVERDUE"
- Required documentation is past its submission deadline. Check missingDocumentations field for specifics.
- missingDocumentations: Array of specific items required by policy but not yet provided. Possible values: ["MEMO", "RECEIPT", "ATTENDEES", "EXTENDED_FIELD"]
- Empty array []
- Either no documentation is required OR all required documentation is complete
- Non-empty array
- Lists specific items that must be provided (e.g., ["MEMO", "RECEIPT"])
- documentationSubmissionDeadline: The UTC timestamp by which documentation must be submitted (only present if documentation is required)
B. REVIEW COMPLIANCE (for reviewers - approval/rejection):
- reviewComplianceStatus: Status of review/approval requirements that the reviewer must fulfill
- "NOT_REQUIRED"
- Company policy does not require review/approval for this expense.
- "COMPLETED"
- The expense has been reviewed and approved/rejected.
- "DUE"
- Review is required by policy but not yet completed.
- "OVERDUE"
- Required review is past its deadline.
- reviewDeadline: The UTC timestamp by which the review must be completed (only present if review is required)
KEY DISTINCTIONS:
- DocumentationComplianceStatus="NOT_REQUIRED" and missingDocumentations=[] → Documentation not required by company policy
- Empty receipts/memo with documentationComplianceStatus="DUE" or "OVERDUE" and missingDocumentations=["RECEIPT","MEMO"] → Documentation IS required by policy but missing
- reviewComplianceStatus="DUE" or "OVERDUE" → Expense is waiting for someone to review/approve it
- reviewComplianceStatus="NOT_REQUIRED" → No approval needed
All dates should be in ISO 8601 format (e.g., "2025-04-01" or "2025-04-01T14:00:00") in the user's local timezone. They will be automatically converted to UTC using the timezone parameter. All amounts are assumed to be in USD currency. Results are paginated - use limit and cursor for pagination.
Example 1: Analyze company monthly burn rate (all card spend in March 2025): { "types": ["CARD"], "purchased_at_start": "2025-03-01T00:00:00.000Z", "purchased_at_end": "2025-03-31T23:59:59.999Z" }
Example 2: Find all high-dollar expenses over $5,000 in Q1 2025: { "min_amount": 5000, "purchased_at_start": "2025-01-01T00:00:00.000Z", "purchased_at_end": "2025-03-31T23:59:59.999Z" }
Example 3: Analyze SaaS/software spending (search for common software vendors): { "search": "AWS", "types": ["CARD"], "purchased_at_start": "2025-01-01T00:00:00.000Z", "purchased_at_end": "2025-12-31T23:59:59.999Z" }
Example 4: Review all pending reimbursements awaiting payout: { "types": ["REIMBURSEMENT"] }
Example 5: Analyze travel spending across the company (exclude Brex Travel): { "types": ["CARD"], "travel_provider": "NON_BREX_TRAVEL", "additional_fields": ["TRAVEL_METADATA"], "purchased_at_start": "2025-01-01T00:00:00.000Z", "purchased_at_end": "2025-03-31T23:59:59.999Z" }
Example 6: Find expenses missing receipts for compliance audit (preferred): { "receipt_status": "RECEIPT_ABSENT", "types": ["CARD"], "min_amount": 1000 }
Example 7: Expenses requiring review for flights / lodging: { "require_review_reasons": ["FLIGHTS", "LODGING"] }
Example 8: Expenses pending my approval: { "pending_approvals": ["FROM_ME"] }
Example 9: Reimbursements paid outside of Brex: { "types": ["REIMBURSEMENT"], "reimbursement_payment_method": "TRACKING" }
Example 10: Expenses with a government official attendee: { "government_attendees_status": "GOVERNMENT_OFFICIAL_PRESENT" }
Example 11: Expenses for a specific department (resolve name → ID with list_departments first): { "department_ids": ["cudmnt_eng123"] }
Example 12: Expenses for a specific merchant: { "merchant_ids": ["mrch_starbucks"] }
Example 13: Expenses by posted date (accounting): { "posted_at_start": "2025-04-01T00:00:00.000Z", "posted_at_end": "2025-04-30T23:59:59.999Z" }
Example 12: Get expenses with full receipt details including line items: { "expense_owner": "ME", "expand": ["RECEIPTS"] }