Pattern integrazione B2B SaaS
Sync contatti, API campagne e webhook bidirezionali per newsletter embedded.
Questa pagina descrive un'architettura di riferimento per un prodotto B2B SaaS che integra le capacità newsletter di MailingCore: la tua app resta la fonte di verità del consenso, mentre MailingCore mantiene una replica operativa per invio, disiscrizione ospitata e deliverability.
Il pattern è stato validato in integrazioni tipo produzione (app multi-tenant, add-on CRM, SaaS verticali). Adatta nomi e ID al tuo dominio.
Panoramica architettura
Scope API key (minimi)
| Scope | Uso |
|---|---|
contacts:read | Riconciliazione (updatedSince) |
contacts:write | Upsert, bulk import, erasure |
campaigns:read | Poll stato e statistiche |
campaigns:write | Creare, test, programmare, inviare |
webhooks:manage | Registrare URL receiver |
Opzionale: suppressions:write se invii disiscrizioni dal pannello admin oltre ai webhook.
1. Sincronizzazione contatti
Obiettivo: Mantenere l'audience opted-in in MailingCore senza passare liste destinatari a ogni invio.
| Aspetto | Raccomandazione |
|---|---|
| Identità | externalId = ID stabile utente/account nel tuo sistema (opaco, senza PII extra) |
| Upsert | PUT /contacts quando viene concesso il consenso |
| Carico iniziale | POST /contacts/bulk a chunk (≤ 1000 per richiesta) |
| Incrementale | Job periodico + hook on-change su email, locale o consenso |
| Campi | email, locale, optIn: true, consentVersion, tag source |
| Revoca nell'app | DELETE /contacts/:externalId o PATCH con optIn: false |
| Erasure GDPR | DELETE /contacts/:externalId — MailingCore propaga suppression |
Riconciliazione: GET /contacts?updatedSince=<ISO>&cursor= per allineare disiscrizioni ospitate al tuo store consenso.
Cadenza suggerita: ogni 15–60 minuti più hook real-time su eventi consenso.
2. Receiver webhook (tuo server)
Registra con Creare endpoint:
{
"url": "https://tuo-saas.com/webhooks/mailingcore",
"events": [
"contact.unsubscribed",
"email.bounced",
"email.complained"
],
"secret": "<tuo-segreto-env>"
}
| Evento | Azione tipica nel tuo SaaS |
|---|---|
contact.unsubscribed | Revocare consenso newsletter per externalId o email; audit log |
email.bounced (hard) | Segnare email non valida; sync suppression opzionale |
email.complained | Revocare consenso; alert operatori |
Verifica X-MailingCore-Signature (HMAC SHA-256, tolleranza replay ±5 min). Rispondi 200 subito; elabora in async. Vedi Consegne e retry.
3. Flusso campagna (sostituisce relay batch)
Smetti di usare fan-out POST /emails/batch con array destinatari espliciti. Usa l'API campagne:
Pre-sync audience
Esegui sync contatti con
optIn: trueaggiornati.Crea bozza
POST /campaignscontemplateVersionId,subject,audienceFilter: { optIn: true }.Verifica copertura locale
GET /campaigns/:id/locale-coverage— varianti template per Copertura locale.Invio test
POST /campaigns/:id/testa 1–5 indirizzi QA interni.Programma o invia
POST /campaigns/:id/scheduleoPOST /campaigns/:id/send(fan-out async).Poll stato
GET /campaigns/:idfino aSENT,FAILEDoCANCELLED. PersistimailingcoreCampaignIdnella tua entità campagna.
Passo passo completo: Creare e inviare campagna.
4. Feature flag e rollback
Mantieni uno switch di configurazione (es. NEWSLETTER_MODE=legacy_relay | mailingcore_api) per tornare al percorso di invio precedente senza redeploy. Esegui smoke test su staging prima di spostare il traffico produzione.
5. Checklist smoke test
| # | Scenario | Criterio pass |
|---|---|---|
| 1 | Upsert contatti test con locale distinti | Elencati in GET /contacts; optIn: true |
| 2 | Test send campagna | Email ricevuta; {{unsubscribeUrl}} presente |
| 3 | Audience multi-locale | Warning locale-coverage coerenti |
| 4 | Invio produzione piccolo | status: SENT; stats sent > 0 |
| 5 | Clic disiscrizione ospitata | contact.unsubscribed ricevuto; consenso revocato nell'app |
| 6 | Revoca consenso nell'app | Contatto rimosso o opt-out in MailingCore |
| 7 | Retry sync idempotente | Nessun duplicato externalId |