# Envie as inscrições do seu próprio formulário de newsletter para o MailerLite

> Conecte seu próprio formulário de inscrição ao MailerLite: um relay adiciona novos leitores como não confirmados para o double opt-in e nunca pede a um assinante que confirme duas vezes.

Publicado em 2026-10-25 · https://ikiform.com/pt-br/guides/newsletter-signup/mailerlite

Envie seu próprio formulário ao Ikiform e aponte o webhook para um relay que chama a API do MailerLite. O relay procura o endereço primeiro: um leitor novo é criado como `unconfirmed`, o que faz o MailerLite enviar o e-mail de double opt-in quando a opção da API está ligada, e um assinante existente só ganha o novo grupo. É essa consulta que impede que um assinante confirmado seja convidado a confirmar de novo.

## O que muda com o MailerLite

O endpoint de criar assinante do MailerLite é um upsert: um `POST` em `/api/subscribers` cria um novo assinante ou atualiza um existente, respondendo `201` ou `200`. Ele não é destrutivo, então grupos e campos que você omite continuam como estavam. O porém é o `status`. Com a opção de conta **Double opt-in for API and integrations** ligada, o MailerLite envia uma confirmação por e-mail aos novos assinantes via API. Um assinante existente, ativo ou descadastrado, só recebe uma quando a chamada envia `status: "unconfirmed"`.

A ajuda do MailerLite diz que assinantes existentes, ativos ou descadastrados, não recebem o e-mail de confirmação a menos que a chamada inclua `"status": "unconfirmed"`. Então um relay que sempre envia `unconfirmed` transforma cada nova inscrição de um leitor fiel num novo pedido de confirmação. A solução é procurar o endereço antes de decidir o que enviar:

Diagrama: Como o relay decide o que enviar ao MailerLite

1. O relay verifica o webhook do Ikiform.
2. Ele pede ao MailerLite o assinante pelo e-mail.
3. Não encontrado: ele o cria com status unconfirmed e o grupo da posição, e o MailerLite envia o e-mail de confirmação.
4. Encontrado e ativo ou não confirmado: ele adiciona o grupo sem status, então nada muda na confirmação.
5. Encontrado e descadastrado: ele não faz nada, para que uma inscrição nunca desfaça um descadastro sem ninguém perceber.

Duas chamadas de API por inscrição, e a segunda depende do que a primeira encontrou.

## Configure o MailerLite

1. No MailerLite, abra as configurações de inscrição e ligue **Double opt-in for API and integrations**. Edite ali o e-mail de confirmação; o MailerLite envia o mesmo para todo assinante adicionado pela API.
2. Crie um grupo por posição, como "Website footer" e "Blog posts", e anote o id de cada grupo.
3. Em **Integrations**, crie um token de API e guarde-o para o ambiente do relay.

> O FAQ de preços do MailerLite diz que o acesso à API é limitado no plano mais baixo. Teste se o token consegue criar assinantes no seu plano antes de confiar nele.

## O relay

Este é um servidor Express. Ele lê o corpo bruto como texto, porque a assinatura cobre exatamente os bytes que o Ikiform enviou, e interpretar o JSON antes os alteraria.

`server.ts`:

