Vai al contenuto
migrabox

API partner · v1

Migrazioni email per hosting provider

Quando un cliente compra un hosting da te, anche le sue email devono traslocare. Con l’API Migrabox avvii la copia dal tuo pannello, oppure mandi al cliente un link a una pagina con il tuo logo dove le password le inserisce lui. Copiamo via IMAP ogni messaggio, cartella e allegato; la vecchia casella non viene mai modificata.

Questa pagina è disponibile anche in English · Español · Português (Brasil) · Français · Deutsch

Come si inserisce nel tuo lavoro

  • Stesso indirizzo, nuovo server. È il caso più comune: info@cliente.it resta uguale, cambia solo l’hosting. Copiamo subito tutto lo storico e, dopo il cambio dei record MX, le ultime email, continuando a leggere il vecchio server.
  • Non tocchi mai le password se usi i link ospitati: il cliente le inserisce su migrabox.com, vengono cifrate e cancellate 14 giorni dopo l’ultima copia.
  • Una casella, un credito. Qualsiasi dimensione. Se la prima copia non parte perché una password è sbagliata o un server non risponde, il credito torna nel tuo saldo.
  • Le chiavi di test sono gratuite e simulano ogni stato e ogni webhook: costruisci tutta l’integrazione prima di comprare qualcosa.

Prezzi

Credito prepagato, valido 12 mesi dal pagamento. Stesse cifre in euro e in dollari USA: scegli la valuta al pagamento. Più pacchetti si sommano; il credito si consuma dal pacchetto che scade prima. Prezzi IVA inclusa.

PacchettoPrezzoA casella
20 caselle20,00 € · 20,00 USD1,00 €
100 caselle80,00 € · 80,00 USD0,80 €
500 caselle300,00 € · 300,00 USD0,60 €
2.000 caselle1000,00 € · 1000,00 USD0,50 €

Velocità standard: fino a 20 Mbps per casella. Una corsia più veloce via API è prevista (il campo speed è già riservato).

Partire in 5 minuti

  1. Crea un account partnerRagione sociale, paese e partita IVA vanno sulle ricevute. Accedi con un link che ti mandiamo via email: nessuna password da gestire.
  2. Crea una chiave di testArea partner → Chiavi API → modalità Test. Inizia con mbx_test_ e la vedi una sola volta.
  3. Chiama l’APICrea una migrazione con l’esempio qui sotto. In test non viene copiato niente: la migrazione passa per queued, running e completed in una decina di secondi.
  4. Aggiungi un webhookArea partner → Webhook. Premi Invia evento di prova e controlla che il tuo endpoint verifichi la firma.
  5. Vai in produzioneAcquista un pacchetto di credito, crea una chiave mbx_live_ e sostituiscila. Stesse rotte, stessi payload.
# 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"

Autenticazione

Ogni richiesta porta la chiave nell’header Authorization: Authorization: Bearer mbx_live_…. Senza una chiave valida la risposta è 401 UNAUTHORIZED.

Le chiavi si vedono una sola volta e noi ne conserviamo solo l’impronta SHA-256. Ruota crea una chiave nuova e lascia funzionare la vecchia per 24 ore; Revoca la blocca subito.

Una chiave vede solo le migrazioni della propria azienda e della propria modalità: una chiave live non vede mai le migrazioni di test e viceversa. Tutto il resto risponde 404 NOT_FOUND.

Usa l’API solo dai tuoi server. Non mettere mai una chiave in una pagina web o in un’app.

Modalità test

Le chiavi mbx_test_ usano le stesse rotte delle chiavi live. Non si collegano mai a un server di posta, non conservano password e non consumano credito. Verifiche e migrazioni sono simulate con una sequenza fissa: 2 secondi in coda, 8 secondi di copia, poi lo stato finale, con tutti i webhook che manderebbe una migrazione vera (solo agli endpoint di test).

Scegli l’esito con la password della casella di origine:

test-auth-failed
La creazione fallisce con 422 SOURCE_AUTH_FAILED (come password di destinazione: DEST_AUTH_FAILED).
test-connect-failed
La creazione fallisce con 422 SOURCE_CONNECT_FAILED. Lo stesso con un host che finisce in .invalid.
test-run-fails
La migrazione parte, poi fallisce con failure_code: AUTH_SOURCE e manda migration.failed.
test-run-errors
La migrazione termina come completed_with_errors (alcuni messaggi non copiati).

