Migrate from MailerLite to Unitpost

A MailerLite campaign arriving in Unitpost as a plain-text draft, its image and button left to rebuild in the editor

Contacts, suppressions, templates, sending domains and more come over in one import.

What comes with you

To leave MailerLite, paste a MailerLite API token into Unitpost's Migration Assistant. It imports subscribers with their status and custom fields, groups and segments as segments, bounced and spam-complaint subscribers as suppressions, and webhooks. MailerLite's API returns no email HTML, so campaigns arrive as plain-text drafts you rebuild in the editor. Unconfirmed subscribers are left out. Only current MailerLite accounts connect: Classic accounts from before March 2022 use a different API.

DataResultWhat happens
ContactsImportsSubscribers import with MailerLite's name field as the first name, last_name as the last name and every other field as a custom field, plus their opt-in date and signup source.
Unsubscribes and consentImportsUnsubscribed, bounced and junk subscribers import unsubscribed. Unconfirmed subscribers never confirmed double opt-in, so MailerLite can't email them either, and they are left out.
Suppressions (bounces and complaints)ImportsMailerLite has no separate suppression list; a subscriber's status is the record. Bounced subscribers import as bounce suppressions and junk subscribers, who marked an email as spam, as complaint suppressions.
Groups and segmentsPartly importsGroups become static segments with their members. MailerLite segments come over as a snapshot of today's members, because MailerLite's API doesn't return their filter rules.
TemplatesPartly importsMailerLite's REST API has no templates endpoint and returns campaign emails as subject and plain text only. Draft campaigns and your 25 most recent sent campaigns arrive as plain-text drafts with {$name} style variables rewritten; rebuild each design in the editor.
Sending domainsPartly importsMailerLite's API has no domains endpoint. Domains seen on your campaigns' sender addresses are recreated as verifying with new DKIM keys; add any others in Domains.
WebhooksPartly importsWebhooks import switched off with a new signing secret. Subscriber, bounce, spam, open and click events map to ours; campaign.sent and automation events don't. MailerLite limits webhooks on its Free plan, so they may not be readable there.
TopicsRebuildMailerLite has no topics. If readers picked groups in your preference center, create a topic for each here.
API keysRebuildMailerLite tokens stay at MailerLite. Create Unitpost API keys instead, and delete the token you used for the import.
SMS consentRebuildMailerLite's API has no SMS data. Its phone field comes over as a custom field, not as the contact's SMS number, and carries no consent. Add numbers and record consent before you text anyone.
Send history and analyticsStays behindCampaign reports, opens, clicks and subscriber activity stay at MailerLite.
AutomationsStays behindMailerLite automations stay; the preview lists them with their email count. Rebuild them in Unitpost Automations, which are in early access, or send those emails from your code.
Forms, landing pages, websites and productsStays behindNot read. Unitpost has no hosted forms, landing pages or websites, and doesn't sell to readers.

Before you start

  • A MailerLite API token: Integrations → MailerLite API → Generate new token. MailerLite shows it once.
  • Leave IP restrictions off for this token. MailerLite lets you limit a token to certain IP addresses, and a restricted token refuses the importer.
  • A current MailerLite account. Accounts created before March 2022 that still run on MailerLite Classic use a separate API and key, which the importer doesn't read.
  • MailerLite tokens have no read-only setting and stop working if the user who made them leaves the account. The importer only reads; delete the token when the move is done.
  • A Unitpost API key for your app with emails:send, plus contacts:write and segments:write if your signup form adds contacts, created in API keys.
  • A second Unitpost key for the migration steps, with templates:write and webhooks:manage, saved as UNITPOST_MIGRATION_KEY. Keep it out of your app and revoke it once the move is done.
  • Access to your DNS host.

The cut-over plan

