Pular para o conteúdo
migrabox

API para parceiros · v1

Migração de e-mail para empresas de hospedagem

Quando um cliente contrata hospedagem com você, os e-mails dele também precisam mudar de lugar. Com a API do Migrabox, você inicia a cópia pelo seu painel de controle ou envia ao cliente um link para uma página com o seu logo, onde ele mesmo digita as senhas. Copiamos todas as mensagens, pastas e anexos via IMAP; a caixa antiga nunca é alterada.

Esta página também está disponível em Italiano · English · Español · Français · Deutsch

Como se encaixa no seu negócio

  • Mesmo endereço, servidor novo. O caso mais comum: info@customer.com continua igual, só a hospedagem muda. Copiamos agora todo o histórico e, depois da troca do MX, os últimos e-mails, ainda lendo do servidor antigo.
  • Você nunca mexe em senhas se usar links de migração: o cliente digita as senhas no migrabox.com, elas são criptografadas e apagadas 14 dias depois da última cópia.
  • Uma caixa, um crédito. De qualquer tamanho. Se a primeira cópia não conseguir começar porque uma senha está errada ou um servidor não responde, o crédito volta para o seu saldo.
  • As chaves de teste são gratuitas e simulam todos os status e webhooks: você pode construir a integração inteira antes de comprar qualquer coisa.

Preços

Crédito pré-pago, válido por 12 meses a partir do pagamento. Os mesmos valores em euros e em dólares americanos: você escolhe a moeda no checkout. Pacotes diferentes se somam; o crédito é descontado primeiro do pacote que vence antes.

PacotePreçoPor caixa
20 caixas€ 20,00 · US$ 20,00US$ 1,00
100 caixas€ 80,00 · US$ 80,00US$ 0,80
500 caixas€ 300,00 · US$ 300,00US$ 0,60
2.000 caixas€ 1.000,00 · US$ 1.000,00US$ 0,50

Velocidade padrão: até 20 Mbps por caixa. Uma opção mais rápida pela API está prevista (o campo speed já está reservado).

Comece em 5 minutos

  1. Crie uma conta de parceiroNome da empresa e país aparecem nos seus recibos. Você entra com um link enviado por e-mail: nenhuma senha para gerenciar.
  2. Crie uma chave de testeÁrea do parceiro → Chaves de API → modo Teste. Ela começa com mbx_test_ e só é exibida uma vez.
  3. Chame a APICrie uma migração com o exemplo abaixo. No modo de teste nada é copiado: a migração passa por queued, running e completed em cerca de dez segundos.
  4. Adicione um webhookÁrea do parceiro → Webhooks. Clique em Enviar evento de teste e confira se o seu endpoint verifica a assinatura.
  5. Entre em produçãoCompre um pacote de crédito, crie uma chave mbx_live_ e troque pela de teste. Mesmas rotas, mesmos payloads.
# 1. Your test key (partner area → API keys). Test mode never copies anything.
export MIGRABOX_KEY=mbx_test_...

# 2. Check the key and your credit
curl https://migrabox.com/api/v1/account -H "Authorization: Bearer $MIGRABOX_KEY"

# 3. Create a migration (server to server)
curl https://migrabox.com/api/v1/migrations \
  -H "Authorization: Bearer $MIGRABOX_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001-mailbox-1" \
  -d '{
    "source":      { "email": "info@customer.com", "host": "imap.oldhost.com", "password": "old-secret" },
    "destination": { "email": "info@customer.com", "host": "imap.yourhosting.com", "password": "new-secret" },
    "same_address": true,
    "external_id": "order-1001"
  }'

# 4. Follow it (or wait for the migration.completed webhook)
curl https://migrabox.com/api/v1/migrations/MIGRATION_ID -H "Authorization: Bearer $MIGRABOX_KEY"

Autenticação

Toda requisição leva a sua chave no header Authorization: Authorization: Bearer mbx_live_…. Requisições sem uma chave válida recebem 401 UNAUTHORIZED.

As chaves são exibidas uma única vez e guardamos apenas a impressão digital SHA-256 delas. Trocar cria uma chave nova e mantém a antiga funcionando por 24 horas; Revogar desativa a chave na hora.

Uma chave só vê as migrações da própria empresa, no próprio modo: uma chave live nunca vê migrações de teste, e vice-versa. Qualquer outra coisa responde 404 NOT_FOUND.

Use a API apenas a partir dos seus servidores. Nunca coloque uma chave numa página web ou num app móvel.