Qualsiasi altra password: la migrazione si completa.

Due modi per avviare una migrazione. Entrambi producono lo stesso oggetto migrazione, gli stessi webhook e la stessa pagina di stato.

Link ospitato (consigliato)

  • POST /migration-links restituisce un URL come https://migrabox.com/it/trasloco-email/#… da mandare al cliente.
  • La pagina mostra Migrabox in collaborazione con il tuo nome e il tuo logo (lo carichi nell’area partner).
  • Il cliente inserisce le due password; puoi fissare il server di destinazione (il tuo nuovo hosting), così deve scrivere solo la nuova password.
  • Il credito si scala quando il cliente invia il modulo. Ricevi link.opened, link.submitted e poi gli eventi della migrazione.
  • Si usa una volta sola, vale da 1 a 30 giorni (14 di default) e puoi revocarlo finché non è stato usato.

Da server a server

  • POST /migrations con le due caselle e le loro password, quando le hai già (per esempio una casella che stai creando adesso sui tuoi server).
  • Verifichiamo i due accessi e misuriamo l’origine prima di scalare il credito: una password sbagliata risponde 422 e non costa niente.
  • Le password viaggiano solo in HTTPS, sono cifrate a riposo (AES-256-GCM), non compaiono mai in log, risposte o webhook e vengono cancellate 14 giorni dopo l’ultima copia.
  • Fino a 500 caselle alla volta 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", … }

Stesso indirizzo, nuovo hosting

Imposta same_address: true quando il cliente tiene info@cliente.it e lo sposta sui tuoi server. Origine e destinazione hanno lo stesso indirizzo; l’host di destinazione è il tuo nuovo server.

Alla creazione memorizziamo gli indirizzi del vecchio server che ha risposto. Ogni copia successiva si collega lì (con TLS verificato sul vecchio nome), così dopo che hai spostato i record MX sui tuoi server, POST /migrations/{id}/delta legge ancora la vecchia casella e recupera quello che è arrivato nel frattempo.

Flusso consigliato: crea la migrazione (o il link ospitato) appena l’hosting è attivo → parte la copia → cambi i record MX → chiami delta → fatto. Il delta è gratuito entro 14 giorni dall’ultima copia; i messaggi già copiati vengono saltati, quindi niente doppioni.

Webhook

Aggiungi gli endpoint nell’area partner (solo https, nome DNS pubblico, fino a 5 per modalità). Mandiamo un evento JSON in POST a ogni endpoint iscritto a quel tipo. I payload non contengono mai password o token privati.

Rispondi 2xx entro 10 secondi. Qualsiasi altra risposta viene riprovata con attese crescenti (30 s, 2 min, 10 min, 30 min, 1 h, 2 h, 4 h, 6 h, 8 h: circa 22 ore in tutto). L’area partner mostra ogni consegna e ti fa riprovarla.

Un evento può arrivare più di una volta e fuori ordine: usa id per elaborarlo una volta sola e lo status dell’oggetto come fonte di verità.

Eventi

migration.created
È stata creata una migrazione (API, riga di un batch o link ospitato).
migration.started
Una copia è partita (prima copia o delta).
migration.completed
Una copia è terminata: status è completed o completed_with_errors.
migration.failed
Una copia non è riuscita: vedi failure_code e credit_refunded.
migration.cancelled
Una copia è stata fermata con /cancel.
link.opened
Il cliente ha aperto per la prima volta un link ospitato.
link.submitted
Il cliente ha inviato il link ospitato: l’oggetto contiene la nuova migrazione.
credits.low
Il credito live ha raggiunto la tua soglia (area partner → Impostazioni).
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, …
  } }
}

Verifica la firma

Ogni consegna ha l’header Migrabox-Signature: t=<secondi unix>,v1=<hex>. v1 è l’HMAC-SHA256 di t + "." + corpo grezzo, con chiave il segreto di firma dell’endpoint (whsec_…, mostrato una sola volta alla creazione).

Calcolalo sul corpo grezzo (prima del parse JSON), confronta in tempo costante e rifiuta i timestamp più vecchi di 5 minuti per bloccare le ripetizioni. Durante la rotazione del segreto l’header può contenere più v1: accetta l’evento se uno qualsiasi corrisponde.

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

Errori

Gli errori sono JSON con un code stabile (da usare nel tuo codice) e un message in inglese (per i log). Lo status HTTP indica la classe: 4xx la tua richiesta, 5xx noi (riprova con la stessa Idempotency-Key).