MailerLite keeps sending until the last step, so there is no gap in delivery.

  1. Run the Migration Assistant

    Paste the token in Settings → Migration. The preview counts subscribers by status, lists the unconfirmed ones it leaves out, and shows which campaigns arrive as plain text. Suppressions are written before contacts, so bounced and junk addresses land unsubscribed.

  2. Verify your domain

    Open Domains, add any domain the importer didn't find, and publish the records shown: MX and SPF on unitpost.<your domain> and a DKIM TXT under _domainkey. They don't replace MailerLite's records, so both stay authenticated while you move. Keep your single _dmarc record.

  3. Rebuild designs from the plain-text drafts

    Each campaign arrives as a plain-text draft with its subject. Rebuild the layout in the visual editor, or paste your own HTML in code mode. {$name} became {{first_name}}, {$last_name} {{last_name}}, {$email} {{email}} and {$unsubscribe} {{unsubscribe_url}}; |default('…') fallbacks are dropped, and {$url}, {$forward} and {$preferences} stay for you to replace. Publish with PATCH /api/v1/email/templates/{id}.

  4. Point signups at Unitpost

    MailerLite forms, landing pages and websites keep adding subscribers to MailerLite. Send signups from your own form with POST /api/v1/contacts, and add the contact to the segment that replaced each group. MailerLite's create call updates an existing subscriber; here an existing contact answers 409, and PATCH /api/v1/contacts/{id or email} updates it.

    signup.ts
    // Before: MailerLite
    await fetch("https://connect.mailerlite.com/api/subscribers", {
      method: "POST",
      headers: { Authorization: "Bearer " + process.env.MAILERLITE_API_KEY, "content-type": "application/json" },
      body: JSON.stringify({
        email: "user@example.com",
        fields: { name: "Ada", last_name: "Lovelace" },
        groups: [GROUP_ID],
      }),
    });
    
    // After: Unitpost
    import { Unitpost } from "unitpost";
    const unitpost = new Unitpost(process.env.UNITPOST_API_KEY);
    const { error } = await unitpost.contacts.create({
      email: "user@example.com",
      first_name: "Ada",
      last_name: "Lovelace",
    });
    // 409 conflict: the contact already exists. MailerLite's call upserts; update with contacts.update.
    if (error && error.code !== "conflict") throw new Error(error.message);
    // A group became a static segment.
    await unitpost.segments.addMember("seg_123", { contact: "user@example.com" });
  5. Re-key and enable webhooks

    MailerLite signs each delivery with a Signature header, an HMAC-SHA256 of the body. Unitpost signs with a whsec_ secret in svix-id, svix-timestamp and svix-signature. Rotate the secret in Webhooks to see it, update your handler, then set status to enabled.

  6. Test, move traffic, then delete the token

    Send each template with POST /api/v1/email/templates/{id}/test-send and fire POST /api/v1/webhooks/{id}/test at each endpoint. Send your next campaign from Unitpost to a small segment first, then to everyone, and delete the MailerLite token.

Name changes

Same ideas, new names

MailerLiteUnitpostNote
SubscriberContact
GroupSegment (static)
SegmentSegment (dynamic)Imported as a snapshot; rebuild the filter.
FieldContact field
name fieldFirst name
Junk subscriberSuppression (complaint)
Unconfirmed subscriberNot imported
CampaignCampaign
AutomationAutomationsIn early access.
Preference center ({$preferences})Unsubscribe preference page
{$name}{{first_name}}

API calls

MailerLite APIUnitpost APINote
POST /api/subscribersPOST /api/v1/contactsMailerLite's call upserts; here an existing contact answers 409 and you update it with PATCH.
PUT /api/subscribers/{id}PATCH /api/v1/contacts/{id or email}MailerLite's PUT removes groups you leave out; segment membership here changes only through the segment calls.
GET /api/subscribersGET /api/v1/contacts
POST /api/subscribers/{subscriber_id}/groups/{group_id}POST /api/v1/segments/{id}/contacts
GET /api/groupsGET /api/v1/segments
GET /api/segmentsGET /api/v1/segments
GET /api/fieldsGET /api/v1/contact-fields
POST /api/campaignsPOST /api/v1/email/campaigns
POST /api/webhooksPOST /api/v1/webhooks
Authorization: Bearer on connect.mailerlite.comAuthorization: Bearer <api key>

Webhook events

MailerLite eventUnitpost eventNote
subscriber.createdcontact.created
subscriber.updated, subscriber.unsubscribed, subscriber.activecontact.updated
subscriber.added_to_group, subscriber.removed_from_groupsegment.joined, segment.leftThe importer maps them to contact.updated; the segment events are the closer match.
subscriber.deletedcontact.deleted
subscriber.bouncedemail.bounced
subscriber.spam_reportedemail.complained
campaign.openemail.opened
campaign.clickemail.clicked
campaign.sentemail.sentOurs fires per recipient.
subscriber.automation_triggered, subscriber.automation_completedNo equivalent

Before you cancel MailerLite

  • Export subscribers as CSV, including unconfirmed ones, which the importer leaves out.
  • Save the designs you still use; MailerLite's API can't hand them over.
  • Write down each automation, with its trigger, steps and delays.
  • Move your forms, landing pages and websites, or keep MailerLite for them.
  • Delete MailerLite's DNS records once no mail goes through MailerLite. Keep _dmarc and Unitpost's records.
  • Delete the MailerLite API token you used for the import.

Facts about MailerLite checked 2026-11-05. Providers change their APIs and plans; check their docs before you rely on a detail.

Questions about leaving MailerLite

Why are my MailerLite emails plain text?

MailerLite's REST API returns a campaign's subject and plain-text version, never its HTML, and has no templates endpoint. The importer brings what the API gives. Rebuild each design in Unitpost's visual editor or paste your own HTML into code mode.

My account is on MailerLite Classic. Can I connect it?

Not directly. Classic accounts, created before March 2022, use a separate API and key that the importer doesn't read. MailerLite lets a Classic account move to the current MailerLite; do that first, or export subscribers as CSV and import them in Contacts.

MailerLite rejected a valid token. Why?

Most often the token is limited to certain IP addresses, which refuses the importer. Create a token without IP restrictions. A token also stops working when the user who made it leaves the account.

Does Unitpost replace MailerSend too?

MailerLite sends transactional email through MailerSend, a separate product. Unitpost sends transactional and marketing email on one API and one bill, so one account covers both. The importer reads MailerLite only, not MailerSend.

Leaving MailerLite?

Preview the migration on the free tier

Verify a domain, paste an API key, and see what would come across before anything is written.