```ts
import express from "express";
import { verifyWebhook, WebhookVerificationError } from "@ikiform/sdk/webhooks";

const API = "https://connect.mailerlite.com/api";
const GROUPS: Record<string, string> = {
  footer: process.env.MAILERLITE_GROUP_FOOTER!,
  post: process.env.MAILERLITE_GROUP_POST!,
};

function mailerlite(path: string, init: RequestInit = {}) {
  return fetch(`${API}${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${process.env.MAILERLITE_API_KEY}`,
      "Content-Type": "application/json",
      Accept: "application/json",
    },
  });
}

async function subscribe(email: string, name: string | undefined, source: string) {
  const found = await mailerlite(`/subscribers/${encodeURIComponent(email)}`);
  if (found.status !== 200 && found.status !== 404) return found;

  const groups = [GROUPS[source] ?? process.env.MAILERLITE_GROUP_FOOTER!];
  const fields = name ? { name } : {};

  if (found.status === 404) {
    return mailerlite("/subscribers", {
      method: "POST",
      body: JSON.stringify({ email, fields, groups, status: "unconfirmed" }),
    });
  }

  const existing = await found.json();
  if (existing.data.status === "unsubscribed") return new Response(null, { status: 208 });
  return mailerlite("/subscribers", { method: "POST", body: JSON.stringify({ email, fields, groups }) });
}

const app = express();

app.post("/hooks/mailerlite", express.text({ type: "application/json", limit: "512kb" }), async (req, res) => {
  let event;
  try {
    event = await verifyWebhook({ payload: req.body, headers: req.headers, secret: process.env.IKIFORM_WEBHOOK_SECRET! });
  } catch (error) {
    if (error instanceof WebhookVerificationError) return res.status(400).send(error.reason);
    return res.status(500).end();
  }
  if (event.type !== "submission.created") return res.status(204).end();

  const { email, first_name, consent, source } = event.data.fields;
  if (consent !== true || typeof email !== "string") return res.status(200).send("Skipped");

  const answer = await subscribe(
    email,
    typeof first_name === "string" ? first_name : undefined,
    typeof source === "string" ? source : "footer",
  );
  if (answer.status === 208) return res.status(200).send("Unsubscribed earlier, left alone");
  if (answer.status === 429) {
    return res.status(503).set("retry-after", answer.headers.get("retry-after") ?? "60").send("MailerLite rate limit");
  }
  if (!answer.ok) return res.status(502).send(`MailerLite answered ${answer.status}: ${await answer.text()}`);
  res.status(204).end();
});

app.listen(Number(process.env.PORT ?? 3000));
```

- O MailerLite recebe o token como `Authorization: Bearer`. A URL base é `https://connect.mailerlite.com/api`.
- `GET /api/subscribers/{email}` aceita um e-mail ou um id e responde `404` quando o assinante não existe.
- `groups` recebe ids de grupos que já existem. Um id errado é recusado com `422`, que o relay repassa como `502` com a mensagem do MailerLite.
- `fields.name` é o campo padrão de primeiro nome do MailerLite. Campos personalizados precisam existir no MailerLite antes de você enviá-los.
- O `208` é um marcador interno para um leitor descadastrado. O Ikiform vê `200` e uma nota no log de entregas.

Faça o deploy em qualquer lugar que ofereça uma URL HTTPS pública na porta 443, adicione essa URL em **Webhooks** no Ikiform e coloque o segredo `whsec_` em `IKIFORM_WEBHOOK_SECRET`. A [documentação de webhooks](https://ikiform.com/pt-br/docs/webhooks.md) cobre as novas tentativas e o payload, e [seu próprio servidor](https://ikiform.com/blog/form-submissions-to-your-own-server.md) tem a mesma configuração Express com um banco de dados.

## Onde fica o registro de consentimento

A chamada de create do MailerLite aceita `subscribed_at`, `ip_address`, `opted_in_at` e `optin_ip`. Deixe os campos de IP de fora. O webhook do Ikiform nunca inclui o endereço IP do visitante nem o hash dele, então o relay não tem nada verdadeiro para enviar, e um valor inventado é pior que nenhum.

O registro da inscrição fica no Ikiform: o envio guarda `consent: true` com data e hora, origem, referrer e país. O registro da confirmação fica no MailerLite, que anota quando o leitor clicou no link. Com os dois, você consegue mostrar quando alguém marcou a caixa e quando provou que o endereço era seu. Exporte o lado do Ikiform como CSV em **Submissions** quando precisar.

## Limites de taxa

O limite global da API do MailerLite é de 120 requisições por minuto. O relay faz duas por inscrição, então cabem cerca de 60 inscrições por minuto. Acima disso, o MailerLite responde `429`, o relay responde `503` com `Retry-After` e o Ikiform tenta de novo mais tarde com a mesma entrega.

| O MailerLite responde | O relay responde | Ikiform |
| --- | --- | --- |
| `201` ou `200` | `204` | Entrega bem-sucedida |
| `429` | `503` com `Retry-After` | Espera e tenta de novo |
| `401` | `502` | Tenta de novo. Corrija o token e use **Retry now** nas entregas com falha |
| `422` | `502` com os erros | Tenta de novo. Geralmente um id de grupo ou nome de campo errado |

## Pegadinhas

- **Não envie `status: "active"`.** Ele marca a pessoa como inscrita, e a documentação do MailerLite não diz se uma confirmação ainda é enviada. Teste com o status que você envia.
- **Reinscrever é uma escolha.** O MailerLite tem uma flag `resubscribe` para quem se descadastrou. Só a envie quando o seu formulário disser isso, e quando o leitor souber que está voltando a se inscrever.
- **A chave importa.** O MailerLite só envia e-mail de confirmação para inscrições via API quando **Double opt-in for API and integrations** está ligado.
- **Um único e-mail de confirmação.** O e-mail de double opt-in da API é compartilhado por todas as inscrições via API. Se você precisa de textos diferentes por posição, use formulários separados do MailerLite.
- **Duplicados no Ikiform.** O Ikiform guarda todo envio aceito, enquanto o MailerLite guarda um assinante por e-mail. Conte os assinantes no MailerLite, não no painel do Ikiform.

## Confira se funciona

1. Envie um teste pelo endpoint no Ikiform. A entrega mostra `204`.
2. Inscreva-se com um endereço novo seu. O MailerLite mostra o assinante como não confirmado no grupo do rodapé, e o e-mail de confirmação chega.
3. Confirme e depois inscreva-se de novo a partir de um post do blog. O assinante continua ativo, entra no segundo grupo e não recebe um novo e-mail de confirmação.
4. Descadastre esse endereço no MailerLite e inscreva-se mais uma vez. O log de entregas mostra a nota de descadastrado, e o MailerLite continua mostrando o endereço como descadastrado.

## Perguntas

### Posso usar meu próprio formulário HTML com o MailerLite em vez do embed dele?

Sim. Envie o formulário ao Ikiform e deixe um relay adicionar cada inscrição pela API do MailerLite com o grupo certo. O formulário fica no seu markup e o MailerLite continua enviando a newsletter.

### Por que o MailerLite não envia e-mail de confirmação para inscrições via API?

Ou o Double opt-in for API and integrations está desligado nas configurações de inscrição do MailerLite, ou o relay criou o assinante como ativo. Mantenha a opção ligada, envie status unconfirmed e teste com um endereço seu.

### Um assinante que se inscreve duas vezes recebe dois e-mails de confirmação?

Não com este relay. Ele procura o endereço primeiro e só envia unconfirmed para um assinante novo. Um assinante existente é adicionado ao novo grupo e nada mais muda.

### Como coloco as inscrições do rodapé e do blog em grupos diferentes do MailerLite?

Dê a cada posição um valor diferente no input oculto source do formulário e mapeie cada valor para um id de grupo do MailerLite no relay. Um assinante existente que se inscreve a partir de uma segunda posição entra nesse grupo também, e continua no primeiro.

### O Ikiform envia alguma coisa ao assinante?

Não. O Ikiform nunca envia e-mail para quem envia um formulário. O MailerLite envia a confirmação, cada newsletter e o link de descadastro.

## Mais guias

- [Formulário de inscrição em newsletter](https://ikiform.com/pt-br/guides/newsletter-signup.md): Crie um formulário de newsletter no seu próprio markup, registre o consentimento, barre inscrições de bots e passe cada assinante para Kit, MailerLite, beehiiv ou qualquer ferramenta.
- [Double opt-in](https://ikiform.com/pt-br/guides/newsletter-signup/double-opt-in.md): O Ikiform não envia e-mails de confirmação, então o double opt-in roda na sua ferramenta de e-mail: um relay adiciona cada inscrição como não confirmada e a ferramenta envia o link.
- [Kit (ConvertKit)](https://ikiform.com/pt-br/guides/newsletter-signup/kit.md): Conecte seu próprio formulário de newsletter ao Kit com um relay que cria o assinante, o adiciona a um formulário do Kit para o incentive email e marca a posição com uma tag.
- [beehiiv](https://ikiform.com/pt-br/guides/newsletter-signup/beehiiv.md): Conecte seu próprio formulário de inscrição ao beehiiv: um relay cria cada subscription com double opt-in ligado, a posição como UTM source e a página como referrer.
- [Site estático](https://ikiform.com/pt-br/guides/newsletter-signup/static-site.md): Adicione um formulário de newsletter a um site estático em Hugo, Jekyll, Eleventy ou Astro, mantenha a chave de API da ferramenta de e-mail fora da página e confirme na ferramenta.
- [Formulário de newsletter no Next.js](https://ikiform.com/pt-br/guides/newsletter-signup/nextjs.md): Um formulário de newsletter no rodapé do Next.js: uma server action com checagem de consentimento e Turnstile, enviando ao Ikiform, e um route handler que adiciona leitores ao Kit.