HTTP/1.1 422 Unprocessable Entity
{ "error": { "code": "SOURCE_AUTH_FAILED", "message": "Cannot sign in to the source mailbox" } }
CodiceHTTPSignificato
INVALID_INPUT400Un campo manca o non è valido; il messaggio lo nomina (mai il suo valore).
UNAUTHORIZED401Chiave mancante, malformata, revocata o scaduta.
INSUFFICIENT_CREDITS402Credito live esaurito (per un batch: non basta per tutte le righe).
NOT_FOUND404Nessun oggetto con quell’id per questa chiave e modalità.
RUN_ACTIVE409C’è già una copia in coda o in corso.
CREDENTIALS_PURGED409Sono passati più di 14 giorni dall’ultima copia: le password sono cancellate, crea una nuova migrazione.
IDEMPOTENCY_MISMATCH422Questa Idempotency-Key è stata usata con una richiesta diversa.
SOURCE_AUTH_FAILED422Il server di origine ha rifiutato l’accesso. DEST_… per la destinazione.
SOURCE_CONNECT_FAILED422Il server di origine non risponde (anche TLS_FAILED, TIMEOUT, HOST_NOT_ALLOWED).
SAME_SERVER422Le due parti sono la stessa casella sullo stesso server: rifiutato, mai copiato.
RATE_LIMITED429Troppe richieste per questa chiave: aspetta e riprova.

Limiti e convenzioni

  • Limiti per account e modalità (tutte le tue chiavi insieme), per endpoint e per minuto: 120 richieste, 60 creazioni, 30 verifiche, 10 batch. Oltre il limite: 429 RATE_LIMITED. /probe e /discover live sono disponibili dopo il primo acquisto di credito (prima: 402 CREDIT_REQUIRED).
  • Idempotency-Key su ogni POST: manda un valore univoco (l’id del tuo ordine o della casella). La prima risposta resta salvata 24 ore e viene ripetuta per la stessa chiave; te lo dice l’header Idempotent-Replayed: true.
  • Paginazione: GET /migrations?limit=20 restituisce has_more e next_cursor; passa cursor= per la pagina successiva. Dalla più recente.
  • I nomi dei server devono essere nomi DNS: indirizzi IP e reti private vengono rifiutati. I certificati TLS sono sempre verificati.
  • Le date sono ISO 8601 in UTC; il created dei webhook è in secondi Unix. Possiamo aggiungere campi alle risposte in qualsiasi momento: ignora quelli che non conosci.

Esempi

Esempi completi, senza dipendenze. Sostituisci la chiave con la tua.

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

Riferimento API

URL di base https://migrabox.com/api/v1. Gli schemi completi sono nel documento OpenAPI.

Account

  • GET/v1/account

    Saldo del credito e lotti con le scadenze.

Mailboxes

  • POST/v1/discover

    Impostazioni IMAP di un indirizzo (stesso motore del sito).

    Errori: INVALID_INPUT, CREDIT_REQUIRED

  • POST/v1/probe

    Verifica un accesso in TLS e, con measure, conta messaggi e byte.

    Errori: INVALID_INPUT, CREDIT_REQUIRED, RATE_LIMITED

Migrations

  • POST/v1/migrations

    Crea e avvia una migrazione con le due password.

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

    Fino a 500 migrazioni, elaborate in background.

    Errori: INVALID_INPUT, INSUFFICIENT_CREDITS

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

    Esito di un batch, riga per riga.

    Errori: NOT_FOUND

  • GET/v1/migrations

    Elenco con filtri (stato, external_id, date) e cursore.

    Errori: INVALID_INPUT, INVALID_CURSOR

  • GET/v1/migrations/{id}

    Stato e avanzamento.

    Errori: NOT_FOUND

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

    Copia ciò che è arrivato dall’ultima copia (dopo il cambio MX).

    Errori: NOT_FOUND, RUN_ACTIVE, CREDENTIALS_PURGED, CREDIT_REFUNDED, NOT_READY

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

    Ferma la copia in coda o in corso.

    Errori: NOT_FOUND, NOT_RUNNING

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

    Tutte le copie con i contatori e la cronologia.

    Errori: NOT_FOUND

Hosted links

Novità

  • v1: migrazioni, batch, link ospitati con il tuo logo, delta, interruzione, report, discover, probe, webhook firmati, modalità test.