Ir al contenido
migrabox

API para partners · v1

Migraciones de correo para empresas de hosting

Cuando un cliente contrata hosting contigo, su correo también tiene que cambiar de sitio. Con la API de Migrabox lanzas la copia desde tu panel de control, o envías al cliente un enlace a una página con tu logo donde él mismo escribe las contraseñas. Copiamos todos los mensajes, carpetas y adjuntos por IMAP; el buzón antiguo nunca se modifica.

Esta página también está disponible en Italiano · English · Português (Brasil) · Français · Deutsch

Cómo encaja en tu negocio

  • Misma dirección, servidor nuevo. El caso más habitual: info@customer.com no cambia, solo cambia el hosting. Copiamos ahora todo el historial y, tras el cambio de MX, los últimos correos, leyendo todavía del servidor antiguo.
  • Nunca tocas contraseñas si usas enlaces de migración: el cliente las escribe en migrabox.com, se guardan cifradas y se borran 14 días después de la última copia.
  • Un buzón, un crédito. Sea cual sea su tamaño. Si la primera copia no puede empezar porque una contraseña es incorrecta o un servidor no responde, el crédito vuelve a tu saldo.
  • Las claves de test son gratuitas y simulan todos los estados y webhooks: puedes construir toda la integración antes de comprar nada.

Precios

Crédito prepago, válido 12 meses desde el pago. Las mismas cifras en euros y en dólares estadounidenses: eliges la moneda al pagar. Los packs se suman; el crédito se descuenta primero del pack que caduca antes.

PackPrecioPor buzón
20 buzones20,00 € · 20,00 US$1,00 €
100 buzones80,00 € · 80,00 US$0,80 €
500 buzones300,00 € · 300,00 US$0,60 €
2000 buzones1000,00 € · 1000,00 US$0,50 €

Velocidad estándar: hasta 20 Mbps por buzón. Está prevista una opción más rápida a través de la API (el campo speed ya está reservado).

Empieza en 5 minutos

  1. Crea una cuenta de partnerEl nombre de la empresa y el país aparecen en tus recibos. Accedes con un enlace que te enviamos por correo: no hay contraseña que gestionar.
  2. Crea una clave de testÁrea de partners → Claves API → modo Test. Empieza por mbx_test_ y solo se muestra una vez.
  3. Llama a la APICrea una migración con el ejemplo de abajo. En modo test no se copia nada: la migración pasa por queued, running y completed en unos diez segundos.
  4. Añade un webhookÁrea de partners → Webhooks. Pulsa Enviar evento de prueba y comprueba que tu endpoint verifica la firma.
  5. Pasa a producciónCompra un pack de crédito, crea una clave mbx_live_ y sustituye la de test. Mismas rutas, mismos 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"

Autenticación

Cada petición lleva tu clave en la cabecera Authorization: Authorization: Bearer mbx_live_…. Las peticiones sin una clave válida reciben 401 UNAUTHORIZED.

Las claves se muestran una sola vez y solo guardamos su huella SHA-256. Rotar crea una clave nueva y mantiene la antigua activa durante 24 horas; Revocar la desactiva al instante.

Una clave solo ve las migraciones de su propia empresa y de su propio modo: una clave live nunca ve migraciones de test, y al revés. Cualquier otra cosa responde 404 NOT_FOUND.

Usa la API solo desde tus servidores. Nunca pongas una clave en una página web ni en una app móvil.

Modo test

Las claves mbx_test_ usan las mismas rutas que las claves live. Nunca se conectan a un servidor de correo, nunca guardan contraseñas y nunca consumen crédito. Las comprobaciones y las migraciones se simulan con una secuencia fija: 2 segundos en cola, 8 segundos copiando y luego el estado final, con todos los webhooks que enviaría una migración real (solo a endpoints de test).

El resultado lo eliges con la contraseña de origen:

test-auth-failed
La creación falla con 422 SOURCE_AUTH_FAILED (como contraseña de destino: DEST_AUTH_FAILED).
test-connect-failed
La creación falla con 422 SOURCE_CONNECT_FAILED. Un host que termine en .invalid hace lo mismo.
test-run-fails
La migración empieza y luego falla con failure_code: AUTH_SOURCE y envía migration.failed.
test-run-errors
La migración termina como completed_with_errors (algunos mensajes no se copian).

Cualquier otra contraseña: la migración se completa.

