- Brand
- Brex
- Category
- Finance
- Primary Subcategory
- Corporate Spend, Expense & Procurement
Integration details
Description
Brex helps finance teams and employees review company spend through ChatGPT. Users can look up expenses, cards, limits, users, bills, vendors, and accounting records; analyze spend; attach receipts from HTTPS URLs; update memos and attendees; assign card expenses to limits; export expense data; and submit product feedback.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Corporate Spend, Expense & Procurement
- Secondary Subcategories
- None listed
- Brand
- Brex
- Access
- Account required
- First tracked
- 2026-09-21
- Tool count
- 67
- Market
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Your score is coming
ChatGPT now suggests Plugins on its own when they match a user's request.Your Plugin Discovery Score measures how often yours appears, and it will show here as soon as it’s ready.
What discovery looks like

Get alerts for Brex
Get updates when Brex’s Discoverability Score or category rank changes.
Competing in ChatGPT Corporate Spend, Expense & Procurement
View Category67 tools agents can invoke
Assign a spend limit or user limit to a card. The system will automatically determine whether the provided limit ID corresponds to a spend limit or user limit. Example 1: Assigning a spend limit to a card: { "card_id": "card_123", "limit_id": "limit_123" } Example 2: Assigning a user limit to a card: { "card_id": "card_123", "limit_id": "limit_123" } — Confirmation gate (REQUIRED, do this before EVERY call) — 0. This REPLACES the card's limit source rather than adding a second one, and the tool cannot read back what funded the card before. Never describe the change as additive, and never state a "from <current>" you cannot see. 1. Resolve both objects by name first — list_cards for the card, list_spend_limits or list_my_limits for the limit — and present them by display name. Suggested format: You're moving <card display name> (last 4: <last4>) onto the <limit display name> limit Spend on the card will draw from that limit from now on, replacing whatever funds it today. 2. Ask a yes/no question whose ONLY purpose is consent. Wait for the answer. 3. Treat answers to clarifying questions (which card, which limit) as INPUTS, not consent. The yes/no is a separate, dedicated turn. 4. Only after an explicit yes do you emit the assign_limit_to_card tool call. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary.
assign_limit_to_card
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" }
assign_limit_for_card_expenses
Cancel a card permanently. Works for purchasing cards, employee cards, and spend-limit cards. This cannot be undone — a cancelled card cannot be reactivated; issue a new card instead. If any of these are true, this tool is NOT to be called. Recommend the alternative and stop. - Operator wants to temporarily pause spend (reversible) → use lock_card, not cancel_card. - Operator wants a new card number and a replacement card → use replace_card, not cancel_card. - Operator wants to change WHO holds the card while keeping its number → use transfer_card. - Operator wants to change the limit, name, policy, or controls → use update_purchasing_card / update_employee_card. - The card is already cancelled → calling this tool again is a harmless no-op; it will report that nothing changed rather than erroring. — Resolving the card — If the operator names it by vendor / display name / last4 ("cancel the Figma card"), call list_cards FIRST. Read the current holder from the `user` field — NEVER holder_name, which is the name embossed at issuance and is stale on any card that has been transferred. If more than one candidate matches, present them (display name, last4, cardholder) and ask which one; never guess. — Talking to the operator — A cancelled card reads as TERMINATED on the wire; to the operator it is "cancelled", never "terminated". Mention the card's state only when it adds something, and skip it entirely when it does not. When reporting a completed cancellation, carry the permanence over into your own words. "Cancelled" and "can no longer be used" both read as a reversible pause to an operator who also uses lock_card, so say that it cannot be undone and that a replacement means issuing a new card. Say it again in the final report even though the confirmation recap already said it: the report is what the operator keeps. The result's message states this; paraphrasing it away is the failure to avoid. — Reason — CARD_LOST and CARD_DAMAGED apply to physical cards only — using either on a non-physical card is rejected. NO_LONGER_NEEDED covers both physical and virtual cards and is the right default for "we don't need this anymore" / offboarding without a transfer. FRAUD marks later declines as fraud-related rather than simply "card cancelled" — only use it when the operator says the card was compromised. Everything else is OTHER (the default when omitted). — Confirmation gate (REQUIRED, do this before EVERY call) — 1. Present the card being cancelled and what cancellation means. Suggested format: You're cancelling: <display name> (last 4: <last4>), held by <cardholder> This cannot be undone: the card will stop working immediately, any pending physical shipment will be cancelled, and recurring subscriptions billed to it will start declining rather than being cancelled automatically. 2. Ask a yes/no question whose ONLY purpose is consent. Wait for the answer. 3. Treat answers to clarifying questions (which card) as INPUTS, not consent. The yes/no is a separate, dedicated turn. 4. Only after an explicit yes do you emit the cancel_card tool call. — Retry policy — Do NOT automatically retry on an uncertain failure — re-check with get_card_by_id instead. A repeat call after a successful cancellation is a no-op, not a double-cancel, so retrying a call whose outcome is unclear is safe, but blind automatic retries still are not the default here — confirm with the operator first. — Example scenario — Operator: "Chris left the company — cancel his Figma card." 1. Call list_cards, find the Figma card, confirm Chris currently holds it. 2. Recap: "Cancelling Figma (last 4: 2836), held by Chris Reporter. This cannot be undone: the card will stop working immediately and subscriptions billed to it will start declining. Proceed?" 3. On "yes," call cancel_card with the resolved card ID and reason "NO_LONGER_NEEDED". 4. Report the outcome in plain language, permanence included: "Cancelled the Figma card ending 2836. This can't be undone — if the team still needs Figma, issue a new card." Do NOT say "status is now TERMINATED." SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary.
cancel_card
Issue up to 10 virtual employee cards and set each user's monthly employee-card limit in one call. — What this tool does — This tool creates an employee card for travel, entertainment, and other employee expenses. Before anything, when the operator asks for an employee card, BEFORE any clarifying question about configurations such as the limit: 1. Call list_cards once with card_category: ["EMPLOYEE_CARD"] and user_ids containing every distinct target cardholder ID. Each user can have at most one active employee card. 2. If an active employee card already exists for any user (status ACTIVE, WAITING_ACTIVATION, or LOCKED), surface it FIRST and recommend update_employee_card for that user. Exclude that user from the create batch unless the operator changes the request. The service also reports duplicates as per-card failures with EMPLOYEE_CARD_ALREADY_EXISTS. 3. Call list_employee_card_limits with limit: 100 (the maximum page size) to look up whether each target cardholder already has a spendable employee-card limit on file, following next_cursor for further pages until it comes back null so a match isn't missed on a later page. Use this as the primary source for the "existing non-zero limit → propose it as default" logic below — prefer it over inspecting a nested USER_LIMIT off a TERMINATED card from step 1. If list_employee_card_limits fails with a permission/access error (missing scope, permission, or feature flag) rather than a network/timeout error, treat this check as unavailable and fall back to the TERMINATED-card USER_LIMIT check from step 1 instead of blocking the flow. 4. Call list_spend_limits with status: ACTIVE and limit: 100, following next_cursor the same way, and scan every returned name for anything topically related to the operator's stated reason for the card — the same event, offsite, trip, or project (e.g. a "NYC Offsite" spend limit when the operator wants a card for someone attending the NYC offsite). If a clearly related spend limit exists, surface it FIRST and ask whether the operator wants to add the person to that existing spend limit via the Brex dashboard instead of creating a new employee card — a spend limit already represents shared/event-scoped spend that a per-user employee card can't. If list_spend_limits fails with a permission/access error rather than a network/timeout error, treat this check as unavailable and continue the employee-card flow normally — a caller authorized to create employee cards is not guaranteed the separate access either listing tool requires, and that must never block card creation. 5. For users with no active employee card, no relevant spend limit hand-off, and no other blocker, present the complete proposed batch for confirmation. This is an internal preflight — do not mention it unless an existing active employee card or a relevant spend limit was found. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary. - Before creating, always show the final proposed setup and ask a yes/no confirmation. - Answers to missing-field questions are inputs, not confirmation to create. — Definitions — Employee cards What it is: Employee cards are for employee T&E and incidental spend. They can be physical or virtual and can be used with employee card limits / spend limits. Best for: Individual employee-driven spend where the employee needs general access to funds for travel, meals, or other incidental business expenses. Not best for: Recurring vendor subscriptions, supplier payments, department-owned operational spend, or spend that should remain attached to a dedicated operational card. Example use cases: Meals, travel, lodging, airfare, rideshare, client entertainment, recurring per-person allowances. Employee card limits What it is: Employee card limits are optional monthly limits that apply only to employee cards and cannot be used for reimbursements. If the limit is set to $0, the employee card can only be used with separately issued spend limits. Spend controls: Monthly limit amount, per-transaction maximum, limit flexibility (none, 5%, 10%, 25%, max), default policy, limit increase requests. Merchant controls can be set via the default policy. Best for: General monthly guardrails on employee spending. T&E spend use cases of employee cards. Not best for: Shared spending pools across multiple users or dedicated vendor spending. Spend use cases of purchasing cards (operational spend). Needing spend to reference a non-default policy (employee card limits can only reference the default policy). Limit recurrence that is not monthly. Needing advanced spend controls only available through spend limits. — Scope of THIS tool — - Issues virtual employee cards during creation. To create a physical employee card, first use this tool to make a virtual card and ship separately once the card exists through the shipping tool. - Supported per-card inputs: customer_user_id, limit_amount (monthly), limit_currency. - Not yet supported: per-transaction maximum, limit flexibility, custom policy, limit increase requests. - The limit always resets MONTHLY. There is no weekly, quarterly, annual or one-time option. When the operator asks for any other cadence ("$1,000 a week"), do not create yet: tell them employee-card limits reset monthly only and ask which monthly amount to use. Never convert the amount yourself, and never describe an employee-card limit as anything but monthly, before or after creating. - Create-only: rejects with EMPLOYEE_CARD_ALREADY_EXISTS if the user already has an active employee card. Returns card_id and user_limit_id on success. - limit_amount is optional. If the operator did not specify a limit but list_employee_card_limits (preflight step 3) returned a non-zero spendable limit for the user, present that total as the default configuration. If list_employee_card_limits found nothing but a returned card from step 1 carries a non-zero nested USER_LIMIT total, use that instead (it stays valid even when the card itself is TERMINATED). Otherwise, omitting it defaults the limit to $0. Pass an explicit value (such as "0" or "100") to set/overwrite the limit. - IMPORTANT: when limit_amount is omitted, do NOT ask "what monthly limit would you like?" just because no limit was specified. Instead, propose the default configuration in the confirmation message: - existing non-zero employee-card limit on file -> present that existing limit - no existing non-zero employee-card limit on file -> present $0 / monthly Only ask a follow-up about the limit if the operator rejects the proposed configuration or asks for a different recommendation. — When this tool is NOT the right fit (summary of adjacent spend objects) — P-Cards: dedicated cards for operational/vendor spend (SaaS, recurring suppliers, departmental, facilities) with a per-card limit and policy. Best when spend should live on a vendor- or project-scoped card rather than on an employee's general card. Call create_purchasing_card instead of this tool for P-Card requests. Spend limits: purpose-driven controls for shared funds across multiple users, time-boxed group spending / events, rollover of unused balance, reimbursements, delegated limit ownership, or non-default policy routing where a P-Card isn't the right fit. Creation is NOT in scope here — recommend and hand off to the Brex dashboard. Always call list_spend_limits first (see preflight step 4 above) to check whether a topically-related spend limit already exists before recommending the operator create a new one. Spend limit groups: when each person needs their own limit rather than a shared pool. Creation is NOT in scope here — recommend and hand off to the Brex dashboard. Spend Limit cards: virtual cards tied to a single spend limit (optional, for stipend / travel-limit use cases). Creation is NOT in scope here. In general, spend limits and spend limit cards should be a fallback from the core employee card (with employee card limit) and P-Cards. — Core rules before calling — 1. Reason across all Brex spend objects before deciding. Don't default to an employee card just because employee-card creation is one of the only write flows in scope. — Confirmation gate (REQUIRED, do this before EVERY call) — 1. Once every required field is gathered or proposed, assemble the exact final configuration for every cardholder — monthly limit and currency — and present the complete batch in one numbered list, in the shape of the example flow below. 2. Ask a single yes/no question whose ONLY purpose is consent, covering the whole batch. Wait for the answer. 3. Treat answers to clarifying questions (whose card, what limit) as INPUTS, not consent. The yes/no is a separate, dedicated turn. 4. If any item changes, re-present the complete updated batch and ask again. 5. Only after an explicit yes do you emit the create_employee_card tool call. — Required-field guidance — - Cardholder (customer_user_id): infer only when named explicitly; otherwise ask for name or email and resolve via list_users with search_text. If list_users with search_text returns more than one match, do NOT pick one — present the candidates (name, email, role) and ask the operator which one. — Batch requests — - Put every confirmed employee card in the cards array. Each item is self-contained. - A call may contain at most 10 cards. For larger confirmed requests, make follow-up calls containing at most 10 cards each. - After the call, inspect every result and report created and failed users separately. Example Flow (match this shape and tone; you must present configuration as such before creating a card): User: "I want a T&E card for Jade" Agent: If there is no existing employee-card limit on file and the operator did not specify one, the first message should still present configuration instead of asking for a limit: "I recommend an employee card for Jade Lee since this looks like general T&E spend. Here is the proposed setup: - Cardholder: Jade Lee - Card limit: $0 / monthly (default) - Card form: Virtual Employee Card Should I create this employee card?" If list_employee_card_limits returns a non-zero spendable limit for the user (or, absent that, list_cards shows only TERMINATED employee cards where one of those card records includes a nested USER_LIMIT with a non-zero total), use that existing limit as the proposed default: "I recommend an employee card for Jade Lee since this looks like general T&E spend. Here is the proposed setup: - Cardholder: Jade Lee - Card limit: $80 / monthly (existing user limit) - Card form: Virtual Employee Card Should I create this employee card?" ─── — Retry policy — This call is NOT idempotent. Review every per-card result before retrying. For a network failure, timeout, or uncertain upstream failure, call list_cards for the affected users before offering to submit only cards confirmed to be missing. Never resubmit a result marked created. — Example scenario (T&E request) — Operator: "I need a card for [employee name]." 1. Confirm intent: is this for general T&E (meals, flights, hotels, client entertainment)? 2. If yes: recommend an employee card and briefly explain. Do not ask for a limit — propose the default configuration per the limit_amount guidance above (existing non-zero limit on file, else $0/monthly). 3. Resolve the employee's name → customer_user_id via list_users with search_text. 4. Present the complete batch for one confirmation (see example above). 5. On "yes," call this tool once with all confirmed cards. On "no," ask what to edit or cancel, then re-present the complete batch. If the operator wants spend controls employee card limits don't support (non-default policy, non-monthly recurrence, rollover, shared pool, etc.), the right structure is an employee card (limit $0) + a separately issued spend limit. Spend-limit creation is NOT in this tool — recommend and hand off. — Example scenario (existing spend limit hand-off) — Operator: "Create an employee card for Sam Rivera for the NYC offsite." 1. Preflight step 4 already ran list_spend_limits with status: ACTIVE and found a "NYC Offsite" spend limit. 2. Do NOT propose creating a new employee card for this. Surface the existing spend limit instead: "There's already an active 'NYC Offsite' spend limit set up for this. I'd recommend adding Sam Rivera to that limit through the Brex dashboard rather than creating a new employee card, since it already covers shared spend for the event." 3. Only fall back to proposing a new employee card if the operator explicitly says the offsite spend limit isn't what they want (e.g. they want Sam's general T&E card instead). Example 1 — virtual employee card, $5,000/month USD (substitute the actual resolved customer_user_id): { "cards": [{ "customer_user_id": "<resolved_customer_user_id>", "limit_amount": "5000.00", "limit_currency": "USD" }] } Example 2 — two employee cards in one call: { "cards": [ { "customer_user_id": "<first_resolved_customer_user_id>", "limit_amount": "5000.00", "limit_currency": "USD" }, { "customer_user_id": "<second_resolved_customer_user_id>", "limit_amount": "0", "limit_currency": "USD" } ] }
create_employee_card
Issue up to 20 virtual purchasing cards (P-Cards) for operational spend in one call. — What this tool does — This tool creates one or more P-Cards, each with its own name, primary cardholder, expense policy, and recurring spending limit. Cards are issued as VIRTUAL during creation; physical cards can be ordered separately afterward. Before anything, the moment the operator asks for one or more P-Cards ("make cards for Zoom and Figma", "create a P-Card for LinkedIn"), BEFORE any clarifying question about cardholder / limit / policy / frequency: 1. Call list_cards ONCE with card_category: ["PURCHASING_CARD"] to scope the search to existing P-Cards (no search_query). Do NOT pass user_ids — duplicates can be held by any cardholder. 2. Scan the returned displayName / holderName against every proposed card for anything topically related — exact match, vendor synonyms ("LinkedIn" ≈ "Professional Networks", "Zoom" ≈ "Video Conferencing", "Figma" ≈ "Design Tools" / "SaaS Subscriptions"), or category overlap. 3. Call list_spend_limits with status: ACTIVE and limit: 100 (the maximum page size) to scope the search to existing spend limits, and follow next_cursor for further pages until it comes back null — an account can have more active spend limits than fit on one page, and stopping early risks missing the relevant one. Scan every returned name the same way as step 2 for anything topically related to the proposed card(s) — the same event, project, department, or vendor (e.g. a "NYC Offsite" spend limit when the operator asks for a card for someone attending the NYC offsite). If list_spend_limits fails with a permission/access error (missing scope, permission, or feature flag) rather than a network/timeout error, treat this check as unavailable and continue the P-Card flow normally — a caller authorized to create P-Cards is not guaranteed the separate access this listing tool requires, and that must never block card creation. 4. If likely duplicates exist (from either step 2 or step 3), surface all flagged items to the operator FIRST and ask whether to create another, reuse, edit, or remove each one. For a topically-related spend limit specifically, explain that shared/group spend already has a home there and recommend managing it (adding the person, adjusting the amount) through the Brex dashboard instead of issuing a new P-Card — P-Card creation cannot join an existing spend limit. Only include duplicate-risk cards in the batch after the operator explicitly chooses to create another. This is an internal preflight. If no relevant existing P-Card or spend limit is found, continue naturally and do not mention the preflight. If a relevant existing P-Card or spend limit is found, only mention the existing object itself. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary. - Before creating, always show the final proposed setup and ask a yes/no confirmation. - Answers to missing-field questions are inputs, not confirmation to create. - Terminology: when a card's status is TERMINATED, call it "cancelled" in messages to the operator. — Definitions — Purchasing cards (P-Cards) What it is: Purchasing cards (P-cards) are made for operational spend, like one-time and recurring vendor payments and departmental spend. They have built-in limits and are limited to virtual only during creation, but physical cards can be ordered after the initial creation. P-cards are optimized for continuity of recurring operational spend when you replace or transfer card ownership. Spend controls: any policy, limit amount, limit flexibility, limit recurrence (one-time, weekly, monthly, quarterly, annually), start/end date, accounting coding rules, entity billing, limit increase requests, merchant controls, per-transaction maximum. Best for: Controlled procurement spend with configurable spending limits and accounting pre-coding. P-cards are best when spend should live on a dedicated operational card rather than on an individual employee's general spending card. Not best for: Individual employee travel and expenses (T&E) spend. Some spend limit-specific use cases: shared funds across multiple users, when there is a need to rollover unused recurring limit balance, structured reimbursements. Example use cases: SaaS, vendor payments, recurring supplier spend, department spend, facilities, office spend, project operational spend. Shared purchasing cards What it is: A shared P-Card is an ordinary purchasing card that more than one person can spend on. There is still one card number and one limit, and everyone authorized draws from that same pool. Who has access: The primary cardholder always has access and is added automatically. Beyond them, access comes from naming individuals outright, or from targeting user attributes — department, location, cost center, title, legal entity, or a manager's direct reports. Attribute-based access is a standing rule rather than a snapshot: someone who later joins the department gains access, and someone who leaves loses it. Best for: A vendor or tool a whole team buys from, where one card number is simpler than one card each and nobody needs their own separate limit. Not best for: Giving each person a separate limit, tracking per-person spend against separate limits, or rolling over unused balance — those are spend limits. — Scope of THIS tool — - Issues VIRTUAL P-Cards only. Physical cards can be ordered after creation via the Brex dashboard. - One tool call accepts 1–20 cards. If the confirmed request contains more than 20 cards, split it into follow-up calls of at most 20 cards each. Never truncate the request. — Sharing a card (authorized_users) — NEVER ask whether a card should be shared. Sharing is opt-in by mention: set authorized_users only when the operator names other people or asks for shared access ("include John and all of Marketing", "the design team should be able to use it"). On an ordinary create, do not raise the subject at all. How targeting combines: several values of the SAME attribute match any of them (two departments means either department), while DIFFERENT attributes must all match (a department plus a location means people in that department and at that location). Named individuals are independent of that — they are simply added. A manager grants access to their DIRECT reports only — not the manager themselves, and not reports of reports. If the operator asks for someone's whole org, say what you can actually do rather than approximating it. Never list the primary cardholder as an authorized user; they always have access. If the operator names only the cardholder, the card cannot be shared — explain that instead of calling the tool. Resolve every name to an ID first: people and managers via list_users with search_text, and the rest via list_departments, list_locations, list_cost_centers, list_titles, and list_legal_entities. Mapping what the operator says onto a field: "the Marketing team" is a department; "everyone in the London office" is a location; "the UK entity" or "anyone under Brex UK Ltd." is a legal entity; "Priya's reports" is a manager; "all the engineers" is a title; a named cost centre is a cost center. Watch the legal-entity case in particular — authorized_users.legal_entity_ids controls who may SPEND on the card, while the separate legal_entity_id field controls which entity is BILLED. Naming an entity implies only one of those, so ask which the operator meant rather than setting both. Name everyone who will have access in the confirmation recap, by display name. Access granted by attribute is applied shortly after the card is created, so an immediate read-back may not list those people yet — do not treat that as a failure. If shared cards are not enabled for the account the create is refused outright and no card is issued. Relay that plainly and offer to create the card without sharing. — When this tool is NOT the right fit (summary of adjacent spend objects) — Employee cards: per-user T&E and incidental spend (meals, travel, lodging) on an individual employee's general spending card — NOT for vendor/operational spend. Spend limits: purpose-driven controls for shared funds across multiple users, time-boxed group spending / events, rollover of unused balance, reimbursements, delegated limit ownership, or non-default policy routing where a P-Card isn't the right fit. Creation is NOT in scope here — recommend and hand off to the Brex dashboard. Always call list_spend_limits first (see preflight step 3 above) to check whether a topically-related spend limit already exists before recommending the operator create a new one. Spend limit groups: when each person needs their own limit rather than a shared pool. Creation is NOT in scope here — recommend and hand off to the Brex dashboard. Spend Limit cards: virtual cards tied to a single spend limit (optional, for stipend / travel-limit use cases). Creation is NOT in scope here. In general, spend limits and spend limit cards should be a fallback from the core employee card (with employee card limit) and P-Cards. — Core rules before calling — 1. Reason across all Brex spend objects before deciding. Don't default to a P-Card just because P-Card creation is one of the only write flows in scope. 2. Ask efficiently — when multiple required fields are missing, ask for them together in one concise message. 3. Infer optional fields only when low-risk: - currency: default USD when unspecified - limit_reset_frequency: default ONE_TIME when unspecified - limit_flexibility: default (allow 10% over the limit) when unspecified Surface inferred values in the confirmation step. — Confirmation gate (REQUIRED, do this before EVERY call) — 1. Once every required field is gathered or inferred, assemble the exact final configuration for EVERY card in the batch — name, cardholder, policy, limit, recurrence, currency, plus any value you inferred — and present it in one numbered recap, in the shape of the confirmation examples below. 2. Ask a single yes/no question whose ONLY purpose is consent, covering the whole batch. Wait for the answer. Never ask for confirmation separately for each card. 3. Treat answers to clarifying questions (which policy, what limit) as INPUTS, not consent. The yes/no is a separate, dedicated turn. 4. If the operator edits any item, re-present the complete updated batch and ask again. 5. Only after an explicit yes do you emit the create_purchasing_card tool call. — Required-field guidance — - name: infer from vendor / department / project when clear; otherwise ask. - customer_user_id (primary cardholder): infer only when named explicitly; otherwise ask for name or email and resolve via list_users with search_text. New P-Cards cannot be assigned to users who are pending activation, inactive, deactivated, disabled, archived, deleted, or embedded-only; tell the operator they were skipped. Active users may be included. Invited users may be included only when their role clearly identifies them as a physical or virtual purchasing-card user. If more than one eligible user matches, do NOT pick one — present the eligible candidates (name, email, role, status) and ask which one. - expense_policy_id: resolve this via list_expense_policies and do not ask the operator for a policy ID. Default to the account's default policy when the operator doesn't explicitly name one; when they do name one, match it against list_expense_policies by display name and use that policy's ID. If you can't confidently match a named policy, surface the available policies by name (not ID) and ask which one. - limit_amount: require an explicit amount. Ask if not provided. - limit_flexibility (optional): how much spend over limit_amount is still authorized. New P-Cards default to a 10% cushion, allowing spend slightly over the limit to be authorized instead of declined. Never ask the operator about flexibility; instead state the default in the recap AND what it means in money: the card declines at roughly 10% over the limit (for a $25,000 limit, around $27,500). Only send this field when the operator asks for something else: hard limit declines everything above the limit ("hard limit", "don't let them go over at all"), 5% and 25% give a smaller or bigger cushion, and unlimited declines only once spend exceeds the company credit limit. If a user requests an option outside of these five presets (such as "allow 20% over"), do not silently round it — say 5%, 10%, and 25% are the available cushions and offer the nearest one. Word each preset to the operator as "flexible, up to 10% over the limit", the way the confirmation examples below do. - max_transaction_amount (optional): a cap on any SINGLE transaction, separate from limit_amount. limit_amount is the pool of money the card can spend over the period; max_transaction_amount declines one purchase that is too large even when the pool still has room. "No single purchase over $500" is max_transaction_amount; "$500 total to spend" is limit_amount — never conflate them, and never derive one from the other. Only set it when the operator asks for a per-purchase ceiling; omit it for no cap, which is the dashboard default. It always uses the card's limit_currency, and must be greater than zero. State it in the recap whenever it is set. - start_date / end_date (optional): the card's validity window, as calendar dates only (YYYY-MM-DD) — this tool has no notion of a time of day or a timezone, so never send one. Only set them when the operator bounds the card in time ("for the September conference", "kill it at the end of the quarter", "starts next Monday"); omit both for an open-ended card. end_date is the first day the card can NO LONGER spend, so a card that must work through the last day of a month ends on the 1st of the next month — state the window that way in the recap ("spending stops on 2026-10-01") instead of implying the card still works that day. end_date must be today or later and on or after start_date; a start_date in the future issues the card suspended until that day, which you must tell the operator in the recap. - limit_visible_to_cardholders / allow_limit_increase_requests (optional): both default to true, matching the dashboard, so never ask about them unless the operator wants a change. Only set limit_visible_to_cardholders false when the operator explicitly wants the limit hidden from the cardholder ("don't let them see the limit", "private limit"). Setting it false silently forces limit-increase requests off too, no matter what allow_limit_increase_requests is set to — say so in the recap when both are touched together. - legal_entity_id (optional): only relevant for multi-entity accounts. Omit unless the operator names a specific legal entity to bill the spend to ("bill this to Brex UK Ltd."). When they do, resolve the name via list_legal_entities and pass its id — never guess one. Use only an entity that list_legal_entities reports as verified; if the named entity is not, tell the operator instead of setting it. State the entity used in the recap. - Default to issuing a virtual card (this tool only does virtual anyway). - merchant_category_controls (optional): only set when the operator explicitly asks to restrict where the card can spend. Set control_type ALLOW or BLOCK, and identify categories by merchant_category_ids (resolve names to raw pmca_ ids via list_merchant_categories) or merchant_names. Only pass merchant_category_codes (MCC) if the operator gives them — never look them up. — Batch requests — - Put every confirmed card in the cards array. Each item is self-contained and must include its own name, customer_user_id, expense_policy_id, limit_amount, and a unique idempotency_key. - A call may contain at most 20 cards. For larger confirmed requests, make follow-up calls containing at most 20 cards each. - After the call, inspect every result. Report created and failed cards separately. For uncertain failures, use list_cards to check whether the card exists before offering to submit only the failed item again. Example single-card confirmation (for one card, present a simple list): ─── I recommend creating a P-Card for Anthropic since this looks like recurring vendor spend. Here is the proposed setup: - Card name: Anthropic - Cardholder: Jade Lee - Policy: Default Policy - Card limit: $25,000 one-time - Limit enforcement: flexible, up to 10% over the limit (defaulted) — declines around $27,500 Should I create this P-Card? ─── Example batch confirmation (match this shape and tone; you must present the full batch before creating cards): ─── I recommend creating these P-Cards since they look like recurring vendor spend. Here is the proposed setup: 1. Deloitte - Cardholder: Tony Report - Policy: Default Policy (defaulted) - Card limit: $25,000 one-time (frequency defaulted) - Limit enforcement: flexible, up to 10% over the limit (defaulted) — declines around $27,500 2. Figma - Cardholder: Jane Doe - Policy: Design Policy - Card limit: $1,000 monthly - Limit enforcement: hard limit — declines at $1,000 Should I create these 2 P-Cards? ─── — Retry policy — Review the per-card results before retrying. If a card failed because of a network failure, timeout, or upstream error, do NOT automatically retry it. Check list_cards when the failure is uncertain, then let the operator decide whether to submit only the failed card again. Never resubmit cards whose result is created. Anti-pattern (do NOT do this): Operator: "create a Figma P-Card for $1k/mo, holder Chris Wilson" Agent: (resolves cardholder, asks for the policy, gets it, immediately issues the create call) ↑ Wrong. The policy answer was an INPUT, not consent. Agent should have assembled the full config and asked yes/no in a dedicated turn first. — Example scenarios — Scenario A — multiple named recurring vendors: Operator: "We need a card on file for Figma, AWS, and Slack." 1. Three named vendors, all recurring → operational spend → P-Cards fit. 2. Ask: who should hold these cards, and what's the monthly limit for each vendor (or one limit applied across all three)? 3. Resolve cardholder via list_users with search_text if needed. 4. Present the configs for confirmation as a table: Create these P-Cards? | # | Name | Cardholder | Policy | Limit | Currency | |---|-------|------------|---------|------------------|----------| | 1 | Figma | Jane Doe | Default | $1,000 / monthly | USD | | 2 | AWS | Jane Doe | Default | $5,000 / monthly | USD | | 3 | Slack | Jane Doe | Default | $500 / monthly | USD | 5. On "yes," call create_purchasing_card once with all three cards in the cards array. On "no," ask which to edit or cancel, then re-present all three. Scenario B — ambiguous "ad spend": Operator: "I need a card for ad spend." 1. Ad spend is operational → P-Card track. But "ad spend" doesn't specify vendor count — clarify before recommending structure. 2. Ask: how many ad platforms is this covering — just one (e.g. Google Ads), or several (e.g. Google, Meta, TikTok)? 3. Branch on the answer: - One vendor → single P-Card → continue to required-field collection. - Multiple vendors → multiple P-Cards (one per platform), OR a single shared card if the operator prefers. Note the trade-off (a single number covers every platform, so one compromise or reassignment affects all) once, then proceed with whichever the operator chooses. Scenario C — "marketing department card" (hand-off case): Operator: "We need a marketing department card." 1. Preflight step 3 already ran list_spend_limits — check its results for a "Marketing" (or similarly named) spend limit before doing anything else. If one exists, surface it now and ask whether the operator wants to use that instead of creating something new. 2. If nothing relevant was found: ambiguous — could be P-Card for recurring vendors, shared spend pool across the team, or both. Two clarifying questions: - Are there specific vendors this card is for, or general department use? - How many people need access to the funds? 3. Branch on the answers: - Named vendors + single cardholder → P-Card per vendor. - Multiple vendors + multiple users with dedicated limits per user → a spend limit group (one spend limit per user, grouped). NOT in scope here — recommend setting up via the Brex dashboard. - Shared pool across the whole team → a single spend limit. NOT in scope here — recommend setting up via the Brex dashboard. Scenario D — bulk cardholders by name: Operator: "Create a P-Card for every Andre in the account." 1. Resolve "Andre" via list_users with search_text. 2. Separate eligible users from pending-activation, inactive, deactivated, disabled, archived, deleted, or embedded-only users before presenting the final setup. 3. Tell the operator which users are being skipped because they cannot be assigned a new P-Card. 4. Ask for confirmation to create cards only for eligible users. Never call this tool for skipped users, and never loop through expected failures. Scenario E — a card that should only work for a while: Operator: "We need a card for the September sales conference — $5k, and it should stop working after the conference ends on September 30." 1. Time-bounded operational spend → single P-Card with a validity window. 2. Translate the operator's inclusive wording into the exclusive end_date: "through September 30" means end_date 2026-10-01. If they gave no start, omit start_date so the card works immediately. 3. Recap it back in those terms: "Card limit: $5,000 one-time / Valid: from today until spending stops on 2026-10-01 (covers September 30)". 4. On "yes," call once with "end_date": "2026-10-01". Scenario F — the operator names other people (the only way sharing starts): Operator: "Set up a Canva card, $2k a month. Priya should be able to use it, and so should anyone in Design." 1. Recurring vendor spend → P-Card. The operator named other people, so this card is shared; on a request that named nobody you would never have raised sharing at all. 2. Resolve Priya via list_users with search_text and Design via list_departments. Do not include the cardholder. 3. Recap by name: "Canva, $2,000 monthly, held by <cardholder>. Priya Raman and everyone in Design can also spend on it." 4. On "yes," call once with authorized_users carrying Priya's user ID and the Design department ID. 5. Had the operator said "Priya and anyone in Design based in NYC", that is a department AND a location — both must match, which is a smaller group than either alone. Confirm that reading before creating. 6. Had they instead said "anyone under our UK entity should be able to use it", that is legal_entity_ids (resolve via list_legal_entities) — granting access to that entity's people, which is NOT the same as billing the card to that entity. If they want both, say so explicitly in the recap and set legal_entity_id as well. Example input shape for a single recurring vendor: { "cards": [{ "name": "Figma", "customer_user_id": "<resolved_eligible_customer_user_id>", "expense_policy_id": "<resolved_or_default_policy_id>", "limit_amount": "1000.00", "limit_currency": "USD", "limit_reset_frequency": "PER_MONTH", "idempotency_key": "<unique_idempotency_key>" }] } Example 2 — two P-Cards in one call: { "cards": [ { "name": "Figma", "customer_user_id": "<resolved_eligible_customer_user_id>", "expense_policy_id": "<resolved_or_default_policy_id>", "limit_amount": "1000.00", "limit_reset_frequency": "PER_MONTH", "idempotency_key": "<figma_idempotency_key>" }, { "name": "AWS", "customer_user_id": "<resolved_eligible_customer_user_id>", "expense_policy_id": "<resolved_or_default_policy_id>", "limit_amount": "5000.00", "limit_reset_frequency": "PER_MONTH", "idempotency_key": "<aws_idempotency_key>" } ] } Example 3 — the operator asked for non-default flexibility ("$2k monthly, but allow 25% over" / "hard cap, no overage"): { "cards": [{ "name": "Figma", "customer_user_id": "<resolved_eligible_customer_user_id>", "expense_policy_id": "<resolved_or_default_policy_id>", "limit_amount": "2000.00", "limit_reset_frequency": "PER_MONTH", "limit_flexibility": "FLEXIBLE_25", "idempotency_key": "<figma_idempotency_key>" }] } (For "hard cap, no overage" send "limit_flexibility": "HARD_LIMIT".) Example 4 — a time-bounded card ("$5k for the September conference, starts Sept 1, done after Sept 30"): { "cards": [{ "name": "Sales Conference", "customer_user_id": "<resolved_eligible_customer_user_id>", "expense_policy_id": "<resolved_or_default_policy_id>", "limit_amount": "5000.00", "start_date": "2026-09-01", "end_date": "2026-10-01", "idempotency_key": "<conference_idempotency_key>" }] } (end_date is the first day the card cannot spend, so Oct 1 covers all of Sept 30. A Sept 1 start in the future means the card is issued suspended until then — say so.) Example 5 — a private-limit card ("give the contractor a card but don't let them see the limit"): { "cards": [{ "name": "Contractor Card", "customer_user_id": "<resolved_eligible_customer_user_id>", "expense_policy_id": "<resolved_or_default_policy_id>", "limit_amount": "1000.00", "limit_visible_to_cardholders": false, "idempotency_key": "<contractor_idempotency_key>" }] } (Hiding the limit also forces off limit-increase requests, regardless of allow_limit_increase_requests — say so in the recap.) Example 6 — a per-purchase ceiling ("$10k a month for AWS, but no single charge over $2,500"): { "cards": [{ "name": "AWS", "customer_user_id": "<resolved_eligible_customer_user_id>", "expense_policy_id": "<resolved_or_default_policy_id>", "limit_amount": "10000.00", "limit_reset_frequency": "PER_MONTH", "max_transaction_amount": "2500.00", "idempotency_key": "<aws_idempotency_key>" }] } (The two amounts are independent: $10,000 is the monthly pool, $2,500 is the biggest single charge that will authorize. Recap both.)
create_purchasing_card
Find users with combined search, filters, sorting and pagination. Use search_text to find users by name or email, and set limit to the number requested, up to 100 per page. Use roles directly for built-in roles such as BOOKKEEPER or AP_CLERK; use admin_role for all admins. ID FILTERS: department, location, cost_center, entity, title, role, access and manager accept only Brex IDs, never names, labels or other human-readable strings. When the user describes a filter in plain language (for example "Engineering department", "San Francisco office", "R&D cost center", "bill pay approvers" or "reports to Jane Smith"), first call its discovery tool to resolve the name, then pass only the returned IDs: - department: list_departments (IDs look like cudmnt_...) - location: list_locations (culoc_...) - cost_center: list_cost_centers (cc_...) - entity: list_legal_entities (le_...) - title: list_titles (ti_...) - role: list_roles with role_type FUNCTIONAL (role_... or aurl_...) - access: list_roles with role_type ACCESS (role_... or aurl_...) - manager: list_users with search_text (cuuser_...) If the user already supplied an ID with the expected prefix, skip discovery and pass it through. Never guess IDs, never pass a name as an ID, and never silently drop a filter instead of resolving it. COMBINING FILTERS: for requests such as "active users in Finance", resolve every named filter and include all requested filters in the same call. Never drop a filter because another filter was already applied. Follow next_cursor with the same filters and sort order until you have the number requested or next_cursor is null.
list_users
**DEPRECATED — planned retirement.** Prefer list_integrations when that tool appears in your available tools list. list_integrations returns ACTIVE and DISABLED rows when status is omitted, and supports multi-ERP accounts. This singleton errors if more than one integration is active. When list_integrations is available, do not use this tool. 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" }
get_active_integration
Get detailed information about a specific banking transaction by its ID. Returns comprehensive transaction details including timeline, payment details, initiated/cancelled by user info, and cancellation status. Use list_banking_transactions first to find valid transaction IDs. Example: { "transaction_id": "dptx_abc123" }
get_banking_transaction
Get a bill (payable) by its ID. Bills are invoices from vendors that need to be paid. This tool retrieves detailed information about a specific bill. Parameters: - id: The unique identifier of the bill Example: { "id": "exp_abc123" }
get_bill_by_id
Get a business account by its ID. Returns detailed information about a specific business account including balance breakdown and cashflow. Use list_business_accounts first to find valid account IDs. Example: { "account_id": "dpacc_abc123" }
get_business_account
Get a card by its ID, including its current spend configuration (merchant category controls and expense policy). For a shared card, shared_card_details.authorized_users is a preview, not the roster: it stops at the first 100 members. Always check it against member_count, which is the real total. If member_count is larger than the number of users listed, you are seeing a partial list — report the count and say the rest are not shown. Never present a partial list as everyone who has access. Describe MANUAL_INCLUDE as "added directly" — that person stays until someone removes them. Describe MEMBER_CONDITION as "added by a rule" — they match a rule such as a department, and they drop off on their own if they stop matching, so removing them means changing the rule rather than the person. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary.
get_card_by_id
Get shipping details for a specific card by its ID SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary.
get_card_shipping_details
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. - include: Optional tokens. phone_number, brex_assistant, notification_preferences. Unrequested fields are null. Example Output: { "id": "cuuser_123", "first_name": "John", "last_name": "Doe", "email": "john.doe@example.com", "role": "CARD_ADMIN", "status": "ACTIVE" }
get_user_myself
Get an expense by its ID Declines and failed authorizations: - payment_status - the payment outcome. DECLINED means the card authorization was refused; CANCELED means an authorization was reversed or expired without clearing; CLEARED means it settled. - payment_status_label - the same wording the Brex dashboard shows, for display. Use payment_status for logic and filtering, this for phrasing: it varies by expense type, so DECLINED reads "Declined" on a card but "Failed" elsewhere, CLEARED reads "Completed" but "Paid" on a clawback, and CREDITED reads "Chargeback". Prefer it over inventing your own wording for a status. - payment_status_reason - WHY, for card authorizations. This is the field that explains a decline: e.g. EXCEEDED_CARD_LIMIT (over the card's limit), EXCEEDED_BUDGET_LIMIT / EXCEEDED_ANCESTOR_BUDGET_LIMIT (over the budget), BUDGET_CATEGORY_RESTRICTION / BUDGET_MERCHANT_RESTRICTION / MCC_BLOCKED (merchant or category not allowed), CARD_SUSPENDED / CARD_TERMINATED / CARD_NOT_ACTIVE / CARD_EXPIRED (card state), INVALID_CVV / INVALID_EXPIRATION_DATE / INVALID_BILLING_ADDRESS (bad credentials at checkout), SUSPECTED_FRAUD, ACCOUNT_SUSPENDED, USER_SUSPENDED, NO_BUDGET. THIS TOOL IS THE ONLY SOURCE OF payment_status_reason. list_expenses returns payment_status but not payment_status_reason, because resolving the reason costs one extra lookup per expense. To answer "why was my card declined?": call list_expenses to find the failed attempts (payment_statuses: ["DECLINED", "CANCELED"], plus merchant/date/card as needed), then call this tool with each expense id to read its reason. A null payment_status_reason here means no authorization decision is recorded (or the expense is not a card expense) -- it does NOT mean "declined for an unknown reason". Include (opt-in fields; otherwise null): - include: Array of tokens. Supported values: * "receipts" - Full receipt details (asset_id, download_uri, parsed content/line items). Without this, receipts only contain IDs. * "travel_metadata" - Flight, car rental, lodging, and train data * "travel_booking" - Associated Brex Travel booking (trip ID and booking status) * "location" - Expense location details * "memo_details" - Detailed memo source information * "accounting_field_values" - Accounting coding fields assigned to the expense Location and travel data are ALWAYS null unless requested via include. A null location does NOT mean "no location exists" — re-call with include: ["location"]. Same for travel_metadata. ⚠️ When the user asks ANYTHING about receipts — line items, itemized charges, "what did I buy", receipt content/images/downloads, parsed receipt data, whether a receipt is attached, or receipt counts — you MUST pass include: ["receipts"]. A receipt with only an ID and no content/download_uri means include did not contain "receipts" — re-call with include: ["receipts"]. Example 1: Getting an expense with full receipts (includes line items, download URL, parsed content): { "id": "expense_123", "include": ["receipts"] } Example 2: Getting an expense with travel metadata and location: { "id": "expense_123", "include": ["travel_metadata", "location"] } Example 3: Getting an expense with everything: { "id": "expense_123", "include": ["receipts", "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
get_expense_by_id
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
get_expense_download_result
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 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.
get_expense_policy
Lists the documentation policy requires for one expense (receipt, memo, attendees, custom fields), each tagged SATISFIED or MISSING, plus a COMPLETE / INCOMPLETE rollup. Use it for "what do I still need for this expense?", "does this expense have all required documentation?", and "what would I need if I moved it to the Travel limit?". It covers documentation only, not spending restrictions or approvals. When evaluating a move to another limit, pass its limit_id from list_my_limits; call this before assign_limit_for_card_expenses so the user knows what the new limit asks for. Use get_expense_policy for a limit's rules in general, and list_tasks for everything the caller owes across expenses. A null requirement means policy does not require it. A receipt with status PENDING has not arrived yet but Brex expects to generate one: do not ask the user for it. A receipt that is MISSING with receipt_count above 0 is attached but not itemized where policy requires itemization: ask for an itemized one. On a proposed limit, whether an attached receipt is itemized is not checked. Fix MISSING items with update_expense_memo, upload_card_expense_receipt_from_urls, replace_attendees_for_card_expense, or accounting field updates; attendees.unmet says which attendee details are lacking. Errors: INVALID_ID_FORMAT (400) when expense_id or limit_id is not a raw ID; BAD_REQUEST (400) for bill pay or clawback expenses, or a limit that cannot be evaluated; NOT_FOUND (404) when the expense is not visible to the caller.
get_required_documentation
Get the Brex reward points balance and redemption eligibility for the authenticated account. Returns the current reward balance, wallet type (POINTS or CASH), and whether the account can currently redeem rewards. Parameters: none. Example response: { "amount": 2781573647, "type": "POINTS", "redeemable": true } Notes: - "amount" is in centipoints when "type" is POINTS (divide by 100 to get points). - "amount" is in USD cents when "type" is CASH. - "redeemable" is false if the account is delinquent.
get_reward_points
Get complete details for one spend limit by its raw ID. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. Use this only after the request or a prior tool result identifies one specific spend limit. Pass the raw budget_... ID returned by list_spend_limits or list_my_limits; do not pass a limit name or Relay-encoded ID. ROUTING EXAMPLES: - "Show full details for spend limit budget_123" → use this tool - "Show full details for the Marketing limit I manage" → use list_spend_limits first, then this tool with the resolved ID - "How much is available on that limit?" after a list result identified one limit → use this tool with that result's ID - "Which spend limits can I manage?" → use list_spend_limits - "What limits can I spend from?" → use list_my_limits Returns financial details, dates, owners, members, visibility, and the visible containing-budget path when the caller is authorized to view them.
get_spend_limit_by_id
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
get_reimbursement_payout_date
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. - include: Optional tokens. phone_number, brex_assistant, notification_preferences. Unrequested fields are null. Example Input: { "id": "cuuser_123", "include": ["phone_number"] } 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" }
get_user_by_id
Get a vendor by ID
get_vendor_by_id
List Brex account roles. For built-in user roles such as BOOKKEEPER, AP_CLERK, CARD_ADMIN, ACCOUNT_ADMIN or EMPLOYEE, call list_users directly with the `roles` enum filter. Do not call list_roles to resolve these values. For all admins, use list_users with `admin_role: "ADMINS"`. Use this discovery tool when the request needs functional role IDs for list_users `role` or access role IDs for `access` (for example, a custom functional role or "bill pay approver" access). Resolve names here first, then pass the returned IDs into the corresponding filter. 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-100, default 10), 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 }
list_roles
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_gl_accounts
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_accounting_records
List banking transactions with filters, date ranges, amount ranges, and sorting. If the user mentions an account by name, use list_business_accounts first to resolve the name to an ID. Results are paginated - use limit and cursor for pagination. IMPORTANT: Transaction amounts use signed convention: - Positive amounts = incoming money (credits/deposits) - Negative amounts = outgoing money (debits/payments) For incoming transactions (money received), use positive min_amount. For outgoing transactions (money sent/paid), use negative max_amount. CRITICAL - Amount filter decision logic: 🔍 When the user mentions amounts, ALWAYS include the appropriate filter: "Over $X" or "More than $X": - Incoming: min_amount: X (e.g., "deposits over $100" → min_amount: 100) - Outgoing: max_amount: -X (e.g., "payments over $1000" → max_amount: -1000) "Between $X and $Y": - MUST include BOTH min_amount AND max_amount - Incoming: min_amount: X, max_amount: Y (e.g., "deposits between $100 and $500") - Outgoing: min_amount: -Y, max_amount: -X (e.g., "payments between $100 and $500" → min_amount: -500, max_amount: -100) "Under $X" or "Less than $X": - Incoming: max_amount: X - Outgoing: min_amount: -X Example 1: Getting recent transactions sorted by timestamp: { "sort": "TIMESTAMP", "direction": "desc" } Example 2: Getting ACH transactions for a specific account: { "business_account_ids": ["dpacc_abc123"], "type": ["ACH"] } Example 3: Incoming transactions over $100 (deposits/credits): { "start_date": "2025-01-01T00:00:00Z", "end_date": "2025-01-31T23:59:59Z", "min_amount": 100.00 } Example 4: Outgoing payments over $1,000 (debits): { "max_amount": -1000.00, "sort": "AMOUNT_USD_CENTS", "direction": "asc", "limit": 10 } Example 5: Account transfers between Brex accounts: { "type": ["ACCOUNT_TRANSFER", "BOOK_TRANSFER"] } Example 6: Only processed transactions: { "status": ["PROCESSED"] } Example 7: Pending transactions (processing or awaiting approval): { "status": ["PROCESSING", "APPROVAL_REQUIRED"] }
list_banking_transactions
List bills (vendor invoices) with bill-specific details like due dates, payment schedules, and vendor information, OR aggregate bills by group. ⚠️ WHEN TO USE THIS VS list_expenses: Use list_bills when the user needs BILL-SPECIFIC information: - Due dates, overdue status, payment schedules: "bills due this week", "overdue bills", "bills due in the next 30 days" - Vendor-centric queries: "bills from vendor X", "how much do we owe vendor Y" - Bill payment status and details - Comprehensive bill metadata (invoice numbers, service dates, payment send dates) - Bill aggregations: "total bill spend by vendor", "bill count by status", "monthly bill totals", "top vendors by amount owed" Use list_expenses when bills are just ONE expense type in a broader analysis alongside CARD/REIMBURSEMENT: - Overall spending analysis: "total expenses this month", "expenses over $500" - Mixed expense queries: "show all card and bill expenses", "compare reimbursements to bills" Note: Bills in list_expenses have LESS detail (no due_at, vendor details are minimal). Aggregations on bills work in BOTH tools — use this one when the user is asking ABOUT bills (not "all spend"). Two modes — same filters, different output: - LISTING mode (default): omit aggregations → returns a paginated list of bills with full bill-specific metadata - 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 on bills. AGGREGATION STATUS RULE: Never send VOID. Include CANCELED only when filtering payment outcomes; explicit status filters are passed through unchanged. For general counts, yearly breakdowns, or totals across statuses, omit statuses to use DRAFT, SUBMITTED, APPROVED, and OUT_OF_POLICY. For money owed, use only SUBMITTED, APPROVED, and DRAFT. SINGLE-NUMBER QUESTIONS ("how many") — use AGGREGATION mode with no group_by: Except for amounts owed (always include a status breakdown), for a 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 bills are submitted?" → statuses:["SUBMITTED"], aggregations:[{func:"COUNT", field:"all", alias:"submitted_count"}] - "How many overdue bills?" → due_at_end:"<today>", statuses:["SUBMITTED","APPROVED","DRAFT"], aggregations:[{func:"COUNT", field:"all", alias:"overdue_count"}] - "How many unpaid bills from vendor X?" → statuses:["SUBMITTED","APPROVED","DRAFT"], vendor_ids:["..."], aggregations:[{func:"COUNT", field:"all", alias:"unpaid_count"}] - "How many unpaid bills from vendors X and Y?" → statuses:["SUBMITTED","APPROVED","DRAFT"], vendor_ids:["...","..."], aggregations:[{func:"COUNT", field:"all", alias:"unpaid_count"}] - "How many bills missing memo OR missing receipt?" → statuses:["SUBMITTED","APPROVED"], documentation_missing_any:["MEMO","RECEIPT"], aggregations:[{func:"COUNT", field:"all", alias:"missing_docs"}] - "What's the total amount owed?" → statuses:["SUBMITTED","APPROVED","DRAFT"], group_by:["bill_status"], aggregations:[{func:"SUM", field:"billing_amount", alias:"total_owed"}]. Sum the status rows per currency for the overall total and show each status subtotal. - "Total bill spend in May 2026?" → due_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 bills span multiple currencies — present each bucket separately or convert client-side. BREAKDOWN QUESTIONS ("by", "per", "top N") — use AGGREGATION mode with group_by: - "Top vendors by total bill spend this year" → group_by:["vendor"], aggregations:[{func:"SUM", field:"billing_amount", alias:"total_owed"}] - "Bill counts BY status" → group_by:["bill_status"], aggregations:[{func:"COUNT", field:"all", alias:"bill_count"}] - "Monthly bill spend by vendor" → group_by:["month","vendor"], aggregations:[{func:"SUM", field:"billing_amount", alias:"total"}] - "Bill count by department" → group_by:["department"], aggregations:[{func:"COUNT", field:"all", alias:"bill_count"}] CUSTOM AMOUNT BUCKETS (e.g. "<$1k, $1k-$5k, $5k+"): Use min_amount / max_amount to bound bills by amount (USD), in both listing and aggregation mode. E.g. "bills over $1,000" → min_amount:1000; "$1k-$5k" → min_amount:1000, max_amount:5000. For a full histogram, issue one call per bucket (or bucket client-side from an unfiltered aggregation). Counting bills: - 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. Time bucketing: - Supported granularities: day, week, month, quarter, year (based on purchased_at). - For yearly totals across multiple years, group by "year". For a single year's total, omit group_by entirely with a year-bounded date filter and a SUM aggregation. Bill-specific time grouping (by due_at, payment_send_at, or has_payment_schedule) currently requires LISTING mode with the corresponding date filter and client-side bucketing. Without a payment_statuses filter, defaults to DRAFT, SUBMITTED, APPROVED, and OUT_OF_POLICY bills (all except VOID and CANCELED). Do not include VOID in the statuses you request. Explicit status filters are passed through unchanged; the service does not remove statuses for you. Include CANCELED when filtering payment outcomes or explicitly listing canceled bills. Exclude CANCELED from amounts owed. PAYMENT FAILURES: "failed", "payment failures", and "didn't go through" mean payment_statuses:["DECLINED"], not statuses:["CANCELED"]. Use this filter in both listing and aggregation mode. Omit statuses unless the user explicitly asks for particular approval states: with payment_statuses set, the default includes all non-VOID statuses, including CANCELED. A failed payment can belong to a DRAFT, APPROVED, or CANCELED bill. Explicit statuses are intersected with payment_statuses. Bill payment failure reasons are not available here. Do not infer a cause from the payment status or offer get_expense_by_id as a source of bill failure explanations; its payment_status_reason describes card authorization declines. If asked why a bill payment failed, explain that the reason is unavailable. Choose statuses based on the user's intent unless they explicitly request specific statuses: - "Show me my bills": use incurred_by:"ME" and omit statuses to include all except VOID and CANCELED. - "How much do we owe": statuses:["SUBMITTED","APPROVED","DRAFT"]. Show the total AND a split by status, keeping currencies separate. - "Overdue" / "due this week": statuses:["SUBMITTED","APPROVED","DRAFT"] with the appropriate due-date filters. - Compliance backlog / missing documents: statuses:["SUBMITTED","APPROVED"]. Exclude DRAFT. OUT_OF_POLICY is a terminal rejection state (for example, an admin rejected a duplicate bill or a bill with bad data). Exclude it from amounts owed; it remains visible in broad bill-history queries. Always state the statuses included in the answer, even when using defaults or returning no results. A bill's lifecycle status is distinct from its payment_status. Parameters: - vendor_ids: Optional non-empty array of vendor IDs to filter bills. Use one ID for a single vendor or multiple IDs for multiple vendors. Resolve vendor names first with list_vendors. - user_ids: Optional array of specific Brex user IDs to filter bills by. Resolve names to IDs first with list_users with search_text. Mutually exclusive with incurred_by. - incurred_by: Determines whose bills to show (optional). Options: - Not specified: All bills you have permission to see (for admins/bookkeepers: all company bills) - "ME": Only bills created by you (same as using list_my_bills) - "REPORTS": Bills from your direct reports only - "ALL_REPORTS": Bills from all nested reports (your reports + their reports) Note: Regular users without reports will get no results when using REPORTS/ALL_REPORTS. - statuses: Optional array of expense statuses to filter by (bills are expenses with type=BILLPAY). The schema accepts all bill statuses. Do not request VOID. Payment-status queries include CANCELED unless statuses is explicitly narrowed. If not specified, defaults to DRAFT, SUBMITTED, APPROVED, and OUT_OF_POLICY; also includes CANCELED when payment_statuses is set. - due_at_start: Filter bills with due date on or after this local date/datetime (e.g., '2025-04-01' or '2025-04-01T14:00:00'). Will be converted to UTC using timezone parameter. - due_at_end: Filter bills with due date on or before this local date/datetime (e.g., '2025-04-30' or '2025-04-30T23:59:59'). Will be converted to UTC using timezone parameter. - payment_send_at_start: Filter bills with scheduled payment send date on or after this local date/datetime. Will be converted to UTC using timezone parameter. - payment_send_at_end: Filter bills with scheduled payment send date on or before this local date/datetime. Will be converted to UTC using timezone parameter. - has_payment_schedule: Filter bills by whether they have a recurring payment schedule (true = recurring bills only, false = non-recurring only) - has_payment_send_at: Filter bills by whether they have a scheduled payment send date (true = scheduled only, false = not scheduled) - 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 bills due on 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 "bills due this week", 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. - limit: Max items per page (1-100, default 10) - cursor: Pagination cursor for next page of results Example 1: Get overdue bills (due before today): { "due_at_end": "2026-06-03T23:59:59", "statuses": ["SUBMITTED", "APPROVED", "DRAFT"] } Example 2: Get bills due in the next 7 days: { "due_at_start": "2026-06-04T00:00:00", "due_at_end": "2026-06-11T23:59:59", "statuses": ["SUBMITTED", "APPROVED", "DRAFT"] } Example 3: Get bills with payments scheduled for this week: { "payment_send_at_start": "2026-06-04T00:00:00", "payment_send_at_end": "2026-06-11T23:59:59" } Example 4: Get bills from one or more vendors: { "vendor_ids": ["vendor_abc123", "vendor_xyz789"] } Example 5: Get all team bills (including nested reports): { "incurred_by": "ALL_REPORTS" }
list_bills
List business accounts. Results are paginated - use limit and cursor for pagination. Example 1: Getting the first 10 accounts: { "limit": 10 } Example 2: Paginating through accounts: { "limit": 25, "cursor": "cursor_from_previous_response" }
list_business_accounts
List card shipping details with filters. Pagination: - limit: max cards per page (1-100, default 10); a higher value is clamped to 100 - cursor: pass next_cursor from the previous response - To retrieve the full set, continue until next_cursor is null. Example 1: Getting shipping details for all cards waiting activation: { "status": ["WAITING_ACTIVATION"] } Example 2: Getting shipping details for specific users: { "user_ids": ["user_123"] } SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary.
list_cards_shipping_details
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 with search_text to get user ID, then pass user_ids parameter Pagination: - limit: max cards per page (1-100, default 10); a higher value is clamped to 100 - cursor: pass next_cursor from the previous response - To retrieve the full set, continue until next_cursor is null. An account holds far more cards than fit on one page, so a single page is not the account's card list — never answer "how many", "list every", or any question that needs the whole set from one page. 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): - To list P-Cards, pass card_category: ["PURCHASING_CARD"]. To check if a card exists for a certain purpose, do NOT set search_query — fetch the broad list and judge contextual relevance yourself. - 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. Filtering by card form (card_form): - Pass card_form: ["VIRTUAL"] to scope results to virtual cards. Sorting: - Pass sort with direction for server-side ordering. Use sort: "ISSUED_AT", direction: "desc", limit: 1 to get the most recently issued matching card. Telling shared cards apart: - A card is shared when shared_card_details is present on it, and not shared when the field is absent. Use that to answer questions like "how many of these are shared?" without a follow-up call per card. - Results are not limited to cards the queried user holds or can spend on. Admins can list every card in the account, and managers can list their reports' cards. Use each card's `user` field to see who actually holds a card. - shared_card_details.is_authorized_user is positive evidence only. True means the queried user is an authorized user on that shared card. False means only that they are NOT — it does not tell you they are the cardholder, and does not explain why the card is visible to them. Never read false as "this card is theirs". - On list results member_count is null and authorized_users is empty — that means "not fetched here", NOT "shared with nobody". Call get_card_by_id on a specific card to see who actually has access. 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: { "card_category": ["PURCHASING_CARD"] } Example 7: Checking whether a specific user already has an employee card: { "user_ids": ["cuuser_abc123"], "card_category": ["EMPLOYEE_CARD"] } Example 8: Getting a user's most recently issued physical card: { "user_ids": ["cuuser_abc123"], "card_form": ["PHYSICAL"], "sort": "ISSUED_AT", "direction": "desc", "limit": 1 } SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. GLOBAL USER-FACING RULES — apply to EVERY message you send the operator. Everything in this description is internal contract. It is here so you can reason and build a correct call; none of it belongs in a reply. - Never show wire values. Statuses, reasons, card categories, card forms, reset frequencies and limit flexibilities are internal codes: say "locked", "cancelled", "a virtual card", "monthly", "up to 10% over the limit". - Never show request or response FIELD NAMES, and never use `field: value` form. Describe what the operator will observe, in prose. - Never show internal IDs (card, user, policy, limit). Name objects by display name only, e.g. "Tony Report", "Default Policy". - Never name tools or internal steps: no "list_cards", "duplicate check", "preflight", "tool call". - Never volunteer how Brex records a card action internally. The spend limits, budgets and other bookkeeping behind locking, cancelling, transferring or issuing a card are implementation, not product: describe only what the operator will observe. Spend limits ARE a product the operator can be offered in their own right — the rule is about not explaining a card action in terms of them. - Any examples below use wire vocabulary deliberately, because they show the shape of a call. Copy their structure, never their vocabulary.
list_cards
List cost centers (id + display name). Call it one of two ways: - The user names a cost center (for example "Is R&D one of our cost centers?" or "users in R&D"): pass that name as `search_text`. This is the only way to check whether a named cost center exists. Do not raise `limit` or page through results instead. - The user asks about cost centers in general: omit `search_text`, and follow `next_cursor` until it is null. list_users accepts only cost center IDs in its `cost_center` filter. When the user names a cost center there, call this tool first with `search_text` and pass the returned `id` into list_users. Parameters: limit (1-100, default 10), cursor (pagination), search_text (the cost center name the user gave). Example Output: { "items": [{ "id": "cc_1234", "name": "Engineering" }], "next_cursor": "cursor_abc" }
list_cost_centers
List configured choices for a field. When a request includes both an ERP code and an external reference, validate them together in one call using value_id and remote_id; each result must match both identifiers. If that combined lookup returns no choices, ask for corrected identifiers before recommending a classification. To check a specific named choice, always pass the display name as value. A response with non-null next_cursor is incomplete: fetch every remaining page or repeat the lookup with value before declaring a choice missing. A missing-choice verdict requires a successful lookup ending with next_cursor=null and no matching label. No record or expense ID is needed. Resolve field_id from the field brex_id returned by list_fields. Filter by value_id for ERP codes or remote_id for external references. For a full catalog, omit value and follow every next_cursor while preserving field_id and filters. Active and disabled choices are returned together; inspect is_disabled before recommending a choice for new coding. Show value labels to the user. The option brex_id is the Brex choice ID used as value_id for an IDENTIFIER accounting assignment; returned value_id is a separate remote-system code. This tool discovers choices and does not change record classification.
list_field_values
List departments (id + name). Call it one of two ways: - The user names a department (for example "Is Engineering one of our departments?" or "users in Engineering"): pass that name as `search_text`. This is the only way to check whether a named department exists. Do not raise `limit` or page through results instead. - The user asks about departments in general: omit `search_text`, and follow `next_cursor` until it is null. list_users accepts only department IDs in its `department` filter. When the user names a department there, call this tool first with `search_text` and pass the returned `id` into list_users. Parameters: limit (1-100, default 10), cursor (pagination), search_text (the department name the user gave). Example Output: { "items": [{ "id": "cudmnt_1234", "name": "Engineering" }], "next_cursor": "cursor_abc" }
list_departments
List employee card limits across the account. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. Use this for account-wide questions about spendable employee card limits: - "Show me everyone's spendable employee card limits" - "List employee card limits" - "Which employee card limits are spendable?" - "How much employee card limit does Grace have?" Returns employee card limit details including the limit name, configured amount (total), spent amount, and available amount. For questions about a specific employee's card limit, limit amount, or available card spend, this is still the right tool. Do not call user lookup tools just to answer employee-card-limit amount questions. Match the employee by the returned limit name. This does not list card records, card IDs, card numbers, card status, physical/virtual card form, shipping details, or other card metadata. Use list_cards for card records or card lifecycle questions. This tool only returns employee card limits with spendable configuration. Here, spendable means every limit rule has a positive funded amount or is unlimited, or at least one active positive temporary override exists. It does not account for whether the cardholder has permission to spend.
list_employee_card_limits
List all available expense categories (also known as 'expense types' in Brex) for filtering expenses. Expense categories are custom categorizations like: - Airfare, Lodging, Car Rental (travel) - Meals & Entertainment - Office Supplies - Software & SaaS - Marketing & Advertising - Professional Services Use this tool to: - Discover available expense category IDs for the expense_category_ids filter - Search categories by name (e.g., "travel", "meals") - Browse all configured expense categories Parameters: - query: Optional search to filter by name (e.g., "travel", "meals") - limit: Max items per page (1-100, default 10) - cursor: Pagination cursor from previous response Example — find travel categories: { "query": "travel" } Response (trimmed): { "items": [ { "id": "category_abc", "name": "Airfare" }, { "id": "category_def", "name": "Car Rental" } ], "next_cursor": null }
list_expense_categories
List expense POLICY RECORDS for the account (catalog/discovery). Returns lightweight summaries only — not rules, not limit balances. Supports filtering by default flag and by status, INCLUDING listing disabled/inactive policies (statuses: ["DISABLED"]). **WHEN TO USE (account policy catalog):** - User wants to see which policies exist, find the default policy, or browse policy names/IDs - User wants to list DISABLED / inactive / archived policies → this IS supported here: call this tool with statuses: ["DISABLED"]. Do NOT submit_feedback claiming status filtering is unavailable — it is available via the statuses param. - Examples: "What expense policies do we have?", "Show me the default expense policy", "Which expense policy is the default?", "List all disabled expense policies" (use statuses: ["DISABLED"]). Use filters internally, but do not mention raw parameter names to the user. **WHEN NOT TO USE — pick a different tool instead:** - User asks policy RULES / compliance on their spending (receipts, approvals, "can I expense X") → list_my_limits then get_expense_policy with spend_limit_id - User asks about limit balances or "how much is left" → list_my_limits - User asks what they can spend on their card in general → get_expense_policy or list_my_limits (not this tool) **What you get back:** - items[]: policy summaries — id, display_name, description, is_default, status (NO receipt/approval/merchant rules) - next_cursor: opaque cursor for the next page, or null after the final page **Scope:** Returns the account's EXPENSE policies. Defaults to ACTIVE (CREATED); override with statuses. **After discovery:** To show full rules for a policy, you still need a spend limit attached to that policy — call list_my_limits, then get_expense_policy with spend_limit_id. This tool does not return rule text. **Parameters (all optional):** - limit: max policies per page (1-100). Defaults to 10 when omitted. - cursor: opaque next_cursor from the previous response; omit for the first page. - default-policy filter: true = only default policies; false = only non-default; omit = both. - policy_ids: restrict to specific policy IDs. - statuses: defaults to CREATED (active). Pass ["DISABLED"] to list disabled/inactive policies, or ["CREATED","DISABLED"] for both.
list_expense_policies
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"). SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. EXPENSE ATTRIBUTION AND LIMIT ROUTING: - Listing results include spend_limit when available. It has an ID/name but no object type or containing-budget path; do not infer a spend limit versus employee card limit versus Budget from this field's name alone. - "How much did I spend on my Travel limit?" → resolve the spend limit with list_my_limits, then call this tool with expense_owner:"ME", limit_ids:[the returned ID], the requested date range, and aggregations:[{func:"SUM",field:"billing_amount",alias:"total_spend"}]. Omit group_by for a single total. - For managed spend limits, resolve names with list_spend_limits instead. Match the returned names and use budget_path to disambiguate duplicate names. Follow pagination as needed; do not guess IDs. - For a containing Budget, use its returned ID from budget_path. If discovery is needed, list_spend_limits exposes visible paths; its search parameter searches spend-limit names, not containing Budget names. limit_ids includes expenses assigned to the specified spend limits and descendants of specified containing Budgets. Pass the containing Budget ID once rather than summing overlapping parent/child queries. If the Budget cannot be resolved, ask for clarification rather than inventing an ID or claiming zero spend. - "My spend" means expense_owner:"ME"; for spend across everyone on a limit or Budget omit expense_owner and user_ids (subject to access). - Employee card limit amounts/available balances belong to list_my_limits (own) or list_employee_card_limits (account-wide). Do not assume limit_ids supports employee card limit IDs, or substitute user_ids: expenses owned by a user can be assigned to different limits. - group_by:["budget"] is the existing name-based expense grouping key, not a containing-Budget hierarchy rollup. It can combine identical names and does not provide object types or paths. For a total under a resolved containing Budget, use limit_ids plus SUM without group_by. 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 brex-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). EXTREMA — a SINGLE most/least expensive expense (not a total/breakdown): use LISTING mode with order_by:"amount", order_direction DESC (most) or ASC (least), limit:1. Do NOT use the default recency sort — it returns the most RECENT expense, not the highest-dollar one. order_by:"amount" ranks by the USD-normalized amount shown per row, so it's correct across mixed currencies. 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. DECLINED / FAILED CARD AUTHORIZATIONS ("why was my card declined?"): Failed authorization attempts ARE returned by this tool -- they are expenses whose payment_status is DECLINED (authorization refused) or CANCELED (authorization reversed or expired without clearing). A merchant retrying a charge produces several such records followed by a CLEARED one. To investigate, use LISTING mode with payment_statuses: ["DECLINED", "CANCELED"] plus whatever narrows it down (merchant/vendor, purchased_at_start/end, card, user). Each row's payment_status tells you the outcome, and payment_status_label carries the dashboard's own wording for it -- prefer that over paraphrasing the enum (CREDITED is shown as "Chargeback", and DECLINED is "Declined" on a card but "Failed" elsewhere). Then, for each expense you want explained, call get_expense_by_id with its id to read payment_status_reason -- the actual decline reason (EXCEEDED_CARD_LIMIT, MCC_BLOCKED, CARD_SUSPENDED, SUSPECTED_FRAUD, ...). This tool does NOT return payment_status_reason at all, because resolving it costs one extra lookup per expense; never report "declined for an unknown reason" from a list result. 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 with search_text 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 include. 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 pass include: ["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 pass include: ["travel_metadata"] When user asks about booking status or trip cancellation (e.g. was a travel booking canceled?): → You MUST pass include: ["travel_booking"] ⚠️ A null location does NOT mean "no location exists" - it means you did not request it in include. **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, 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.
list_expenses
List visible field definitions to find dimensions for classifying accounting records or match a requested field. Omit group to read all eligible definitions, or narrow by group. ACCOUNTING contains custom accounting fields native to Brex, with Brex as the source of truth. ERP contains accounting fields sourced from your connected ERP, such as NetSuite, with that ERP as the source of truth. USER contains user information fields. For ERP coding with a connected non-CSV integration, use ERP fields. Inspect field_type and is_disabled before recommending a value. For selectable choices, pass a returned brex_id as field_id to list_field_values. This tool returns field definitions, rather than values selected on individual records; it does not read or change a record's classification. Use field_id to filter known field IDs. When searching across pages, keep the same filters on every paginated request and follow each returned next_cursor; pagination is complete only when next_cursor is null.
list_fields
List legal entities (id, display name, verification status). Deleted entities are excluded. REQUIRED prerequisite for the list_users `entity` filter: 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` — never invent one. is_verified reflects KYC completion; it does not affect whether the entity can be used with the list_users entity filter. Parameters: limit (1-100, default 10), cursor (pagination), search_text (narrow by display name). Example Output: { "items": [{ "id": "le_1234", "name": "Brex Inc.", "is_verified": true }], "next_cursor": "cursor_abc" }
list_legal_entities
List locations (id + name). Deleted locations are excluded. Call it one of two ways: - The user names a location (for example "Is San Francisco one of our locations?" or "users in San Francisco"): pass that name as `search_text`. This is the only way to check whether a named location exists. Do not raise `limit` or page through results instead. - The user asks about locations in general: omit `search_text`, and follow `next_cursor` until it is null. list_users accepts only location IDs in its `location` filter. When the user names a location there, call this tool first with `search_text` and pass the returned `id` into list_users. Parameters: limit (1-100, default 10), cursor (pagination), search_text (the location name the user gave). Example Output: { "items": [{ "id": "culoc_1234", "name": "San Francisco" }], "next_cursor": "cursor_abc" }
list_locations
List merchant categories (e.g., Restaurants, Software, Travel). Used to resolve a category name to its ID so that list_expenses can filter by merchant_category_ids. Parameters: - query: Optional similarity search on category name. - limit: Max items per page (1-100, default 10). - cursor: Pagination cursor from a previous call. Example — find Restaurants category: { "query": "restaurant" } Response (trimmed): { "items": [{ "id": "mccat_abc", "name": "Restaurants" }], "next_cursor": null }
list_merchant_categories
List the current user's employee-card limit and membered card-spending limits, with amounts, balances, names, and IDs. For out-of-pocket reimbursement eligibility, use list_spend_limits with eligible_for_reimbursements=true; these card limits do not establish reimbursement eligibility. This is NOT a policy catalog and does NOT return policy rules. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. **WHEN TO USE:** - "My limits", card-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:** - Choosing a spend limit for an out-of-pocket reimbursement → list_spend_limits with eligible_for_reimbursements=true. Do not use card limits or current-period balances to infer reimbursement eligibility. - User already has a spend_limit_id and wants full policy rules → get_expense_policy directly **Routing (policies vs limits):** | User wants | Tool | | --- | --- | | 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 with search_text when the user asks about their own limits, even if the limit name contains a person's name. 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: - Employee card limit (USER_LIMIT): personal spending limit for the user - Spend limits: 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 (1-100, default 10) - 'cursor': pass next_cursor from the previous response - To retrieve the full set, continue until next_cursor is null SCENARIO-BASED EXAMPLES: Example 1: Get the first page of my limits (default - returns up to 10 limits): {} Example 2: Request 10 limits explicitly: { "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 {}; follow next_cursor as needed to find the limit → Find limit where name="Marketing Q1", extract ID (e.g., "budget_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 {}; follow next_cursor as needed to find the limit → Find limit where name contains "Travel", extract ID (e.g., "budget_xyz789") → Call list_expenses with: { "expense_owner": "ME", "limit_ids": ["budget_xyz789"] } Scenario 3: "Can I expense Uber Eats on my company card?" (policy RULES — not catalog) → Call list_my_limits with {}; follow next_cursor as needed to inspect active limits → If user has only one active limit, extract its ID (e.g., "budget_policy123") → Call get_expense_policy with: { "spend_limit_id": "budget_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 {}; follow next_cursor as needed to get the relevant limit ID → Extract relevant limit ID (e.g., "budget_corp456") → Call get_expense_policy with: { "spend_limit_id": "budget_corp456" } → Check policy rules for approval thresholds on meal expenses Scenario 5: "How much did I spend on my Q1 Marketing limit in March 2025?" → Call list_my_limits with {}; follow next_cursor as needed to find "Q1 Marketing" → Extract limit ID (e.g., "budget_mkt789") → Call list_expenses with: { "expense_owner": "ME", "limit_ids": ["budget_mkt789"], "aggregations": [{"func": "SUM", "field": "billing_amount", "alias": "total_spend"}], "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 {}; follow next_cursor as needed to find "Travel" → Extract the Travel limit ID (e.g., "budget_travel101") → Call get_expense_policy with: { "spend_limit_id": "budget_travel101" } → Present the complete policy rules from the response
list_my_limits
Discover Brex server guidance and supporting context. Returns metadata and file manifests without loading instructions. An empty catalog means no workflow guides are published; other available tools do not imply that guides exist. Use load_skills to read a listed guide when needed. Errors: BAD_REQUEST (invalid cursor), UNAUTHORIZED, FORBIDDEN, TOO_MANY_REQUESTS, INTERNAL_SERVER_ERROR.
list_skills
Lists spend limit groups the caller can manage: name, status, parent budget, and ID. Callers with account-wide budget access see every group; others see only groups they can access. USER-FACING RULES (every reply): - Don't show IDs unless asked; name objects by display name. - Say "spend limit group". Tell same-named groups apart by status and parent budget. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. ROUTING: - Use this tool for: groups I can manage, a named group, every group including archived, or a group's limit per user. - Spend limits I manage → list_spend_limits. Limits I can spend from → list_my_limits. Employee card limits → list_employee_card_limits. - Every group or a count → follow next_cursor until null; one page, even a full one, is never the whole set.
list_limit_groups
Lists manageable spend limits, or explicitly requested out-of-pocket reimbursement limits. "What can I spend from?" / "my limits" → list_my_limits, not this tool; do not infer reimbursement intent. "What can I reimburse against?" → this tool with eligible_for_reimbursements=true. Never returns spend limit groups; for any question about groups, use list_limit_groups. SPEND TERMINOLOGY: - Spend limits are spending controls that exist independently of cards and can be assigned to expenses. - Employee card limits (USER_LIMIT in tool results) are personal limits used by employee cards. An employee card is the card itself, not its limit; employee cards can also use separately issued spend limits. - Budgets are separate planning/tracking containers that can contain spend limits and other budgets. A containing Budget is not the expense's assigned spend limit. budget_path describes visible containing budgets. - Spend limit groups are templates giving each eligible member their own spend limit, not shared funds. A group is neither a spend limit nor a Budget; its parent_budget is its containing Budget. - If a user says "budget", use the conversation and returned object types/path to distinguish a spend limit from a containing Budget. If the distinction remains ambiguous and changes the answer, ask which they mean; do not silently substitute one for the other. - Use these product names in replies. Field names and ID prefixes such as budget_* do not establish the object's product type. Use returned IDs unchanged for tool calls and identify objects by name in replies. ROUTING: - Management: owner-scoped, directly or through an ancestor budget; account-wide with budget access. - Bill Pay: status=ACTIVE, eligible_workflow=BILLPAY_BILLS. - Balances: include=["period_balance"]; pass receipt purchase_date, or omit for each limit's current period. - Limits I can spend from → list_my_limits. Employee card limits → list_employee_card_limits. - All results/counts: follow next_cursor until null; preserve filters/includes.
list_spend_limits
List employee titles (id + display title). Call it one of two ways: - The user names a title (for example "Is Software Engineer one of our titles?" or "users in Software Engineer"): pass that name as `search_text`. This is the only way to check whether a named title exists. Do not raise `limit` or page through results instead. - The user asks about titles in general: omit `search_text`, and follow `next_cursor` until it is null. list_users accepts only title IDs in its `title` filter. When the user names a title there, call this tool first with `search_text` and pass the returned `id` into list_users. Parameters: limit (1-100, default 10), cursor (pagination), search_text (the title name the user gave). Example Output: { "items": [{ "id": "ti_1234", "name": "Software Engineer" }], "next_cursor": "cursor_abc" }
list_titles
List travel bookings across the company with filtering, sorting, and pagination. Mirrors the Bookings page on the Brex dashboard (Travel → Company → Bookings). Use this tool when the user asks specifically about individual bookings (flights, hotels, car rentals) rather than whole trips. Results are always sorted by booking start date descending. Filters are grouped to match the dashboard: General: - booking_start_date_on_or_after / booking_start_date_on_or_before: Booking start date. Date (YYYY-MM-DD) bounding the booking start date (local). - booking_types: Booking type. Array of booking categories (AIR, CAR_RENTAL, LIMO, LODGING, MISC, RAIL). People: - booker_user_ids: Booker. Array of booker (employee) user IDs (cuuser_*) to filter by specific bookers. - traveler_user_ids: Traveler. Array of traveler user IDs (cuuser_*) to filter by traveler. - traveler_guest_emails: Traveler. Array of guest traveler emails to filter by traveler. - traveler_types: Traveler type. Array of ["EMPLOYEE", "GUEST"] to narrow by traveler type. Status: - booking_statuses: Booking status. Array of booking statuses (CONFIRMED, PENDING, CANCELED, etc.). - approval_statuses: Approval status. Array of approval statuses (APPROVED, PENDING, REJECTED). - policy_statuses: Policy status. Array (IN_POLICY, OUT_OF_POLICY). Pagination: - limit: Max items per page (1-100, default 10). - cursor: Cursor from a previous response's next_cursor. Example: { "booking_types": ["AIR"], "booking_statuses": ["CONFIRMED"] }
list_bookings
List travel trips across the company with filtering, sorting, and pagination. Mirrors the Trips page on the Brex dashboard (Travel → Company → Trips). Use this tool when the user asks for a company-wide view of trips (e.g. "show all pending trips", "trips booked for Jane next month"). Filters are grouped to match the dashboard: General: - trip_statuses: Trip status. Array of trip statuses to include (e.g. ["UPCOMING", "PENDING"]). When omitted, trips in DRAFT, DELETED, or VOIDED states are excluded by default. To surface those, set trip_statuses explicitly. - policy_status: Policy status. Filter by policy compliance across a trip's bookings (IN_POLICY, ANY_OUT_OF_POLICY, ALL_OUT_OF_POLICY). Trips without bookings are excluded when this is set. Payment: - spend_limit_ids: Spend limit. Array of spend-limit IDs to filter trips by the associated spend limit. Date: - billable_at_on_or_after / billable_at_on_or_before: Billable at. ISO-8601 timestamps bounding the trip's billable-at time. - start_date_on_or_after / start_date_on_or_before: Start date. Date (YYYY-MM-DD) bounding the trip start date. People: - booker_scope: ALL_USERS, SELECTED_USERS, or SELF. Defaults to SELF on the GraphQL layer when omitted. - booker_user_ids: Booker. Array of booker (employee) user IDs (cuuser_*). Required when booker_scope is SELECTED_USERS. - traveler_user_ids: Traveler. Array of traveler user IDs (cuuser_*) for employees to filter by traveler. - traveler_guest_emails: Traveler. Array of guest traveler emails. - traveler_types: Traveler type. Array of ["EMPLOYEE", "GUEST"] to narrow by traveler type. Sorting: - order_field: Field to sort by (START_DATE, BILLABLE_AT, INSERTED_AT). - order_direction: ASCENDING or DESCENDING. Defaults to DESCENDING. Pagination: - limit: Max items per page (1-100, default 10). - cursor: Cursor from a previous response's next_cursor. Example: { "trip_statuses": ["UPCOMING", "PENDING"], "order_field": "START_DATE", "order_direction": "DESCENDING", "limit": 25 }
list_trips
**DEPRECATED:** Use list_users with search_text instead. list_users with search_text, limit 10, sort FIRST_NAME and direction asc returns exactly what this tool returns. Searches users by name or email and returns up to 10 matches sorted by first name. - include: Optional token phone_number. Unrequested fields are null. brex_assistant and notification_preferences are not available on list.
list_users_by_name_or_email
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: Max items per page (1-100, default 10) - search_text: Input used for trigram-based fuzzy matching of vendor names - 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: Fuzzy matches vendor names using trigram word similarity - 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 vendor name (ACTIVE by default): { "search_text": "Corp", "limit": 10 }
list_vendors
Brex ChatGPT Plugin FAQ
How the directory, categories and Discoverability Score work.
Read the methodologyHow do I improve Brex's ChatGPT Plugin discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Brex alternatives on ChatGPT?
As of 2026-11-02, Brex competes with Clara Mexico Intelligence, Eqolux, Expensify, GSA Per Diem Rate Calculator, Inteligencia Corporativa Clara, Inteligência Corporativa Clara, Odometry Mileage Log, Perk and 5 more in ChatGPT Corporate Spend, Expense & Procurement, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.