Modo de teste

As chaves mbx_test_ usam as mesmas rotas das chaves live. Elas nunca se conectam a um servidor de e-mail, nunca guardam senhas e nunca usam crédito. Verificações e migrações são simuladas com uma sequência fixa: 2 segundos na fila, 8 segundos copiando e depois o status final, com todos os webhooks que uma migração real enviaria (somente para endpoints de teste).

Você escolhe o resultado pela senha de origem:

test-auth-failed
A criação falha com 422 SOURCE_AUTH_FAILED (como senha de destino: DEST_AUTH_FAILED).
test-connect-failed
A criação falha com 422 SOURCE_CONNECT_FAILED. Um host terminado em .invalid tem o mesmo efeito.
test-run-fails
A migração começa, depois falha com failure_code: AUTH_SOURCE e envia migration.failed.
test-run-errors
A migração termina como completed_with_errors (algumas mensagens não são copiadas).

Qualquer outra senha: a migração é concluída.

Há duas formas de iniciar uma migração. As duas geram o mesmo objeto de migração, com os mesmos webhooks e a mesma página de status.

Link de migração (recomendado)

  • POST /migration-links retorna uma URL como https://migrabox.com/en/email-move/#…, que você envia ao seu cliente.
  • A página mostra o Migrabox em parceria com o seu nome e o seu logo (envie o logo na área do parceiro).
  • O cliente digita as duas senhas; você pode fixar o servidor de destino (a sua nova hospedagem) para que ele só informe a senha nova.
  • O crédito é descontado quando o cliente envia o formulário. Você recebe link.opened, link.submitted e depois os eventos da migração.
  • Uso único, válido de 1 a 30 dias (14 por padrão), pode ser revogado antes de ser usado.

Servidor a servidor

  • POST /migrations com as duas caixas e as senhas, quando você já as tem (por exemplo, uma caixa que você está criando agora nos seus servidores).
  • Verificamos os dois logins e medimos a origem antes de descontar o crédito: uma senha errada responde 422 e não custa nada.
  • As senhas trafegam somente por HTTPS, ficam criptografadas em repouso (AES-256-GCM), nunca aparecem em logs, respostas ou webhooks e são apagadas 14 dias depois da última cópia.
  • Até 500 caixas de uma vez com POST /migrations/batch.
curl https://migrabox.com/api/v1/migration-links \
  -H "Authorization: Bearer $MIGRABOX_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: welcome-7731" \
  -d '{
    "locale": "en",
    "external_id": "service-7731",
    "same_address": true,
    "source_email": "info@customer.com",
    "destination": { "host": "imap.yourhosting.com", "port": 993, "security": "ssl" }
  }'
# → { "id": "…", "url": "https://migrabox.com/en/email-move/#…", "status": "open", … }

Mesmo endereço, hospedagem nova

Use same_address: true quando o cliente mantém info@customer.com e o leva para os seus servidores. Origem e destino têm o mesmo endereço de e-mail; o host de destino é o seu novo servidor.

Na criação, guardamos os endereços do servidor antigo que respondeu. Todas as execuções seguintes se conectam a eles (com TLS verificado no nome antigo). Assim, depois que você apontar os registros MX para os seus servidores, POST /migrations/{id}/delta continua lendo a caixa antiga e busca o que chegou lá nesse meio-tempo.

Fluxo recomendado: crie a migração (ou o link) assim que a hospedagem estiver ativa → a cópia roda → troque o MX → chame delta → pronto. O delta é gratuito por 14 dias depois da última execução; mensagens já copiadas são ignoradas, então nada é duplicado.

Webhooks

Adicione endpoints na área do parceiro (somente https, nome DNS público, até 5 por modo). Enviamos via POST um evento JSON para cada endpoint inscrito naquele tipo. Os payloads nunca contêm senhas nem tokens privados.

Responda 2xx em até 10 segundos. Qualquer outra resposta é tentada de novo com intervalos crescentes (30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, 6 h, 8 h: cerca de 22 horas no total). A área do parceiro mostra cada entrega e permite reenviá-la.

Os eventos podem chegar mais de uma vez e fora de ordem: use o id para processar cada evento uma única vez e considere o status do objeto como a referência.

Eventos