Hay dos formas de iniciar una migración. Las dos terminan en el mismo objeto de migración, con los mismos webhooks y la misma página de estado.

Enlace de migración (recomendado)

  • POST /migration-links devuelve una URL como https://migrabox.com/en/email-move/#… que envías a tu cliente.
  • La página muestra Migrabox en colaboración con tu nombre y tu logo (súbelo en el área de partners).
  • El cliente escribe las dos contraseñas; puedes fijar el servidor de destino (tu nuevo hosting) para que solo tenga que introducir la contraseña nueva.
  • El crédito se descuenta cuando el cliente envía el formulario. Recibes link.opened, link.submitted y después los eventos de la migración.
  • De un solo uso, válido de 1 a 30 días (14 por defecto); puedes revocarlo antes de que se use.

De servidor a servidor

  • POST /migrations con los dos buzones y sus contraseñas, cuando ya las tienes (por ejemplo, un buzón que estás creando en ese momento en tus servidores).
  • Comprobamos los dos accesos y medimos el origen antes de descontar el crédito: una contraseña incorrecta responde 422 y no cuesta nada.
  • Las contraseñas solo viajan por HTTPS, se guardan cifradas (AES-256-GCM), nunca aparecen en logs, respuestas ni webhooks, y se borran 14 días después de la última copia.
  • Hasta 500 buzones a la vez con 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", … }

Misma dirección, hosting nuevo

Indica same_address: true cuando el cliente conserva info@customer.com y lo traslada a tus servidores. Origen y destino comparten la dirección de correo; el host de destino es tu nuevo servidor.

Al crear la migración guardamos las direcciones del servidor antiguo que respondió. Todas las ejecuciones posteriores se conectan a ellas (con TLS verificado sobre el nombre antiguo), así que, después de apuntar los registros MX a tus servidores, POST /migrations/{id}/delta sigue leyendo el buzón antiguo y recoge lo que haya llegado allí mientras tanto.

Flujo recomendado: crea la migración (o el enlace) en cuanto el hosting esté activo → se hace la copia → cambia los MX → llama a delta → listo. Delta es gratuito durante 14 días desde la última ejecución; los mensajes ya copiados se omiten, así que no se duplica nada.

Webhooks

Añade endpoints en el área de partners (solo https, nombre DNS público, hasta 5 por modo). Enviamos por POST un evento JSON a cada endpoint suscrito a su tipo. Los payloads nunca contienen contraseñas ni tokens privados.

Responde 2xx en 10 segundos como máximo. Cualquier otra respuesta se reintenta con esperas crecientes (30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, 6 h, 8 h: unas 22 horas en total). El área de partners muestra cada entrega y te permite reintentarla.

Los eventos pueden llegar más de una vez y desordenados: usa id para procesar cada evento una sola vez y toma el status del objeto como referencia.

Eventos

migration.created
Se ha creado una migración (API, fila de un lote o enlace de migración).
migration.started
Una ejecución ha empezado a copiar (primera copia o delta).
migration.completed
Una ejecución ha terminado: status es completed o completed_with_errors.
migration.failed
Una ejecución ha fallado: consulta failure_code y credit_refunded.
migration.cancelled
Una ejecución se ha detenido con /cancel.
link.opened
Tu cliente ha abierto un enlace de migración por primera vez.
link.submitted
Tu cliente ha enviado el enlace de migración: el objeto incluye la nueva migración.
credits.low
El crédito live ha llegado a tu umbral (área de partners → Ajustes).
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, …
  } }
}

Verificar la firma

Cada entrega lleva la cabecera Migrabox-Signature: t=<unix seconds>,v1=<hex>. v1 es el HMAC-SHA256 de t + "." + raw body, con el secreto de firma del endpoint como clave (whsec_…, que se muestra una sola vez al crear el endpoint).

Calcúlalo sobre el cuerpo sin procesar (antes de parsear el JSON), compara en tiempo constante y rechaza timestamps de más de 5 minutos para bloquear repeticiones. Durante una rotación del secreto, la cabecera puede llevar más de un v1: acepta el evento si coincide cualquiera de ellos.

<?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

Errores

Los errores son JSON con un code estable (úsalo en tu código) y un message en inglés (para tus logs). El estado HTTP indica el tipo: 4xx, problema en tu petición; 5xx, problema nuestro (reintenta con la misma Idempotency-Key).

