Concepts
1. Export Contacts From Loops
Audience page → filter to a segment if you want a subset → Export. Loops writes one CSV of whatever’s in view, with columns for default and custom properties only. There’s no separate export per subscription status, so filter bySubscribed first if you only want active contacts.
Carries over cleanly: email, name, source, custom properties, and subscribed (true/false).
Mailing list membership doesn’t carry over automatically. Loops’ export includes contact properties, not list membership. A straight export and import won’t preserve which lists someone belonged to.
If that matters, filter to each list and export it separately, then reconstruct it in Step 4.
Event history and workflow enrollment state don’t carry over either. Those live in Loops with no Brew equivalent to import into.
In Loops, unsubscribing blocks campaigns and workflows. Brew’s marketing sends respect the same flag, so the behavior your subscribed contacts expect doesn’t change.
2. Map Your CSV
Notes:
userGroupand any custom properties become Brew custom properties. BringuserIdtoo if anything downstream matches on it- These names are reserved and can’t be used for custom properties:
email,first_name,last_name,subscribed,created_at,updated_at,validation_status,last_validated_at,import_id - Mailing list membership needs its own export per list (see Step 1), then its own import into the matching property. It won’t ride along with a general contact import
{firstName} works in campaigns and workflows, and {EVENT_PROPERTY:name} in workflow emails triggered by events.
The first becomes Brew’s {{ firstName | there }}. The property name is case-sensitive, and the fallback shows when the value is missing.
The second becomes a trigger payload reference, written the same way: {{ orderId }}. See merge tags.
{DATA_VARIABLE:name} lives only in Loops transactional emails, which stay in Loops for now.
One difference worth knowing: in Loops, a missing property value with no fallback means the email doesn’t send. In Brew the fallback lives inside the tag itself. There’s no separate step where you could forget one and have a send fail silently.
3. Import Into Brew
Audience → Add contacts → CSV Upload. Map columns, tick validation if the list hasn’t been checked recently, review, then import. Full import behavior is in Add Contacts.4. Rebuild Segmentation
Filters and Segments map to Brew Audiences, dynamic filters over contact properties, email engagement, and subscription status. Describe one in plain English or build the filters by hand. Mailing Lists don’t have a direct equivalent. Brew has one subscription state per contact, subscribed or unsubscribed. There are no opt-in categories and no subscriber-facing preference center. Marketing emails and automations respect that flag. Rebuild each list as a custom property plus an Audience filtered on it. You keep the targeting, but membership is yours to manage. Contacts can’t pick lists for themselves, and unsubscribing opts them out of all marketing email rather than one list. If a Loops list carried a real consent distinction, decide how to honor it before your first send.5. Rebuild Templates
Open Emails in the sidebar, then use the Import tools on the right side of the canvas. See Importing existing designs.
Loops themes, the shared styling across transactional emails, don’t carry over as a concept. Brew’s brand identity replaces the need for a manually maintained theme. Set it once and every rebuilt template inherits your logo, colors, fonts, and voice.
6. Rebuild Workflows as Automations
Loops has a trick for re-running an existing contact through a workflow. Download a CSV, then
re-upload it with “Trigger workflows” toggled on. That maps to a manual-audience run in Brew, the one-off, on-demand option, not a live trigger.
Manual-audience automations are launched with
POST /v1/automations/{automationId}/run rather than published.
Branches become Filter or Split nodes, and delay steps become Wait nodes. Test-fire before publishing, and leave every rebuilt automation unpublished until cutover. That’s what prevents a double-send.
7. Swap Your Code Over to Triggers
Your Loops code has two kinds of call, and they migrate differently.sendEvent calls move to Brew now. A cart-abandonment or trial-ending email is a marketing send fired per recipient by a custom event. In Brew that’s a trigger event plus an automation, and every per-recipient marketing send goes through it.
sendTransactionalEmail calls stay in Loops for now. Brew’s transactional email isn’t generally available yet. Leave resets, magic links, and
receipts pointed at Loops until it is. When it ships, those calls will follow the same trigger pattern as everything below.
Set each marketing event up once:
POST /v1/automations/triggersto create the trigger event, for example “Trial started”. Capture thetriggerEventId. You can also create it in-app from Trigger events.POST /v1/emailsto generate the email design. Capture both theemailIdand theemailVersionId.GET /v1/domainsfor a verifieddomainId.POST /v1/automationswith a Send Email node wired to that trigger. Each sendEmail node carriesemailId,emailVersionId,domainId,subject, andpreviewText.PATCH /v1/automations/{automationId}with{ "published": true }.- Replace the Loops
sendEventcall in your backend with a fire request.
Idempotency-Key on every retried call, the same discipline you used in Loops. Derive it from something stable about the action, like the subscription id above.
A key built from a timestamp changes on every retry, which defeats the point and lets a retry send twice. Idempotency covers the replay window and conflict behavior.
Full request shapes are in the API reference. This is the shape of the migration, not a copy-paste replacement for it.
8. Cut Over
Move one email type at a time.- Warm up your Brew sending domain before any real volume, most engaged contacts first, ramped over several days. Gradual send does the ramping for you.
- Import contacts and rebuild templates and automations while Loops keeps sending everything as normal.
- Cut over your lowest-risk campaign first, a newsletter, to confirm delivery and rendering.
- Move workflows one at a time, once their triggers are confirmed firing correctly. Watch each one in analytics before moving the next.
- Point signup forms and inbound integrations at Brew once everything upstream is verified.
- Transactional email stays in Loops, so keep the plan that covers it. Downgrade the rest once the marketing side is confirmed, and revisit when Brew’s transactional email is generally available.
Quick Reference
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.