migration.created
Uma migração foi criada (API, linha de lote ou link de migração).
migration.started
Uma execução começou a copiar (primeira cópia ou delta).
migration.completed
Uma execução terminou: status é completed ou completed_with_errors.
migration.failed
Uma execução falhou: veja failure_code e credit_refunded.
migration.cancelled
Uma execução foi interrompida com /cancel.
link.opened
Seu cliente abriu um link de migração pela primeira vez.
link.submitted
Seu cliente enviou o link de migração: o objeto inclui a nova migração.
credits.low
O crédito live chegou ao seu limite de alerta (área do parceiro → Configurações).
POST /your/webhook HTTP/1.1
Content-Type: application/json
Migrabox-Signature: t=1794470900,v1=5f2b…c9
Migrabox-Event-Id: evt_7Qm1…

{
  "id": "evt_7Qm1…",
  "object": "event",
  "api_version": "2026-11-12",
  "type": "migration.completed",
  "created": 1794470900,
  "livemode": true,
  "data": { "object": {
    "id": "92430b5b-…", "object": "migration", "status": "completed", "external_id": "order-1001",
    "source": { "email": "info@customer.com", "host": "imap.oldhost.com" },
    "destination": { "email": "info@customer.com", "host": "imap.yourhosting.com" },
    "progress": { "run": "full", "messages_total": 18234, "messages_done": 18234, "percent": 100, … },
    "credit_refunded": false, "can_delta": true, …
  } }
}

Verifique a assinatura

Cada entrega traz o header Migrabox-Signature: t=<unix seconds>,v1=<hex>. v1 é o HMAC-SHA256 de t + "." + raw body, usando como chave o segredo de assinatura do endpoint (whsec_…, exibido uma única vez quando você cria o endpoint).

Calcule sobre o corpo bruto (antes de fazer o parse do JSON), compare em tempo constante e recuse timestamps com mais de 5 minutos para bloquear replays. Durante a troca do segredo, o header pode trazer mais de um v1: aceite o evento se qualquer um deles bater.

<?php
// Verify Migrabox-Signature on the RAW body, before json_decode.
$secret = getenv('MIGRABOX_WEBHOOK_SECRET'); // whsec_...
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_MIGRABOX_SIGNATURE'] ?? '';
$parts = [];
foreach (explode(',', $header) as $p) { [$k, $v] = array_pad(explode('=', $p, 2), 2, ''); $parts[$k][] = $v; }
$t = (int) ($parts['t'][0] ?? 0);
$expected = hash_hmac('sha256', $t . '.' . $body, $secret);
$valid = abs(time() - $t) <= 300 && array_filter($parts['v1'] ?? [], fn($s) => hash_equals($expected, $s));
if (!$valid) { http_response_code(400); exit; }

$event = json_decode($body, true);
// Deliveries can repeat: use $event['id'] to process each event once.
if ($event['type'] === 'migration.completed') {
    $migration = $event['data']['object']; // ['id'], ['external_id'], ['status'], ['progress'] ...
}
http_response_code(200); // answer within 10 seconds, do slow work afterwards

Erros

Os erros são JSON com um code estável (use-o no seu código) e uma message em inglês (para os seus logs). O status HTTP indica a categoria: 4xx, problema na sua requisição; 5xx, problema nosso (tente de novo com a mesma Idempotency-Key).

HTTP/1.1 422 Unprocessable Entity
{ "error": { "code": "SOURCE_AUTH_FAILED", "message": "Cannot sign in to the source mailbox" } }
CódigoHTTPSignificado
INVALID_INPUT400Um campo está faltando ou é inválido; a mensagem diz qual (nunca o valor).
UNAUTHORIZED401Chave ausente, malformada, revogada ou expirada.
INSUFFICIENT_CREDITS402Não há mais crédito live (num lote: não há o suficiente para todas as linhas).
NOT_FOUND404Esse objeto não existe para esta chave e este modo.
RUN_ACTIVE409Já existe uma execução na fila ou copiando.
CREDENTIALS_PURGED409Passaram-se mais de 14 dias desde a última execução: as senhas foram apagadas, crie uma nova migração.
IDEMPOTENCY_MISMATCH422Esta Idempotency-Key já foi usada com uma requisição diferente.
SOURCE_AUTH_FAILED422O servidor de origem recusou o login. DEST_… para o destino.
SOURCE_CONNECT_FAILED422O servidor de origem não respondeu (também TLS_FAILED, TIMEOUT, HOST_NOT_ALLOWED).
SAME_SERVER422Origem e destino são a mesma caixa no mesmo servidor: recusado, nada é copiado.
RATE_LIMITED429Requisições demais para esta chave: aguarde e tente de novo.

