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.
One reassuring parallel: in Loops, unsubscribing blocks campaigns and workflows while transactional email still goes through. Brew works the same way, so that part of the behavior your users already 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, {EVENT_PROPERTY:name} in workflow emails triggered by events, and {DATA_VARIABLE:name} in transactional emails.
The first becomes Brew’s {{ firstName | there }}. The property name is case-sensitive, and the fallback shows when the value is missing.
The other two become trigger payload references, written the same way: {{ orderId }}. See merge tags.
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, and transactional sends bypass it. 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
Loops’ transactional call is one request: atransactionalId, the recipient, and dataVariables. Brew has no single-call equivalent. Every per-recipient send, marketing or transactional, goes through the same trigger and automation system.
That matters even if you never sent transactional email from Loops. A cart-abandonment or trial-ending email is a marketing send fired per recipient by a custom event. It uses this exact mechanism, and transactional email is one case of it, not a separate system.
Set each one up once:
POST /v1/automations/triggersto create the trigger event, for example “Password reset requested”. 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 call 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 reset token 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
Loops mixes transactional and marketing on one audience, so a single flip-the-switch day is riskier than it needs to be. 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 marketing email first, a newsletter rather than a password reset, to confirm delivery and rendering.
- Move transactional email types one at a time, reset link first, then receipts, then whatever’s left. Watch each one in analytics before moving the next.
- Move workflows last, once their triggers are confirmed firing correctly.
- Point signup forms and inbound integrations at Brew once everything upstream is verified.
- Keep Loops active but unused for a couple of weeks as a fallback, then downgrade or cancel.
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.