Get User By Id
Get a user by their unique ID
This tool retrieves detailed information about a specific user using their unique user ID.
Use this when you have a user ID and need to get their complete profile information.
Example Input:
{
"id": "cuuser_123"
}
Example Output:
{
"id": "cuuser_123",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"role": "CARD_ADMIN",
"status": "ACTIVE",
"manager_id": "cuuser_5678",
"manager_first_name": "Jane",
"manager_last_name": "Smith",
"manager_title_id": "ti_1234",
"manager_title_name": "Engineering Manager",
"department_id": "cudmnt_1234",
"department_name": "Engineering",
"location_id": "culoc_1234",
"location_name": "San Francisco",
"title_id": "ti_5678",
"title_name": "Software Engineer"
}
List Users By Name Or Email
List users by name or email
This tool allows you to search for users by name or email.
It will return a paginated list of up to 10 users that match the search criteria, sorted by first name.
If you only have the name or email, you can use this tool to find the user ID and their full details.
Example Input 1 (search by name):
{
"search_text": "John Smith"
}
Example Input 2 (search by email):
{
"search_text": "john.smith@example.com"
}
Example Output:
{
"items": [
{
"id": "cuuser_123",
"first_name": "John",
"last_name": "Smith",
"email": "john.smith@example.com",
"role": "CARD_ADMIN",
"status": "ACTIVE"
}
],
"next_cursor": "cursor_1234"
}
List Users
List users with optional filtering and pagination.
âšī¸ Response narrowing for non-admin callers: callers without the
`user.list` operation permission receive the same users, but with
`email`, `phone_number`, `location_id`, and `location_name`
omitted. Names, titles, departments, managers, roles, and status are
always returned. Use this tool freely for discovery (e.g. picking
attendees); fall back to `get_user_myself` when the caller needs their
own contact info.
đ¨ CRITICAL â ID filters REQUIRE companion discovery tools FIRST đ¨
The following filters accept ONLY Brex resource IDs (never names, labels, or
human-readable strings). If the user describes a filter in plain English
(e.g. "Engineering department", "San Francisco office", "Brex Inc. entity",
"Software Engineer title", "R&D cost center", "bill pay approvers",
"card admins", "reports to Jane Smith"), you MUST call the matching
discovery tool first to resolve that string into an ID, then pass the ID
here. DO NOT guess IDs. DO NOT pass the human-readable name directly.
DO NOT silently drop the filter â always resolve it.
Filter â required discovery tool (ALWAYS call the discovery tool first
when the user gives you a name instead of an ID):
âĸ department â list_departments (IDs look like cudmnt_...)
âĸ location â list_locations (IDs look like culoc_...)
âĸ cost_center â list_cost_centers (IDs look like cc_...)
âĸ entity â list_legal_entities (IDs look like le_...)
âĸ title â list_titles (IDs look like ti_...)
âĸ role â list_roles with role_type=["FUNCTIONAL"] (IDs look like role_... or aurl_...)
âĸ access â list_roles with role_type=["ACCESS"] (IDs look like role_... or aurl_...)
âĸ manager â list_users_by_name_or_email (IDs look like cuuser_...)
Decision rule: if the user says a NAME, call the discovery tool; pass only
the returned ID(s) into list_users. If the user already supplied an ID
with the expected prefix, skip discovery and pass it straight through.
â
Pagination & sorting (no discovery needed):
- cursor: Pagination cursor returned from a previous response.
- limit: Number of users to return (1-1000, default: 100).
- direction / sort: Sort direction ("asc"/"desc") and field (FIRST_NAME, LAST_NAME, EMAIL, ...).
â
Enum filters (values listed inline â no discovery tool needed):
- status: Array of UserStatus (INVITED, PENDING_ACTIVATION, ACTIVE, INACTIVE, DISABLED, ARCHIVED).
Defaults to [INVITED, PENDING_ACTIVATION, ACTIVE, INACTIVE] if omitted.
- admin_role: Single value of "ADMINS" | "NON_ADMINS" | "ALL".
â ī¸ When combining filters (e.g. "active users in Finance"), you MUST still
resolve every name-based filter via its discovery tool AND include all
requested filters in the final list_users call. Never drop a filter just
because another filter was already applied.
Example Input 1 (basic, with defaults):
{}
Example Input 2 (filter by department and role â department and role were
resolved via list_departments and list_roles first):
{
"department": ["cudmnt_1234"],
"role": ["role_5678"],
"status": ["ACTIVE"]
}
Example Input 3 (sort descending by last name, paginated):
{
"limit": 50,
"direction": "desc",
"sort": "LAST_NAME",
"cursor": "cursor_1234"
}
Example Output:
{
"items": [
{
"id": "cuuser_123",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"role": "CARD_ADMIN",
"status": "ACTIVE"
}
],
"next_cursor": "cursor_5678"
}
Get User Myself
Get the current authenticated user
This tool retrieves the profile information of the currently authenticated user making the request.
Use this when you need to get information about who is currently logged in or making the API call.
No input parameters required.
Example Output:
{
"id": "cuuser_123",
"first_name": "John",
"last_name": "Doe",
"email": "john.doe@example.com",
"role": "CARD_ADMIN",
"status": "ACTIVE"
}
List Cost Centers
List cost centers (id + display name).
REQUIRED prerequisite for the list_users `cost_center` filter: list_users
only accepts cost center IDs, so whenever the user mentions a cost center
by name (e.g. "R&D", "Sales"), call this tool first and pass the returned
`id` into list_users.
Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by name).
Example Output:
{
"items": [{ "id": "cc_1234", "name": "Engineering" }],
"next_cursor": "cursor_abc"
}
List Departments
List departments (id + name).
REQUIRED prerequisite for the list_users `department` filter: list_users
only accepts department IDs, so whenever the user mentions a department by
name (e.g. "Engineering", "Finance"), call this tool first and pass the
returned `id` into list_users.
Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by name).
Example Output:
{
"items": [{ "id": "cudmnt_1234", "name": "Engineering" }],
"next_cursor": "cursor_abc"
}
List Locations
List locations (id + name). Deleted locations are excluded.
REQUIRED prerequisite for the list_users `location` filter: list_users
only accepts location IDs, so whenever the user mentions a location by
name (e.g. "San Francisco", "New York"), call this tool first and pass
the returned `id` into list_users.
Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by name).
Example Output:
{
"items": [{ "id": "culoc_1234", "name": "San Francisco" }],
"next_cursor": "cursor_abc"
}
List Legal Entities
List legal entities (id + display name). Deleted entities are excluded.
REQUIRED prerequisite for the list_users `entity` filter: list_users
only accepts legal entity IDs, so whenever the user mentions a legal
entity by name (e.g. "Brex Inc.", "Brex UK Ltd."), call this tool first
and pass the returned `id` into list_users.
Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by display name).
Example Output:
{
"items": [{ "id": "le_1234", "name": "Brex Inc." }],
"next_cursor": "cursor_abc"
}
List Titles
List employee titles (id + display title).
REQUIRED prerequisite for the list_users `title` filter: list_users only
accepts title IDs, so whenever the user mentions a title by name (e.g.
"Software Engineer", "Product Manager"), call this tool first and pass
the returned `id` into list_users.
Parameters: limit (1-200, default 25), cursor (pagination), search_text (narrow by title name).
Example Output:
{
"items": [{ "id": "ti_1234", "name": "Software Engineer" }],
"next_cursor": "cursor_abc"
}
List Roles
List Brex account roles.
REQUIRED prerequisite for the list_users `role` and `access` filters:
list_users only accepts role IDs, so whenever the user mentions a role or
access type by name (e.g. "card admin", "employee", "bill pay approver",
"card access"), call this tool first and pass the returned `id` into
list_users.
Roles have two types:
- FUNCTIONAL ("what the user is" â CARD_ADMIN, EMPLOYEE, ACCOUNT_ADMIN, ...).
These IDs feed the list_users `role` filter.
- ACCESS ("what the user can do" â card access, bill pay approver, travel admin, ...).
These IDs feed the list_users `access` filter.
Pass role_type=["FUNCTIONAL"] to resolve names for the `role` filter,
role_type=["ACCESS"] to resolve names for the `access` filter, or omit
to return both. For FUNCTIONAL roles, is_admin=true indicates the role
grants admin-level access.
Parameters: limit (1-200, default 100), cursor (pagination), role_type (filter by type).
Example Output:
{
"items": [
{
"id": "role_1234",
"name": "CARD_ADMIN",
"display_name": "Card Admin",
"role_type": "FUNCTIONAL",
"is_admin": true
}
],
"next_cursor": null
}
Get Expense By Id
Get an expense by its ID
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 ANYTHING about receipts on this expense â including: receipt line items, itemized charges, "what did I buy", receipt content, receipt images/downloads, parsed receipt data, whether a receipt is attached/uploaded ("did the receipt come in", "is there a receipt", "do I have a receipt for this"), or receipt counts ("how many receipts") â you MUST include expand: ["RECEIPTS"]. Without expand, the response's `receipt_count` is null and `receipts` may only contain bare IDs, so questions about receipt presence or quantity cannot be answered.
A receipt with only an ID and no content/download_uri means expand was NOT used â re-call with expand: ["RECEIPTS"].
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.)
* "ACCOUNTING_FIELDS" - Includes accounting_field_values, the accounting coding fields assigned to the expense for accounting categorization and bookkeeping (for example department, class, vendor, or customer-defined accounting fields).
IMPORTANT: Location and travel data are ALWAYS null unless you explicitly request them via additional_fields. A null location does NOT mean "no location exists" - it means you did not request it. If the user asks about where an expense occurred, you MUST call this tool again with additional_fields: ["LOCATION"]. Same for travel - use additional_fields: ["TRAVEL_METADATA"].
Example 1: Getting an expense with expanded receipts (includes line items, download URL, parsed content):
{
"id": "expense_123",
"expand": ["RECEIPTS"]
}
Example 2: Getting an expense with travel metadata and location:
{
"id": "expense_123",
"additional_fields": ["TRAVEL_METADATA", "LOCATION"]
}
Example 3: Getting an expense with everything:
{
"id": "expense_123",
"expand": ["RECEIPTS"],
"additional_fields": ["TRAVEL_METADATA", "LOCATION"]
}
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
Update Expense Memo
Update memo for multiple expenses in bulk. All expenses will receive the same memo.
Parameters:
- expense_ids: Array of expense IDs to update
- memo: The memo text to apply to all expenses
Example (single expense):
{
"expense_ids": ["exp_123"],
"memo": "Business lunch with client"
}
Example (multiple expenses with same memo):
{
"expense_ids": ["exp_123", "exp_456", "exp_789"],
"memo": "Q1 team building event"
}
Upload Card Expense Receipt From Urls
Upload receipts to a card expense by downloading them from provided URLs.
This tool downloads receipts from the given URLs and uploads them to the specified card expense.
Parameters:
- expense_id: The ID of the card expense to attach the receipts to
- receipt_urls: Array of URLs where receipts can be downloaded (must be publicly accessible)
Example:
{
"expense_id": "card_exp_123",
"receipt_urls": [
"https://example.com/receipts/lunch_receipt.jpg",
"https://example.com/receipts/lunch_receipt_page2.pdf"
]
}
Replace Attendees For Card Expense
Update attendees for a card expense. This tool allows you to update both external and internal attendees to any card expense.
Note: This tool will replace the existing attendees with the new attendees provided.
Parameters:
- card_expense_id: The ID of the card expense to add attendees to
- external_attendees: Array of external attendees (people outside the company with different email domains)
- internal_attendees: Array of internal attendee IDs (company employees by customer user ID)
Internal vs External Attendees:
- Internal attendees: Company employees with the SAME email domain as the current user (e.g., @acmecorp.com)
â These require a user ID lookup using list_users_by_name_or_email
- External attendees: People from OTHER companies with DIFFERENT email domains (e.g., @vendorco.com)
â These can be added directly with just their name, title, and company info (no user ID needed)
Example workflow - Adding both internal and external attendees:
Scenario: Current user is bob.wilson@acmecorp.com adding a business dinner expense with:
- Jane Doe (jane.doe@acmecorp.com) - internal colleague (SAME @acmecorp.com domain)
- John Smith (john.smith@vendorco.com) - external vendor (DIFFERENT @vendorco.com domain)
Step 1: Identify which attendees are internal vs external by comparing email domains
- Current user: bob.wilson@acmecorp.com
- jane.doe@acmecorp.com â SAME @acmecorp.com domain â internal attendee â needs user ID lookup
- john.smith@vendorco.com â DIFFERENT @vendorco.com domain â external attendee â add directly
Step 2: Find the internal user ID using list_users_by_name_or_email
Input to list_users_by_name_or_email:
{
"search_text": "jane.doe@acmecorp.com"
}
Response from list_users_by_name_or_email:
{
"items": [
{
"id": "user_456",
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@acmecorp.com",
...
}
],
"next_cursor": null
}
Step 3: Add both internal and external attendees to the expense
Input to replace_attendees_for_card_expense:
{
"card_expense_id": "card_exp_123",
"external_attendees": [
{
"name": "John Smith",
"title": "Account Manager",
"company_name": "VendorCo",
"is_government_official": false
}
],
"internal_attendees": [
"user_456"
]
}
Assign Limit For Card Expenses
Assign one or more card expenses to a spend limit.
TERMINOLOGY: On Brex, these are called "limits" â NOT "budgets." There are two kinds: card limits (built into a card) and spend limits (exist independently). "Budget" is a separate Premium-only planning/tracking feature. When users say "budget" they almost always mean "limit." Prefer "limit" in responses unless the user is specifically asking about the Budget feature. The API returns fields named "budget_*" but these should be presented as "limits" to users.
Parameters:
- expense_ids: Array of card expense IDs to assign the limit to
- limit_id: The spend limit ID to assign to all expenses
Example (single card expense):
{
"expense_ids": ["card_exp_123"],
"limit_id": "limit_123"
}
Example (multiple card expenses with same limit):
{
"expense_ids": ["card_exp_123", "card_exp_456", "card_exp_789"],
"limit_id": "limit_abc"
}
Get Reimbursement Payout Date
Get the expected payout date for a reimbursement expense.
Returns the date when the reimbursement payment is expected to arrive.
Only works for REIMBURSEMENT type expenses that are paid through Brex.
Note: This tool will return an error if the reimbursement is configured to be paid outside of Brex
(Pay outside of Brex / PoB). In those cases, the payment is handled directly between the company
and employee (usually at payroll time), and Brex does not control the payment date.
Parameters:
- expense_id: The ID of the reimbursement expense
Example:
{
"expense_id": "expense_123"
}
Response includes:
- expense_id: The ID of the expense
- expense_type: The type of the expense (will be REIMBURSEMENT)
- expected_reimbursement_payout_date: The expected date when the reimbursement will be paid out (ISO 8601 format, UTC timezone)
- status: The current status of the expense
Start Expense Download
Start an asynchronous expense download job. Returns a job ID immediately.
IMPORTANT: Download jobs can take up to 5 minutes to complete. Use get_expense_download_result with the returned job_id to poll for completion.
Recommended polling strategy:
- Poll 5s after starting
- If PROCESSING, wait 10 seconds and poll again
- Continue with 10-second intervals until COMPLETED or FAILED
- Maximum expected duration: 5 minutes
Parameters:
- start_date (required): Start of date range (ISO 8601, UTC)
- end_date (required): End of date range (ISO 8601, UTC)
- expense_types (optional): Filter by expense types: CARD, REIMBURSEMENT, BILLPAY, CLAWBACK
- statuses (optional): Filter by statuses: APPROVED, CANCELED, OUT_OF_POLICY, SETTLED, SUBMITTED
- user_ids (optional): Filter by specific user IDs
- min_amount (optional): Minimum expense amount (USD)
- max_amount (optional): Maximum expense amount (USD)
The CSV includes 15 columns: Parent ID, Flagged Expenses, Transaction Date, Expense Type, Card Last 4, Amount, Currency, Original Amount, Original Currency, Merchant Name, User, Budget Name, Memo, Expense Status, Payment Status.
IMPORTANT: This tool is only useful if your client environment can download files from URLs. The completed export provides a download URL for the CSV file. If you cannot download files (e.g., you are in a plain chat session without filesystem access), this tool will not help â use list_expenses with pagination instead.
When to prefer this over list_expenses:
- The dataset has 50+ expenses and the task involves aggregation, analysis, or bulk processing
- Your environment can download files AND run scripts to process the CSV locally (e.g., pandas, awk, shell commands)
- This avoids loading all expense data into the conversation context
If you are unsure whether you can download files from the returned URL, ask the user before starting the export.
Example: Start export for Q1 2025:
{
"start_date": "2025-01-01T00:00:00.000Z",
"end_date": "2025-03-31T23:59:59.999Z"
}
Get Expense Download Result
Check the status of an expense download job and get the download URL when ready.
Call this after start_expense_download to poll for completion. Download jobs typically take 10-300 seconds.
Response statuses:
- PROCESSING: Job is still running. Poll again after waiting
- COMPLETED: Job finished successfully. The download_url field contains a URL to download the CSV file.
- FAILED: Job failed. The error field contains the failure reason
IMPORTANT: Recommended polling strategy:
1. Wait 5 seconds after calling start_expense_download
2. Poll every 10 seconds until status is COMPLETED or FAILED
3. Maximum expected duration: 5 minutes
The CSV file includes 15 columns: Parent ID, Flagged Expenses, Transaction Date, Expense Type, Card Last 4, Amount, Currency, Original Amount, Original Currency, Merchant Name, User, Budget Name, Memo, Expense Status, Payment Status.
If fetching `download_url` fails after status is COMPLETED: The signed URL is valid and reusable. The most common cause of a download failure is that the client environment blocks outbound requests to external hosts. If the client has a domain/URL allowlist (e.g., Claude Code Web's "Allowed domains" setting), the user must add `api.brex.com` to it before the fetch will succeed. After allowlisting, simply retry the fetch â there is no need to re-run start_expense_download.
Parameters:
- job_id (required): The job ID returned by start_expense_download
List Expenses
List expenses with comprehensive filtering, OR aggregate them by group. Use this for personal expense queries, company-wide financial analysis, AND group-by/aggregation analytics ("total spend by vendor", "monthly burn", "top departments by spend", "expense count by status").
PREFER THIS TOOL for any expense question that can be answered with filter + group_by + SUM/COUNT. That covers: "total spend by X", "top N by spend", "count of expenses by X", "monthly/weekly/daily breakdowns", "spend per vendor/department/category/user/budget/expense_type". Reserve query_expense_analytics for higher-order analytics (anomaly detection, trends quarter-over-quarter, forecasting, recommendations, vendor benchmarking) â use it only when the question genuinely requires those capabilities.
Two modes â same filters, different output:
- LISTING mode (default): omit aggregations â returns a paginated list of expenses
- AGGREGATION mode: supply aggregations (with or without group_by) â returns one row per group with computed totals/counts, or a single row when group_by is omitted. Use this for any "how many", "what's the total", "by", "per", "sum", "count", or "breakdown" question.
SINGLE-NUMBER QUESTIONS ("how many", "what's the total") â use AGGREGATION mode with no group_by:
For any question asking for ONE number (no breakdown), supply aggregations and OMIT group_by. The result is a one-row aggregation envelope keyed by your aliases.
- "How many expenses missing receipts?" â receipt_status:"RECEIPT_ABSENT", aggregations:[{func:"COUNT", field:"all", alias:"missing_receipts"}]
- "How many submitted card expenses?" â types:["CARD"], approval_statuses:["SUBMITTED"], aggregations:[{func:"COUNT", field:"all", alias:"submitted_count"}]
- "How many expenses missing memo OR missing receipt?" â documentation_missing_any:["MEMO","RECEIPT"], aggregations:[{func:"COUNT", field:"all", alias:"missing_docs"}]
- "What's our total card spend this quarter?" â types:["CARD"], purchased_at_start/end for the quarter, aggregations:[{func:"SUM", field:"billing_amount", alias:"total_spend"}]
- "What's the total amount of CLEARED transactions in May?" â payment_statuses:["CLEARED"], purchased_at_start/end for May, aggregations:[{func:"SUM", field:"billing_amount", alias:"total"}]
- SUM returns a multi-currency array (e.g. ["1234.00 USD","56.78 CAD"]) when expenses span multiple currencies â present each bucket separately or convert client-side.
BREAKDOWN QUESTIONS ("by", "per", "top N") â use AGGREGATION mode with group_by:
- "Total spend by vendor this quarter" â group_by:["vendor"], aggregations:[{func:"SUM", field:"billing_amount", alias:"total_spend"}]
- "List each vendor with its spend" / "spend for every vendor" / "vendors ranked by spend" â group_by:["vendor"], aggregations:[{func:"SUM", field:"billing_amount", alias:"total_spend"}]. Use THIS tool (not list_vendors â that only lists vendor records and has no spend) whenever the ask pairs vendors/departments/categories/users with an amount or count.
- "Monthly card burn this year" â types:["CARD"], group_by:["month"], aggregations:[{func:"SUM", field:"billing_amount", alias:"total_spend"}]
- "Top 10 departments by spend" â group_by:["department"], aggregations:[{func:"SUM", field:"billing_amount", alias:"total_spend"}], limit:10
- "How many expenses are missing receipts, BY USER?" â receipt_status:"RECEIPT_ABSENT", group_by:["user_first_name","user_last_name"], aggregations:[{func:"COUNT", field:"all", alias:"expense_count"}]
- "Expense counts by category" â group_by:["category"], aggregations:[{func:"COUNT", field:"all", alias:"expense_count"}]
RANKING / ORDER (important for "top N by spend"):
- When you pass sort_by, rows come back already sorted â present them in that order. If ranked_by.basis is set, the ranking is a USD-normalized total that nets multiple currencies together, so the per-currency amounts shown are NOT the sort key â never re-order by a single currency's figure (it produces a wrong order).
CUSTOM AMOUNT BUCKETS (e.g. "<$25, $25-$75, $75-$250, ..."):
For numeric range bucketing, make N targeted calls with min_amount/max_amount filters per bucket (each with COUNT aggregation, no group_by) and combine the results client-side.
Counting expenses:
- For a single count, use AGG mode + aggregations:[{func:"COUNT", field:"all"}] with no group_by.
- For a count broken down by a dimension, use that dimension as group_by with the same COUNT aggregation.
- receipt_status / memo_status are FILTERS, not group keys. To answer "how many missing receipts", set receipt_status:"RECEIPT_ABSENT" as a filter and aggregate with COUNT (or pair with group_by:["user_first_name","user_last_name"] for a per-user breakdown).
Time bucketing:
- Supported granularities: day, week, month, quarter, year (based on purchased_at).
- Time buckets honor the timezone parameter: bucket boundaries align to the caller's local calendar (defaults to UTC when timezone is omitted), consistent with the tz-aware date range filters.
- For yearly totals across multiple years, group by "year". For a single year's total, omit group_by entirely with a year-bounded purchased_at_start/end and a SUM aggregation.
Naming note: "merchant_category" and "category" are interchangeable group keys â both group on vendor category name. Use either.
IMPORTANT - For large LISTING results (50+ expenses): consider start_expense_download for CSV export instead. Aggregation mode collapses results to one row per group, so it's the right answer when the user wants totals rather than individual transactions.
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.
â ī¸ "show me X" is NOT a personal-scope signal. The "me" is the indirect object of "show", not a claim of ownership. Only the possessive "my"/"mine" or the subject "I" indicates personal scope.
Personal queries (use expense_owner: "ME") apply only when the user explicitly refers to themselves:
- 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..."
- Set expense_owner: "ME" only when the user message contains "my", "mine", or "I" as a subject referring to the caller.
- Treat as company-wide: "show expenses", "find expenses", "list expenses", "which expenses", "show me expenses", "expenses over $X", "expenses from [merchant]"
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.
**IMPORTANT - Bills (BILLPAY) in expenses vs list_bills tool:**
Bills appear in this tool as expenses with type=BILLPAY, but with LESS comprehensive detail than the dedicated list_bills tool.
Use this tool when bills are just ONE expense type in a broader analysis:
- Overall spending: "total expenses this month", "all expenses over $500"
- Mixed queries: "show card and bill expenses", "compare reimbursements to bills"
- General patterns without bill-specific details
Note: Bills here have minimal vendor details and NO due date information
Use list_bills tool when the user needs BILL-SPECIFIC information:
- Due dates, overdue status: "overdue bills", "bills due this week"
- Vendor details: "bills from vendor X", "how much do we owe"
- Payment schedules and comprehensive bill metadata
See list_bills tool description for full bill-specific filtering capabilities.
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).
Status Filters:
- approval_statuses: Filter by approval/review status. Commonly used: APPROVED, SUBMITTED, OUT_OF_POLICY, CANCELED (the enum also accepts internal states DRAFT, SETTLED, SPLIT, VOID).
- 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: Commonly used: DISPUTE_STATUS_IN_PROGRESS, DISPUTE_STATUS_CLOSED (also accepts DISPUTE_STATUS_CANCELLED, DISPUTE_STATUS_COMPLETE).
- reimbursement_export_statuses: EXPORTED or NOT_EXPORTED (reimbursement export state).
- user_status: Filter by spender's user status. Commonly used: ACTIVE, DELETED, DISABLED (also accepts INACTIVE, INVITED, PENDING_ACTIVATION).
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, FLIGHTS, LODGING, TRAINS, MILEAGE, MERCHANT_OR_CATEGORY, AMOUNT, OTHERS.
- government_attendees_status: GOVERNMENT_OFFICIAL_PRESENT or GOVERNMENT_OFFICIAL_ABSENT.
Field notes:
- ID filters (department_ids, card_ids, vendor_ids, merchant_ids, merchant_category_ids, expense_category_ids, expense_policy_ids, trip_ids, approver_user_ids, next_approver_user_ids, limit_ids, user_ids) accept IDs only, never names. Resolve names to IDs first with the matching list_* tool (e.g. list_departments, list_vendors, list_merchants, list_merchant_categories, list_expense_categories, list_active_and_upcoming_travel_trips, list_users_by_name_or_email, list_my_limits).
- ERP debit GL account filter (send both parts together): (1) call list_gl_accounts, (2) copy gl_account_field.key into erp_debit_gl_account_field_key, (3) copy one or more accounts[].identifier values (NOT id, NOT value) into erp_debit_gl_account_option_ids. The key is dynamic per accounting integration (shape "custom_gl_account_<uuid>") â never hardcode or guess it. Sending only one of the pair returns a 400.
- group_by dimensions: vendor, vendor_id, category, category_id, merchant_category, merchant_category_id, department, budget, expense_type, expense_status, payment_status, user_first_name, user_last_name, user_id, cost_center. Time buckets: day, week, month, quarter, year. group_by requires at least one aggregation; receipt_status and memo_status are filters, not group keys. Use *_id group keys only when chaining the result back into a filter; otherwise prefer the human-readable name variant.
- aggregations: each entry is { func: SUM | COUNT, field, alias }. SUM is meaningful only on amount fields (billing_amount = USD spend, original_amount = transaction currency, customer_invariant_amount = single comparable currency). COUNT can target any field â use field:"all" for count of expenses. The alias becomes the result-row key.
All dates should be in ISO 8601 format. Results are paginated - use limit and cursor for pagination.
Get Active Integration
Get the currently active accounting integration.
Returns { "id": null, "vendor": null } if no active accounting integration is found.
Example response:
{
"id": "SW50ZWdyYXRpb246NzEwOWU5YWMtYWRiZi00MGZjLTliMzMtZTE4OTBjYTk1MzM1",
"vendor": "QuickBooks Online"
}
List Accounting Records
List accounting records with filters and pagination.
This tool returns accounting records with the full record shape, including amounts, source information,
users, vendors, receipts, and line items.
Supported filters:
- ids: specific accounting record IDs
- review_status: workflow stage for CARD and REIMBURSEMENT records
- source_type: high-level source filter such as CARD, REIMBURSEMENT, or BILL
- updated_at: gt/gte/lt/lte timestamp filters for polling
- erp_posting_date: inclusive from/to timestamp filters for ERP posting date (accruedAt) range
- timezone: IANA timezone for interpreting date-only and local datetime filters; defaults to UTC
- single_entry: return single-entry line items instead of the default double-entry view
- cursor and limit: pagination controls
Date filters accept date-only strings (e.g., "2025-05-06"), local datetimes
(e.g., "2025-05-06T14:00:00"), or UTC/offset datetimes. Date-only and local
datetime values are converted to UTC using timezone. Always tell the user
which timezone was used when presenting date-filtered results.
Constraint:
- review_status is not supported with source_type=BILL
List Gl Accounts
List all available GL accounts for the active accounting integration.
This tool executes a 3-step process:
1. Get the active accounting integration ID
2. Use the integration ID to get the extended field ID for GL accounts
3. Use the extended field ID to get all GL account options
Returns an object containing:
- accounts: Array of GL accounts
- glAccountField: The extended field definition for GL accounts
- gl_account_type: Nullable GL account type on each account when the ERP provides it
Returns null if no active integration is found.
Example response:
{
"glAccountField": {
"id": "extended_field_cm9vkatzo0b8e0i36rxhz7z4r",
"key": "user_category_int_cm9vkas3n00zx0e00zsk25h7z",
"name": "GL Account",
"status": "ACTIVE"
},
"accounts": [
{
"id": "efo_cm9vkauq30b9h0i36k2r3p66f",
"identifier": "1328446901",
"value": "1010 Cash",
"status": "ACTIVE",
"gl_account_type": "ASSET"
},
{
"id": "efo_cm9vkauq30b9i0i36pkb9lzan",
"identifier": "-1076004205",
"value": "1020 Accounts Receivable",
"status": "ACTIVE",
"gl_account_type": null
}
]
}
List Cards
List cards with comprehensive filtering. Use this for both personal card queries and company-wide card management.
đ IMPORTANT - How to scope card queries with card_holder:
Personal queries (use card_holder: "ME"):
- "my cards", "my locked cards", "do my cards have..."
- "which of my cards is active"
- "show me my cards"
â SET card_holder: "ME" to return only the calling user's cards
IMPORTANT DEFAULT BEHAVIOR: When the query is ambiguous (no explicit "company/all/team" scope), default to card_holder: "ME" since users typically want their own cards.
Company-wide queries (omit card_holder):
- "all company cards", "list all cards", "company card inventory"
â OMIT card_holder to return all cards across the organization (admin only)
Specific user queries (use user_ids):
- "John's cards", "show Alice's cards"
â First call list_users_by_name_or_email to get user ID, then pass user_ids parameter
You can filter by status views (ACTIVE, EXPIRED, LOCKED, TERMINATED, WAITING_ACTIVATION)
and card holder user IDs.
Results are paginated - use limit and cursor for pagination.
Attributing a returned card to a person (e.g. "which are Alex's cards?"): rely on each card's `user` field â the current, authoritative cardholder. Do NOT use holder_name (the *original* holder's name, which can be stale if the card was reassigned) or display_name (just the card's label/nickname, e.g. "Salesforce"). On any mismatch, trust `user`.
IMPORTANT: card_holder and user_ids are mutually exclusive. Use card_holder for self-scoping or user_ids for specific user IDs, but not both.
Filtering by card type (card_category) â useful for "check before create" flows:
- To look for an existing P-Card before creating one, pass card_category: ["PURCHASING_CARD"] and do NOT set search_query â fetch the broad list and judge contextual relevance yourself (e.g. a request for a "Figma card" may already be covered by a "Design Tools" or "SaaS Subscriptions" card).
- To check whether a specific user already has an employee card, pass user_ids: [their_id] together with card_category: ["EMPLOYEE_CARD"]. EMPLOYEE_CARD covers both funded and $0-limit cards â read the returned card's limit to tell them apart.
- Other categories (SPEND_LIMIT_CARD, USER_LIMIT_CARD, BILL_PAY_CARD, CARD_SPEND_CONTROL_CARD) are less common.
Filtering by card form (card_form) â useful before calling ship_physical_card:
- ship_physical_card only works on VIRTUAL cards (it issues the physical counterpart). Pass card_form: ["VIRTUAL"] to scope results to eligible cards before confirming which one to ship.
Example 1: Getting all my active cards:
{
"card_holder": "ME",
"status": ["ACTIVE"]
}
Example 2: Getting all my cards (any status):
{
"card_holder": "ME"
}
Example 3: Getting all active cards (admin):
{
"status": ["ACTIVE"]
}
Example 4: Getting all active and locked cards for specific users:
{
"status": ["ACTIVE", "LOCKED"],
"user_ids": ["user_123"]
}
Example 5: Getting cards for a specific user:
{
"user_ids": ["user_123"]
}
Example 6: Listing the company's purchasing cards (P-Card check-before-create â do NOT pass search_query):
{
"card_category": ["PURCHASING_CARD"]
}
Example 7: Checking whether a specific user already has an employee card:
{
"user_ids": ["cuuser_abc123"],
"card_category": ["EMPLOYEE_CARD"]
}
Get Card By Id
Get a card by its ID, including its current spend configuration (merchant category controls and expense policy).
List My Limits
Get spend LIMITS for the current user â amounts, balances, names, and IDs. This is NOT a policy catalog and does NOT return policy rules.
TERMINOLOGY: On Brex, these are called "limits" â NOT "budgets." There are two kinds: card limits (built into a card) and spend limits (exist independently). "Budget" is a separate Premium-only planning/tracking feature. When users say "budget" they almost always mean "limit." Prefer "limit" in responses unless the user is specifically asking about the Budget feature. The API returns fields named "budget_*" but these should be presented as "limits" to users.
**WHEN TO USE:**
- "My limits", spending limits, balances, remaining amount, limit names/IDs
- Resolving a limit name to an ID for list_expenses, list_cards, or get_expense_policy
- FIRST step before get_expense_policy when user asks policy RULES tied to their spending (receipts, approvals, "can I expense X on my card?")
**WHEN NOT TO USE â pick a different tool instead:**
- User wants to LIST or DISCOVER account expense policies (catalog, default policy, policy names) â list_expense_policies
Examples: "What expense policies do we have?", "Show me the default expense policy", "Which policy is default?"
- User already has a spend_limit_id and wants full policy rules â get_expense_policy directly
**Three-tool routing (policies vs limits):**
| User wants | Tool |
| --- | --- |
| Account policy list / which is default | list_expense_policies |
| My limit balances / limit names & IDs | list_my_limits (this tool) |
| Policy rules on a limit (receipts, approvals) | list_my_limits â get_expense_policy |
DO NOT use list_users_by_name_or_email when the user asks about their own limits, even if the limit name contains a person's name.
DO NOT use this tool for account-level policy catalog questions â use list_expense_policies.
For policy-RULE questions (not catalog): call this tool first to get spend_limit_id, then get_expense_policy. If only one active limit, use it automatically.
This includes:
- User Limit: personal spending limit for the user
- Spend Limits: shared limits where the user is a member
Each limit shows:
- Limit amount and remaining balance
- Period type (MONTHLY, QUARTERLY, etc.)
- Status (ACTIVE, EXPIRED, etc.)
- Start and end dates
- Amount spent in current period
Pagination:
- 'limit': how many to return (default 100, max 1000)
- 'cursor': use next_cursor from previous response
SCENARIO-BASED EXAMPLES:
Example 1: Get all my limits (default - returns up to 100 limits):
{}
Example 2: Get first 10 limits (useful for large accounts):
{
"limit": 10
}
Example 3: Get next page of limits:
{
"limit": 10,
"cursor": "eyJhZnRlciI6IjEwIn0="
}
TOOL CHAINING WORKFLOWS:
Scenario 1: "How much is left on my Marketing Q1 limit?"
â Call list_my_limits with {} to get all limits
â Find limit where name="Marketing Q1", extract ID (e.g., "spl_abc123")
â Present the available balance from the "available" field
Scenario 2: "Show me all expenses on my Travel & Entertainment limit"
â Call list_my_limits with {} to get all limits
â Find limit where name contains "Travel", extract ID (e.g., "spl_xyz789")
â Call list_my_expenses with:
{
"limit_ids": ["spl_xyz789"]
}
Scenario 3: "Can I expense Uber Eats on my company card?" (policy RULES â not catalog)
â Call list_my_limits with {} to get all limits
â If user has only one active limit, extract its ID (e.g., "spl_policy123")
â Call get_expense_policy with:
{
"spend_limit_id": "spl_policy123"
}
â Check policy rules for Uber Eats / Food Delivery merchant restrictions
Scenario 4: "Do I need approval for a $200 dinner?" (policy RULES)
â Call list_my_limits with {} to get limit IDs
â Extract relevant limit ID (e.g., "spl_corp456")
â Call get_expense_policy with:
{
"spend_limit_id": "spl_corp456"
}
â Check policy rules for approval thresholds on meal expenses
Scenario 5: "What did I spend on my Q1 Marketing limit last month?"
â Call list_my_limits with {} to find "Q1 Marketing" limit
â Extract limit ID (e.g., "spl_mkt789")
â Call list_my_expenses with:
{
"limit_ids": ["spl_mkt789"],
"purchased_at_start": "2025-03-01T00:00:00.000Z",
"purchased_at_end": "2025-03-31T23:59:59.999Z"
}
Scenario 6: "What are the rules for my Travel limit?" (policy RULES on named limit)
â Call list_my_limits with {} to find "Travel" limit
â Extract the Travel limit ID (e.g., "spl_travel101")
â Call get_expense_policy with:
{
"spend_limit_id": "spl_travel101"
}
â Present the complete policy rules from the response
Scenario 7: "Show me the default expense policy" (policy CATALOG â not this tool)
â Call list_expense_policies with { "is_default": true }
â Returns policy id, display_name, description, is_default (summaries only)
Get Vendor By Id
Get a vendor by ID
List Vendors
Get all vendors for the current authenticated user. Results are paginated - use limit and cursor for pagination.
IMPORTANT: Always use search_text to filter results when users ask about
specific vendors, categories, or contact information. This tool is designed
for efficient searching and filtering.
Parameters:
- cursor: Pagination cursor for next page of results
- limit: Default 30 | Max 100
- search_text: Text to filter vendors by name
- status: Optional single vendor status to filter by (ACTIVE, DELETED, PENDING, DRAFT, DECLINED, or MERGED)
* If omitted: Returns only ACTIVE vendors (default backend behavior)
* If empty array []: Returns vendors of ALL statuses
* If specified: Returns only vendors with that single status
* NOTE: Only ONE status can be filtered at a time
Search capabilities:
- Text search: Searches vendor name, legal name, and business name fields (case-insensitive, partial matching)
- Status filtering: Filter by a single vendor status at a time
- Combined filtering: Use both search_text and status together for precise results
Example usage:
- "Show me all my vendors" (only ACTIVE by default):
{
"limit": 100
}
- "Show me ALL my vendors regardless of status":
{
"status": [],
"limit": 100
}
- Search for a specific vendor by name across ALL statuses:
{
"search_text": "Acme",
"status": [],
"limit": 25
}
- Find active software vendors:
{
"search_text": "Software",
"status": ["ACTIVE"],
"limit": 100
}
- Search by business name (ACTIVE by default):
{
"search_text": "Corp",
"limit": 10
}
Get Expense Policy
Get the full RULES of the expense policy attached to a specific spend limit (receipts, memos, approvals, merchant restrictions).
TERMINOLOGY: On Brex, these are called "limits" â NOT "budgets." There are two kinds: card limits (built into a card) and spend limits (exist independently). "Budget" is a separate Premium-only planning/tracking feature. When users say "budget" they almost always mean "limit." Prefer "limit" in responses unless the user is specifically asking about the Budget feature. The API returns fields named "budget_*" but these should be presented as "limits" to users.
**WHEN TO USE (policy RULES on a limit):**
- User asks whether a specific expense is allowed, or what compliance rules apply on THEIR limit
- Examples: "Do I need a receipt for this $30 lunch?", "Can I expense alcohol?", "Who approves my $500 dinner?", "Can I expense Uber Eats?", "What are the rules for my Travel limit?"
**WHEN NOT TO USE â pick a different tool instead:**
- User wants to LIST or DISCOVER account policies (names, which is default, how many exist) â use list_expense_policies (e.g. "What expense policies do we have?", "Show me the default expense policy" with is_default: true)
- User wants limit balances, remaining spend, or limit names/IDs only â use list_my_limits (e.g. "How much is left on my Marketing limit?")
**Requires spend_limit_id.** When the user asks policy-RULE questions without naming a limit:
1. Call list_my_limits to get limit IDs
2. If only one active limit, use its ID automatically
3. If multiple limits and context is unclear, ask which limit
This tool returns rules in the same format as the Dashboard "View policy" sidebar (structured JSON).
**What you'll get:**
- formatted_text: Human-readable policy text matching Dashboard display
- sections: Array of policy sections with rules
- has_restrictions: Boolean indicating if there are any policy restrictions
- budget_name: Name of the limit
- policy_name: Name of the policy
**Parameters:**
- spend_limit_id: **REQUIRED** - Limit ID from list_my_limits (e.g. spl_abc123).
- rules_filter: **OPTIONAL** - "ONLY_RELEVANT_FOR_REQUESTER" (default) or "ALL_RULES" (admin; all user exceptions).
**Response Format:**
Returns structured JSON with formatted_text, sections[], has_restrictions, budget_name, policy_name.
Submit Feedback
Submit feedback about the Brex API or MCP tools to the Brex product team on behalf of the user.
This feedback is reviewed by the product team and used to prioritize improvements.
WHEN TO USE THIS TOOL:
- When a tool cannot fulfill the user's request due to missing functionality or unsupported filters.
Example: User asks to filter expenses by custom field, but list_expenses doesn't support that filter.
-> submit_feedback with type "limitation" and describe the missing filter capability.
- When list or query tools return empty or unhelpful results for a reasonable request.
Example: User asks "show me spend by department last quarter" but no tool supports that aggregation.
-> submit_feedback with type "limitation" describing the analytics gap.
- When the user explicitly asks to share a suggestion or report a problem with Brex tools.
- When a tool returns an error indicating a platform limitation (not a user input error).
Example: "This operation is not supported for this card type."
-> submit_feedback with type "bug" including the error message and context.
- When accomplishing a task requires an unreasonably complex sequence of tool calls that could be simplified.
Example: Getting a budget summary requires 4 separate API calls that could be one.
-> submit_feedback with type "suggestion" describing the desired simplified workflow.
- You should proactively submit feedback when you encounter tool limitations, even if the user hasn't explicitly complained.
WHEN NOT TO USE:
- Authentication or permission errors - help the user fix their token or scopes instead.
- Invalid input errors - help the user correct their input.
- Transient errors - retry the original tool first.
SOURCE FIELD:
- Use source 'agent' when YOU (the AI assistant) identify a gap, limitation, or issue while helping the user. You should proactively submit feedback when you encounter tool limitations, even if the user hasn't explicitly complained.
- Use source 'user' when the user explicitly asks to submit feedback or report a problem.
IMPORTANT: Always inform the user before submitting feedback. Briefly explain what you're reporting and why.