Limites e convenções

  • Limites por conta e modo (todas as suas chaves juntas), por endpoint e por minuto: 120 requisições, 60 criações, 30 verificações, 10 lotes. Acima do limite: 429 RATE_LIMITED. /probe e /discover em modo live ficam disponíveis após a primeira compra de crédito (antes: 402 CREDIT_REQUIRED).
  • Idempotency-Key em todo POST: envie um valor único (o id do seu pedido ou da caixa). A primeira resposta fica guardada por 24 horas e é repetida para a mesma chave; o header Idempotent-Replayed: true avisa quando isso acontece.
  • Paginação: GET /migrations?limit=20 retorna has_more e next_cursor; passe cursor= para a próxima página. Mais recentes primeiro.
  • Os nomes de servidor precisam ser nomes DNS: endereços IP e redes privadas são recusados. Os certificados TLS são sempre verificados.
  • As datas são ISO 8601 em UTC; o created dos webhooks é em segundos Unix. Podemos adicionar campos novos às nossas respostas a qualquer momento: ignore os que você não conhece.

Exemplos

Exemplos completos e sem dependências. Substitua a chave pela sua.

# 1. Your test key (partner area → API keys). Test mode never copies anything.
export MIGRABOX_KEY=mbx_test_...

# 2. Check the key and your credit
curl https://migrabox.com/api/v1/account -H "Authorization: Bearer $MIGRABOX_KEY"

# 3. Create a migration (server to server)
curl https://migrabox.com/api/v1/migrations \
  -H "Authorization: Bearer $MIGRABOX_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1001-mailbox-1" \
  -d '{
    "source":      { "email": "info@customer.com", "host": "imap.oldhost.com", "password": "old-secret" },
    "destination": { "email": "info@customer.com", "host": "imap.yourhosting.com", "password": "new-secret" },
    "same_address": true,
    "external_id": "order-1001"
  }'

# 4. Follow it (or wait for the migration.completed webhook)
curl https://migrabox.com/api/v1/migrations/MIGRATION_ID -H "Authorization: Bearer $MIGRABOX_KEY"

Referência da API

URL base https://migrabox.com/api/v1. Os schemas completos estão no documento OpenAPI.

Account

  • GET/v1/account

    Saldo de crédito e pacotes, com o vencimento de cada um.

Mailboxes

  • POST/v1/discover

    Configurações IMAP de um endereço (o mesmo mecanismo do site).

    Erros: INVALID_INPUT, CREDIT_REQUIRED

  • POST/v1/probe

    Verifica um login via TLS e, com measure, conta mensagens e bytes.

    Erros: INVALID_INPUT, CREDIT_REQUIRED, RATE_LIMITED

Migrations

  • POST/v1/migrations

    Cria e inicia uma migração com as duas senhas.

    Erros: INVALID_INPUT, INSUFFICIENT_CREDITS, SOURCE_AUTH_FAILED, DEST_AUTH_FAILED, SOURCE_CONNECT_FAILED, DEST_CONNECT_FAILED, SOURCE_TLS_FAILED, SOURCE_HOST_NOT_ALLOWED, SAME_MAILBOX, SAME_SERVER, SAME_ADDRESS_MISMATCH, IDEMPOTENCY_MISMATCH

  • POST/v1/migrations/batch

    Até 500 migrações, processadas em segundo plano.

    Erros: INVALID_INPUT, INSUFFICIENT_CREDITS

  • GET/v1/migrations/batch/{id}

    Resultado de um lote, linha por linha.

    Erros: NOT_FOUND

  • GET/v1/migrations

    Lista com filtros (status, external_id, datas) e cursor.

    Erros: INVALID_INPUT, INVALID_CURSOR

  • GET/v1/migrations/{id}

    Status e progresso.

    Erros: NOT_FOUND

  • POST/v1/migrations/{id}/delta

    Copia o que chegou desde a última execução (depois da troca do MX).

    Erros: NOT_FOUND, RUN_ACTIVE, CREDENTIALS_PURGED, CREDIT_REFUNDED, NOT_READY

  • POST/v1/migrations/{id}/cancel

    Interrompe a cópia na fila ou em andamento.

    Erros: NOT_FOUND, NOT_RUNNING

  • GET/v1/migrations/{id}/report

    Todas as execuções, com contadores e a linha do tempo.

    Erros: NOT_FOUND

Hosted links

Histórico de alterações

  • v1: migrações, lotes, links de migração com o seu logo, delta, cancelamento, relatório, discover, probe, webhooks assinados, modo de teste.