Flussi: trigger e step di automazione
Crea sequenze email automatizzate che reagiscono a eventi su contatti ed email
Un flusso iscrive automaticamente i contatti e li fa passare attraverso una sequenza di step — invia un'email, attendi, dividi in base a una condizione, aggiorna il contatto, chiama un webhook — in base a un trigger che definisci. I flussi vivono all'interno di un tenant, girano interamente lato server e non richiedono polling: iscrizione e ogni step sono guidati da eventi.
Questa pagina documenta il motore dei flussi così come si comporta davvero in produzione, inclusi quali tipi di trigger sono collegati oggi e quali sono riservati a una release futura. Configurare un flusso su un trigger non ancora attivo non genera errori — semplicemente non iscriverà mai nessuno, in silenzio. Vedi Tipi di Trigger qui sotto.
Come Funziona
Un flusso ha tre parti: un trigger (cosa avvia l'iscrizione), un array di step (cosa succede a un contatto iscritto, in ordine) e uno status (draft, active, inactive).
Succede qualcosa (es. un tag viene aggiunto a un contatto)
↓
Ogni flusso active il cui trigger corrisponde viene trovato
↓
Il contatto viene iscritto (idempotente — lo stesso evento non iscrive mai due volte)
↓
Lo step 0 viene eseguito
↓
Lo step 1 viene eseguito (subito, o dopo il ritardo di uno step wait)
↓
...
↓
L'iscrizione si completaSotto il cofano, sono due Cloud Function che comunicano tramite Pub/Sub e Cloud Tasks:
- Valutazione del trigger — qualsiasi azione che fa scattare un trigger (es. un cambio di tag) pubblica un messaggio. Una funzione interroga ogni flusso
activeil cuitrigger.typecorrisponde, controlla la config del trigger contro l'evento, e crea un'iscrizione per ogni corrispondenza. Gli ID di iscrizione sono deterministici (un hash di tenant + flusso + contatto + contesto del trigger), quindi lo stesso evento non può mai iscrivere due volte lo stesso contatto. - Esecuzione degli step — ogni step gira come un proprio Cloud Task. Uno step
waitnon tiene aperta una funzione; pianifica il task dello step successivo con un ritardo e ritorna subito. Questo significa che un flusso con un'attesa di 14 giorni non costa nulla mentre attende, e sopravvive a deploy, riavvii, tutto.
Un contatto viene saltato (non fallito) se il suo status è unsubscribed, bounced, o complained al momento dell'invio — controllato di nuovo a ogni step send_email, non solo all'iscrizione.
Tipi di Trigger
| Trigger | Stato | Iscrive quando |
|---|---|---|
contact_tag_added | Disponibile | Un tag specifico viene aggiunto a un contatto |
contact_tag_removed | Disponibile | Un tag specifico viene rimosso da un contatto |
contact_joins_audience | Riservato | (lo schema esiste; nulla pubblica ancora questo evento) |
email_event | Riservato | (lo schema esiste; nulla pubblica ancora questo evento) |
manual | Riservato | (lo schema esiste; non esiste ancora un endpoint di iscrizione) |
Solo contact_tag_added e contact_tag_removed iscrivono davvero i contatti oggi. Gli altri tre tipi di trigger sono valori validi che l'API accetta — un flusso che li usa si salva senza problemi, si attiva senza problemi, mostra 0 iscrizioni per sempre, e non ti dice mai perché. Se ti serve "iscrivi quando succede X" e X non è un cambio di tag, fai tu stesso il tagging: aggiorna i tag del contatto tramite PATCH /v1/contacts/:id dal tuo codice nel momento in cui l'evento reale accade, e fai scattare il trigger su quel tag.
Configurazione del trigger
La config del trigger è un oggetto piatto { chiave: valore }, solo valori stringa. Una chiave di config vuota o assente significa "corrispondi a qualsiasi cosa", non "non corrispondere a nulla" — omettila deliberatamente.
| Tipo di trigger | Chiave config | Comportamento se impostata | Comportamento se omessa |
|---|---|---|---|
contact_tag_added / contact_tag_removed | tagName | Iscrive solo per quel tag esatto | Iscrive su qualsiasi cambio di tag — quasi mai quello che vuoi |
contact_joins_audience | audienceId | Limita a un'audience | Corrisponde a qualsiasi ingresso in audience |
email_event | eventType, emailId | Limita a un tipo di evento e/o una email specifica | Corrisponde in modo ampio |
{
"type": "contact_tag_added",
"config": { "tagName": "waitlist-confirmed" }
}Crea un Flusso
Creare è in due step: l'API permette solo di dare un nome al flusso in creazione — trigger e step si impostano dopo con PATCH. Rispecchia il builder della dashboard, che crea una bozza vuota nel momento in cui clicchi "Nuovo flow" e ti lascia collegare tutto sul canvas.
1. Crea
curl -X POST https://api.tratto.email/v1/flows \
-H "Authorization: Bearer tratto_live_..." \
-H "Content-Type: application/json" \
-d '{"name": "Nurturing waitlist"}'{ "data": { "id": "flow_8f3ZqXnryVtC5k2Wm7B9e4" } }2. Configura trigger + step
curl -X PATCH https://api.tratto.email/v1/flows/flow_8f3ZqXnryVtC5k2Wm7B9e4 \
-H "Authorization: Bearer tratto_live_..." \
-H "Content-Type: application/json" \
-d '{
"trigger": {
"type": "contact_tag_added",
"config": { "tagName": "waitlist-confirmed" }
},
"steps": [
{ "id": "s0", "type": "send_email", "config": { "templateId": "tmpl_welcome", "subject": "Sei dentro", "from": "hello@tuodominio.com", "fromName": "La tua azienda" } },
{ "id": "s1", "type": "wait", "config": { "delay": "2", "unit": "hours" } },
{ "id": "s2", "type": "send_email", "config": { "templateId": "tmpl_nurture_1", "subject": "Cosa stiamo costruendo", "from": "hello@tuodominio.com", "fromName": "La tua azienda" } }
]
}'Un flusso viene creato in draft e ci resta — senza iscrivere nessuno — finché non lo attivi. Massimo 20 step per flusso. Gli id degli step sono stringhe a tua scelta; devono solo essere univoci all'interno del flusso.
Tipi di Step
Il config di ogni step è { chiave: stringa }, come i trigger — l'API non converte i tipi, quindi numeri e booleani entrano come stringhe.
send_email
| Chiave config | Obbligatoria | Note |
|---|---|---|
templateId | Sì, per renderizzare qualcosa | ID di un template — vedi Template |
subject | Consigliata | Se omessa, resta vuota |
from | No | Se omessa, l'attivazione la riempie con il mittente automation del workspace, o con quello generale. Senza alcun mittente l'attivazione fallisce con 422. Vedi Mittenti |
fromName | No | Nome visualizzato abbinato a from |
{ "id": "s0", "type": "send_email", "config": { "templateId": "tmpl_abc123", "subject": "Benvenuto", "from": "hello@tuodominio.com", "fromName": "La tua azienda" } }Variabili disponibili nel template: email, firstName, lastName del contatto, e ogni chiave nei customFields del contatto vengono passate automaticamente come {{token}} — non serve dichiararle sullo step. Se un contatto ha customFields: { "position": "42" }, un template contenente {{position}} renderizza 42 per quell'invio, senza configurazione aggiuntiva.
wait
| Chiave config | Obbligatoria | Note |
|---|---|---|
delay | Sì | Un intero positivo, come stringa, es. "2" |
unit | No, default minutes | Uno tra seconds, minutes, hours, days |
{ "id": "s1", "type": "wait", "config": { "delay": "14", "unit": "days" } }Il puntatore di step dell'iscrizione avanza subito; è il task dello step successivo a essere ritardato. Controllare un'iscrizione a metà attesa mostra correttamente che è già sullo step successivo, solo non ancora dovuto.
branch
Valuta una condizione sui campi del contatto stesso (non customFields — campi di primo livello come status) e salta a un indice di step diverso in base al risultato.
| Chiave config | Obbligatoria | Note |
|---|---|---|
conditionField | Sì | Nome di un campo sul documento del contatto |
conditionOperator | No, default equals | equals, not_equals, exists, not_exists, contains |
conditionValue | Per equals/not_equals/contains | Valore da confrontare |
trueNextStep | No, default lo step successivo | Indice di step a cui saltare se la condizione è vera |
falseNextStep | No, default termina il flusso | Indice di step a cui saltare se la condizione è falsa |
{
"id": "s2",
"type": "branch",
"config": {
"conditionField": "status",
"conditionOperator": "equals",
"conditionValue": "subscribed",
"trueNextStep": "3",
"falseNextStep": "5"
}
}trueNextStep/falseNextStep sono indici nell'array steps (come stringhe), non ID di step — pianifica l'ordine dell'array prima di collegare i branch.
Lo step branch del builder nella dashboard espone al momento una coppia campo/valore semplificata che non corrisponde alle chiavi di config qui sopra. Configura gli step branch via API finché il builder non viene aggiornato.
update_contact
| Chiave config | Obbligatoria | Note |
|---|---|---|
action | No, default set_field | set_field, add_tag, remove_tag |
field, value | Per set_field | Imposta un campo arbitrario sul contatto |
tag | Per add_tag/remove_tag | Nome del tag da aggiungere o rimuovere |
{ "id": "s3", "type": "update_contact", "config": { "action": "add_tag", "tag": "nurtured" } }webhook_call
Notifica un URL esterno. Il corpo della richiesta è fisso — { "tenantId", "enrollmentId", "stepId" } — non è un template che compili tu.
| Chiave config | Obbligatoria | Note |
|---|---|---|
url | Sì | Deve essere http/https e un indirizzo pubblico — IP privati/riservati (127.0.0.1, 10.x, 192.168.x, ecc.) sono rifiutati |
method | No, default POST | Qualsiasi metodo HTTP |
secret | No | Se impostato, firma la richiesta con X-Tratto-Signature (HMAC-SHA256) — stesso schema dei webhook normali |
{ "id": "s4", "type": "webhook_call", "config": { "url": "https://tuaapi.com/hooks/flow-completed", "secret": "whsec_..." } }Timeout di 10 secondi; i fallimenti vengono loggati ma non fermano il flusso.
Attivare, Disattivare, Modificare
# Attiva — inizia a iscrivere
curl -X POST https://api.tratto.email/v1/flows/flow_abc123/activate \
-H "Authorization: Bearer tratto_live_..."
# Disattiva: ferma le nuove iscrizioni e mette in pausa quelle in corso
curl -X POST https://api.tratto.email/v1/flows/flow_abc123/deactivate \
-H "Authorization: Bearer tratto_live_..."L'attivazione controlla ogni step send_email prima che il flusso possa
iscrivere qualcuno: il mittente deve stare su un dominio verificato e il
template dello step deve essere published. Se non lo è, la richiesta
fallisce con 422 TEMPLATE_NOT_PUBLISHED e
Template 'tmpl_abc123' on step 's0' is not published and cannot be used to send.;
un templateId inesistente fallisce con 404 e
Template 'tmpl_abc123' on step 's0' not found. Pubblica prima il template
(vedi Template), poi riprova ad
attivare.
Uno step senza un proprio from riceve il mittente del workspace
all'attivazione, scritto sullo step: resta quello anche se poi cambi il mittente
automation o quello generale, e disattivare e riattivare il flow non lo cambia.
Per cambiarlo, disattiva il flow, aggiorna gli step togliendo from,
fromName e replyTo dallo step di invio, poi riattivalo. L'editor dei flow
nella dashboard non ha il campo mittente, quindi si fa via API (vedi
Mittenti).
Non puoi fare PATCH degli steps di un flusso active — disattiva prima, modifica, riattiva. trigger e name si possono ancora cambiare mentre è attivo.
Disattivare ferma anche chi è già dentro
Disattivare un flusso non ferma solo le nuove iscrizioni: ferma anche i contatti già iscritti. L'iscrizione passa in pausa e gli step successivi non partono, comprese le attese già in corso.
Le iscrizioni fermate non riprendono se riattivi il flusso. Riprendere vorrebbe dire decidere da quale step ripartire e cosa fare delle attese già scadute, e quel comportamento non esiste: un contatto fermato a metà sequenza resta fermo. Se ti serve che completi, va iscritto di nuovo.
Fino al 29 settembre 2026 il comportamento era l'opposto — chi era già dentro proseguiva — e chi disattivava un flusso per fermare degli invii non li fermava.
Elenca, Recupera, Elimina
curl https://api.tratto.email/v1/flows \
-H "Authorization: Bearer tratto_live_..."
curl https://api.tratto.email/v1/flows/flow_abc123 \
-H "Authorization: Bearer tratto_live_..."
curl -X DELETE https://api.tratto.email/v1/flows/flow_abc123 \
-H "Authorization: Bearer tratto_live_..."Eliminare un flusso active è bloccato allo stesso modo in cui lo è modificarne gli step — disattiva prima.
Testare un Flusso
Non esiste oggi una scorciatoia di iscrizione manuale via API (vedi Tipi di Trigger). Per testare un flusso contact_tag_added/contact_tag_removed end to end:
- Attiva il flusso.
- Crea o riusa un contatto di test.
- Aggiungi il tag esatto per cui il trigger è configurato, via
PATCH /v1/contacts/:id. - Controlla
GET /v1/flows/flow_abc123—enrollmentsdovrebbe incrementare, e il contatto di test dovrebbe ricevere il primo stepsend_emailentro pochi secondi.
Perché Costruire un Flusso
Qualsiasi cosa del tipo "quando succede X a un contatto, fai Y nel tempo" — senza dover scrivere e ospitare tu la logica di scheduling.
Nurturing di iscrizione / waitlist. Tagga un contatto waitlist-confirmed nel momento in cui completa il double opt-in, e lascia che un flusso mandi subito un'email di benvenuto, poi un breve drip (cosa stai costruendo, perché è prezzato in un certo modo, un'anteprima prodotto, un'offerta early-access) distanziato di giorni o settimane — è esattamente lo schema su cui gira la waitlist di Tratto stessa.
Re-engagement / win-back. Esegui un tuo controllo di inattività (ultima apertura email, ultimo login, qualsiasi segnale che dica "sparito") su uno schedule, tagga i contatti corrispondenti inactive-30d, e lascia che un flusso mandi una sequenza di recupero — un primo tocco, poi uno sconto o un aggiornamento prodotto, poi una notifica finale "smetteremo di scriverti" abbinata a uno step update_contact che li disiscrive se ancora non hanno interagito.
Checklist di onboarding. Tagga un contatto quando si iscrive al tuo prodotto; fai un drip di qualche giorno con "hai già provato X", ognuna che punta a una feature diversa, con step wait che danno il tempo di andare davvero a provarla prima del prossimo sollecito.
Passaggio alle vendite su alto intento. Tagga un contatto pricing-page-viewed-3x (dal tuo tracking) e usa uno step webhook_call per avvisare un canale Slack o il CRM nel momento in cui succede — il flusso diventa il trigger per un processo umano, non solo altra email.
Igiene dei dati. Tagga i contatti che entrano in uno stato specifico (trial-expired, payment-failed) e usa step update_contact per normalizzare un campo lifecycle_stage, così la segmentazione altrove nel prodotto (audience, campagne) resta coerente senza un passaggio di pulizia manuale.
Best Practice
Progetta intorno all'unico trigger davvero attivo. Finché contact_joins_audience/email_event/manual non sono collegati, ogni flusso parte di fatto da un cambio di tag. Prendi l'abitudine di taggare i contatti dal tuo codice applicativo nei momenti che contano — è quello il vero punto di ingresso.
Imposta tagName esplicitamente. Un trigger su tag vuoto corrisponde a ogni cambio di tag su ogni contatto. Compilalo sempre.
Dai ai flussi nomi che descrivono cosa fanno, non cosa sono. Follow-up post-acquisto 7 giorni, non Flusso 3.
Disattiva prima di modificare gli step. Non puoi evitarlo — lo impone l'API — quindi prendi l'abitudine presto invece di trovarti l'errore a metà modifica.
Distanzia gli invii con criterio. Gli step wait sono gratuiti e asincroni — non c'è pressione di costo per comprimere una sequenza. Dai ai contatti il tempo di leggere e agire su un'email prima che arrivi la successiva.
Prossimi Passi
- Tracciare le email inviate dai flussi? Configura i Webhook
- Inviare via API direttamente? Vedi Invia Email
- Costruire i template che un flusso invia? Vai a Template
- Gestire i tag dei contatti? Vedi Contatti
Modifica questa pagina su GitHub
Ultimo aggiornamento
Contatti: Crea, Importa e Status
Gestisci contatti email con status, tag e campi personalizzati
Ricetta: avviare un flusso dai tuoi eventi
Aggiungi un tag a un contatto dal tuo backend quando c'è un acquisto, un carrello abbandonato o un'iscrizione a un lead magnet, e lascia che sia un flusso a inviare le email.