HTTP/1.1 422 Unprocessable Entity
{ "error": { "code": "SOURCE_AUTH_FAILED", "message": "Cannot sign in to the source mailbox" } }
CódigoHTTPSignificado
INVALID_INPUT400Falta un campo o no es válido; el mensaje indica cuál (nunca su valor).
UNAUTHORIZED401Clave ausente, mal formada, revocada o caducada.
INSUFFICIENT_CREDITS402No queda crédito live (en un lote: no basta para todas las filas).
NOT_FOUND404No existe ese objeto para esta clave y este modo.
RUN_ACTIVE409Ya hay una ejecución en cola o copiando.
CREDENTIALS_PURGED409Han pasado más de 14 días desde la última ejecución: las contraseñas se han borrado, crea una migración nueva.
IDEMPOTENCY_MISMATCH422Esta Idempotency-Key ya se usó con una petición distinta.
SOURCE_AUTH_FAILED422El servidor de origen ha rechazado el acceso. DEST_… para el destino.
SOURCE_CONNECT_FAILED422El servidor de origen no ha respondido (también TLS_FAILED, TIMEOUT, HOST_NOT_ALLOWED).
SAME_SERVER422Origen y destino son el mismo buzón en el mismo servidor: se rechaza y no se copia nada.
RATE_LIMITED429Demasiadas peticiones con esta clave: espera y vuelve a intentarlo.

Límites y convenciones

  • Límites por cuenta y modo (todas tus claves juntas), por endpoint y minuto: 120 peticiones, 60 creaciones, 30 comprobaciones, 10 lotes. Por encima del límite: 429 RATE_LIMITED. /probe y /discover en modo live están disponibles tras tu primera compra de crédito (antes: 402 CREDIT_REQUIRED).
  • Idempotency-Key en cada POST: envía un valor único (tu id de pedido o de buzón). La primera respuesta se guarda 24 horas y se repite para la misma clave; la cabecera Idempotent-Replayed: true te lo indica.
  • Paginación: GET /migrations?limit=20 devuelve has_more y next_cursor; pasa cursor= para la página siguiente. Primero las más recientes.
  • Los nombres de servidor deben ser nombres DNS: se rechazan direcciones IP y redes privadas. Los certificados TLS se verifican siempre.
  • Las fechas van en ISO 8601 y UTC; el campo created de los webhooks va en segundos Unix. Podemos añadir campos nuevos a nuestras respuestas en cualquier momento: ignora los que no conozcas.

Ejemplos

Ejemplos completos y sin dependencias. Sustituye la clave por la tuya.

# 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"

Referencia de la API

URL base https://migrabox.com/api/v1. Los esquemas completos están en el documento OpenAPI.

Account

  • GET/v1/account

    Saldo de crédito y packs, con su caducidad.

Mailboxes

  • POST/v1/discover

    Configuración IMAP de una dirección (el mismo motor que la web).

    Errores: INVALID_INPUT, CREDIT_REQUIRED

  • POST/v1/probe

    Comprueba un acceso por TLS y, con measure, cuenta mensajes y bytes.

    Errores: INVALID_INPUT, CREDIT_REQUIRED, RATE_LIMITED

Migrations

  • POST/v1/migrations

    Crea e inicia una migración con las dos contraseñas.

    Errores: 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

    Hasta 500 migraciones, procesadas en segundo plano.

    Errores: INVALID_INPUT, INSUFFICIENT_CREDITS

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

    Resultado de un lote, fila por fila.

    Errores: NOT_FOUND

  • GET/v1/migrations

    Lista con filtros (estado, external_id, fechas) y cursor.

    Errores: INVALID_INPUT, INVALID_CURSOR

  • GET/v1/migrations/{id}

    Estado y progreso.

    Errores: NOT_FOUND

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

    Copia lo que ha llegado desde la última ejecución (tras el cambio de MX).

    Errores: NOT_FOUND, RUN_ACTIVE, CREDENTIALS_PURGED, CREDIT_REFUNDED, NOT_READY

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

    Detiene la copia en cola o en curso.

    Errores: NOT_FOUND, NOT_RUNNING

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

    Todas las ejecuciones con contadores y la cronología.

    Errores: NOT_FOUND

Hosted links

Historial de cambios

  • v1: migraciones, lotes, enlaces de migración con tu logo, delta, cancelación, informe, discover, probe, webhooks firmados y modo test.