ml-connector
Sage X3Brex

Sage X3 and Brex integration

Sage X3 runs finance, procurement, and inventory. Brex manages corporate cards and expenses. Connecting the two routes company spend from Brex directly into your Sage X3 general ledger without re-keying, and matches vendors and cost centers so expenses land on the correct accounts. The finance team sees all card activity in X3 without manual entry, and month-end reconciliation starts with spend already accounted for.

How Sage X3 works

Sage X3 exposes suppliers, purchase orders, sales invoices, products, GL accounts, and general ledger entries through REST (legacy api1), GraphQL (Xtrem, V12+), or SOAP endpoints at a customer-specific server URL and port. Authentication uses OAuth2 client credentials with Connected Application for GraphQL, or HTTP Basic authentication for REST api1 (when explicitly enabled by customer admin). Access tokens expire in 5 minutes with 30-day refresh tokens. Sage X3 has no native webhooks or push notifications, so records are detected via poll using updatedDate and modifiedDateTime fields. Analytical dimensions on GL entries vary per customer configuration. The REST api1 endpoint has a default page size of 20 records.

How Brex works

Brex exposes corporate card transactions, cash transactions, expenses, vendors, transfers, and accounting records through REST APIs at https://api.brex.com. Authentication uses Bearer tokens: either a static API key (90-day inactivity expiry) for single-tenant access, or OAuth2 Authorization Code (1-hour token lifetime, 30-day refresh tokens with offline_access scope) for multi-tenant. Brex supports webhooks via Svix with HMAC-SHA256 signature verification, emitting events for TRANSFER_PROCESSED, TRANSFER_FAILED, EXPENSE_PAYMENT_UPDATED, USER_UPDATED, and ACCOUNTING_RECORD_READY_FOR_EXPORT. Transactions are read-only; writes are available on Expenses, Vendors, Transfers, Users, Cards, and Budgets. Expenses endpoint returns a maximum of 100 per page. POST transfers require an Idempotency-Key header to ensure deduplication.

What moves between them

The main flow runs from Brex into Sage X3. ml-connector reads Brex corporate card transactions and expense records, either by polling the Brex Expenses and Transactions endpoints on a schedule or by receiving webhook events for EXPENSE_PAYMENT_UPDATED and ACCOUNTING_RECORD_READY_FOR_EXPORT. For each record, it validates that the vendor exists in Sage X3 (or creates a supplier record if the configuration allows), maps the Brex vendor and amount to a Sage X3 GL account and cost center, and posts the transaction to X3 as a general ledger entry or expense record. Brex card activity flows as GL entries in X3; no data flows back from X3 to Brex, since Brex transactions are read-only. The cadence matches your expense report and card reconciliation cycle.

How ml-connector handles it

ml-connector stores Brex API credentials (OAuth2 or static key) encrypted and refreshes OAuth tokens when they expire. On the Sage X3 side, it accepts the full server URL, port, and folder path per customer, since X3 publishes no central tenant registry, and uses either HTTP Basic auth (if enabled in nodelocal.js) or OAuth2 client credentials. For webhook-based sync, ml-connector registers a webhook endpoint with Brex and verifies HMAC-SHA256 signatures using Svix. For polling, it queries the Expenses and Transactions endpoints with delta detection on modifiedDate and updatedDate fields. Before posting to Sage X3, ml-connector validates vendor references against X3 suppliers, resolves cost centers and GL accounts per customer configuration (since analytical dimensions vary), and batches expenses into GL entry sets. If a Brex expense references a vendor not found in X3, it either skips the record with an audit note, maps to a default expense account, or creates a supplier record, depending on configuration. All GL entries carry source trace IDs, full audit trails, and can be replayed if a downstream write fails. Brex rate limits are handled with exponential backoff. Idempotency keys are generated per transaction to prevent duplicate posting if a write call is retried.

A real-world example

A mid-sized professional services firm runs Sage X3 for accounting and project costing, and issues Brex corporate cards to consultants and staff for travel and client entertainment. Before the integration, the finance team exported Brex transaction reports weekly, matched them to vendor profiles, manually classified spend by project cost center, and keyed each batch into Sage X3 as a journal entry, introducing error and delay. With Sage X3 and Brex connected, each Brex transaction posts to X3 automatically on reconciliation day, allocated to the correct project and cost center, and the finance team's manual re-keying step is eliminated. Spend is visible in X3 in real time, project profitability is accurate, and month-end close starts with card expenses already in the ledger.

What you can do

  • Read Brex corporate card transactions and expense records via webhook events or scheduled polling, and post them to Sage X3 as general ledger entries.
  • Map Brex vendors to Sage X3 suppliers and route spend to the correct GL accounts and cost centers based on customer configuration.
  • Authenticate Brex with OAuth2 or static API key, and Sage X3 with HTTP Basic or OAuth2, handling token refresh and credential expiry.
  • Validate vendor and cost center references in Sage X3 before posting, and audit-trail every transaction with replay capability if a downstream write fails.
  • Handle Brex rate limits and POST idempotency with exponential backoff and deduplication keys, ensuring no duplicate expenses enter the general ledger.

Questions

Which direction does data move between Sage X3 and Brex?
Data flows from Brex into Sage X3. Corporate card transactions and expenses from Brex post to X3 as general ledger entries or expense records, allocated to the correct GL accounts and cost centers. Brex transactions are read-only, so ml-connector does not write activity back to Brex.
Does the integration work with Brex webhooks or does it poll instead?
ml-connector supports both. It can register a webhook endpoint with Brex to receive EXPENSE_PAYMENT_UPDATED and ACCOUNTING_RECORD_READY_FOR_EXPORT events in real time via Svix. It can also poll the Brex Expenses and Transactions endpoints on a schedule if webhooks are not enabled. Webhook events include HMAC-SHA256 signature verification for security.
How does the integration handle vendor matching and cost center allocation in Sage X3?
Before posting an expense to Sage X3, ml-connector validates the vendor reference against X3 suppliers. If the vendor exists, the expense is routed to the GL account and cost center configured for that vendor. If the vendor is not found, the integration can skip the record, map to a default expense account, or create a supplier record in X3, depending on your configuration. Analytical dimensions are resolved per customer since X3 configuration varies.

Related integrations

Connect Sage X3 and Brex

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started