Before You Start
You need:- A Brew brand connected to your assistant, with opted-in contacts already in it
- A CRM connected to the same assistant, with read access to contacts
- Contacts that exist in both systems under the same email address
1. Check What Brew Already Has
Some fields are native. Don’t create custom fields that duplicate them.
Ask your assistant:
List the custom fields in my Brew brand.
2. Create the Fields You’re Missing
Name each field after its source so nobody has to guess where the data came from.Create these custom fields in Brew: crm_lifecycle_stage (string), crm_owner (string), crm_last_contacted (date), crm_record_id (string).Brew normalizes names to camelCase. You declare the underscored name and get the camelCase one back:
fieldName is what your audience filters use, not the name you typed.
Field types are string, number, date, or bool. Declare anything date-like as date so comparisons work.
3. Pick Which CRM Properties to Sync
Only sync what you’ll actually filter on. Four fields cover most exclusion cases:
Verify the internal property names before you build anything. Display labels and internal names differ in most CRMs.
Read the property definitions for contacts in [CRM] and show me the internal names and stored values for [your properties].Some CRMs store dropdown values as internal codes or numeric IDs rather than the label you see. A filter written against the label matches nothing, so check the real stored values first.
4. Run the Sync
Get [your four properties] from [CRM] for every contact in [list or segment]. Update each matching Brew contact with those values. Tell me how many you updated and list any you couldn’t match.Always ask for the count and the unmatched list. An assistant working a long list can skip rows without error. The count is your only proof it finished. Ask for the report in this shape so gaps are obvious:
5. Build the Audience
Add filter conditions in the Brew UI, or ask your assistant:Create a Brew audience called “Q3 nurture” where hubspotLifecycleStage is not opportunity, hubspotOwner is empty, and hubspotLastContacted is before 30 days ago.Use the camelCase field names from step 2. Available operators:
Audiences are saved filters, not frozen snapshots. They re-evaluate at send time against whatever was last synced. Creating one returns the match count immediately:
6. Verify
Change one thing in your CRM and re-run the sync. Check that the audience count moves by the number you expect, not just that it moved.
Use two or three test contacts and confirm before you rely on it for a real send.
From MCP
Your Brew connection is bound to one brand, picked when you connected. The CRM side may be workspace-scoped depending on the provider, so confirm you are pointed at the right brand before writing. Brew tools accept an optionalbrand_id. Omit it to use the bound brand, since supplying a different one fails with BRAND_SCOPE_MISMATCH rather than writing to the wrong place. See Authentication and Scoping.
list_custom_fieldsshows what already exists. Fields withisCore: trueare built in and can’t be created or deleted. Call this before creating anything.create_custom_fieldtakesfieldNameandfieldType. Creating a field that already exists is safe, it returns the existing definition. Field names can’t contain whitespace, path separators, or quotes.update_contacttakes anemailand afieldsmap, one contact per call. There’s no batch write, so work through a large list in chunks and report the running count.create_contactupserts by email and returnscreated: true|false. Use it only for contacts who opted in through your own signup or checkout, not to pull a CRM list into Brew.
idempotency_key, a fresh UUID per intended action, so a retry replays the original result instead of acting twice. The same key with a different payload returns a 409. See Idempotency.
If a CRM property has no value for a contact, leave the Brew field unset. Don’t write an empty string. An unset field reads as “not synced yet”, while a blank one falsely reads as “synced, and empty.”
The full tool catalog is in MCP Tools.
When the Sync Fails
What This Does and Doesn’t Do
Syncs when asked, not automatically. Nothing fires when a record changes in your CRM. Run the sync immediately before a send. A daily sync leaves up to 24 hours of drift. That’s long enough for a rep to open a deal at 9am and your 4pm send to email them anyway. One direction. This pulls CRM data into Brew. To write engagement back to the CRM, see Sync Brew and Attio Over MCP. Matches on email only. If your CRM stores multiple addresses per contact, decide which one is authoritative before syncing. Otherwise one person becomes two Brew contacts. Stores values, not flags. WritecrmLifecycleStage = "customer", not isCustomer = true. Keeping the real value means un-suppressing costs nothing and new filters don’t need a re-sync.
Empty fields may be invisible. Some CRMs omit unset properties from API responses entirely rather than returning null. An absent value is ambiguous. It can mean “never happened” or “this CRM isn’t tracking it.”
Check that a real sample is populated before you filter on it. A recency filter built on an empty field won’t error. It will silently fail to suppress, and you’ll hear about it from a recipient.
Need Help?
Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:- Self-Service Tools
- Talk to Our Team
Search Documentation
Type in the “Ask any question” search bar at the top left to instantly find relevant documentation pages.
ChatGPT/Claude Integration
Click “Open in ChatGPT” at the top right of any page to explore it further with ChatGPT or Claude.