FlowSharp - integrazioni e API
Appendice piu' tecnica per chi integra FlowSharp con sistemi esterni, automazioni, agenti AI, n8n o estensione browser.
1. Principi di integrazione
FlowSharp puo' essere integrato in molti modi, ma il principio resta sempre lo stesso:
FlowSharp governa il processo; gli altri sistemi producono dati, ricevono task o reagiscono agli eventi.
I canali principali sono:
- API REST con autenticazione utente;
- API key per trigger esterni;
- eventi e subscriber;
- webhook task;
- callback per task asincroni;
- n8n;
- MCP per agenti AI;
- estensione browser;
- provider AI e assistenti.
Per presentazioni meno tecniche puoi usare questa infografica come mappa dei canali, lasciando gli endpoint alle sezioni successive.
2. Avviare processi da sistemi esterni
Un sistema esterno puo' avviare un flow FlowSharp usando un trigger API.
Uso tipico:
- un ordine arriva dall'e-commerce;
- un lead qualificato arriva dal CRM;
- una richiesta nasce da un portale cliente;
- un sistema ERP produce una pratica da verificare;
- un'automazione n8n apre un item.
Pattern consigliato
- Pubblica il flow.
- Definisci un codice flow stabile.
- Crea una API key dedicata allo scenario.
- Invia
entityRefIdedata. - Usa idempotenza quando il sistema sorgente puo' ripetere la chiamata.
Idempotenza
La creazione di item e la pubblicazione di eventi supportano una Idempotency-Key: POST /items e POST /events/raise accettano la chiave come header Idempotency-Key (o campo equivalente nel body). Stessa chiave = stessa operazione, eseguita una sola volta — su reti instabili, retry di n8n/webhook o doppio click non nascono duplicati.
Inoltre, i flow con la preferenza "unicità dell'entità" (o con attivazione "Uno alla volta") deduplicano per entità finché il primo item è aperto: lo stesso entityRefId non genera due item attivi contemporaneamente, ma una volta chiuso il primo se ne può aprire un altro. Con attivazione "Una sola volta per entità" la deduplicazione è invece permanente: lo stesso entityRefId non genera mai più un secondo item, anche a flusso completato. La preferenza "entityRef obbligatorio" richiede solo che il riferimento sia presente, senza deduplicare in nessun caso.
I dati iniziali e le patch sono fail-closed. data.id è un normale campo business;
le colonne reali dell'item (tenantId, xflowDefId, currentStatusId,
assignedTo), le chiavi di prototype pollution e le chiavi top-level che iniziano
con _ sono riservate. Se il payload ne contiene una, l'intera richiesta fallisce
con 400 ITEM_DATA_KEY_RESERVED: i campi validi presenti nello stesso body non
vengono applicati.
Su PATCH /items/:id/data, _expectedDataRevision e' l'unica eccezione: e' un
campo di controllo per l'optimistic lock, viene estratto prima della patch e non
entra mai in item.data.
Esempio:
curl -X POST https://flowsharp.example.com/api/v1/trigger/order_approval \
-H "X-Api-Key: xfk_..." \
-H "Content-Type: application/json" \
-d '{
"entityRefId": "ORD-1042",
"data": {
"customer": "Acme Srl",
"amount": 12800,
"currency": "EUR"
},
"assignedTo": "operator@example.com"
}'
3. Eventi
Gli eventi servono a disaccoppiare flow e sistemi.
Un evento puo':
- far partire un flow;
- aggiornare o sbloccare un item;
- notificare sistemi esterni;
- collegare piu' processi;
- rendere visibili relazioni nelle Process Maps.
Esempio
curl -X POST https://flowsharp.example.com/api/v1/events/raise \
-H "Authorization: Bearer ..." \
-H "Content-Type: application/json" \
-d '{
"eventName": "offer.approved",
"payload": {
"offerId": "OFF-1042",
"customerId": "C-77"
}
}'
Subscriber
Un subscriber permette di reagire a un evento con:
- webhook;
- email;
- n8n;
- azione custom.
Per documentazione utente, conviene parlare di "azioni collegate a un evento". Nei materiali tecnici si puo' usare il termine subscriber.
Correlazione delle sottoscrizioni
Ogni sottoscrizione (XFlowItemEventSub) a un evento porta una correlationValue (di norma l'entityRefId dell'item, ereditata dal percorso designer) usata per capire a quale item indirizzare l'evento quando piu' item sono in ascolto sullo stesso XEventDef.
- Una sottoscrizione con
correlationValuericeve solo un evento il cui payload porta lo stesso valore (chiavi cercate, case-insensitive:entityRefId/entityRef, poicorrelationId; se nessuna e' presente, il matching ricade sulsourcedichiarato da chi ha alzato l'evento). - Una sottoscrizione senza
correlationValue(vuota onull— capita quando l'item ha unentityRefIdvuoto) riceve solo un evento che non porta nessuna correlazione nel payload (decisione 03/08). Non riceve piu', come accadeva prima, qualsiasi evento indistintamente: un evento conpayload.entityRefIdvalorizzato e' per definizione indirizzato a un target esplicito, e non deve "colpire" item che non c'entrano solo perche' la loro sottoscrizione non ha un filtro.
Le sottoscrizioni degli item sono one-shot. Il primo evento correlato imposta
receivedAt e consuma quella specifica sottoscrizione; eventi successivi non
vengono riconsegnati allo stesso item. Per attendere una nuova occorrenza serve una
nuova sottoscrizione creata dal processo. Un contratto multi-occorrenza non è
simulato riutilizzando la riga già consumata.
Schema del payload
Una definizione evento può dichiarare payloadSchema e attivare
enforcePayload. Lo schema viene compilato già al salvataggio; enforcePayload
senza schema è rifiutato. L'enforcement è opt-in e, quando attivo, vale per tutti i
producer REST, MCP, task e worker. Un payload non conforme restituisce
422 EVENT_PAYLOAD_INVALID con soli path e keyword, senza includere i valori del
payload nei log o nell'errore.
Azione legacy {type:'transition'} e item in coda WIP
Alcune sottoscrizioni (dati piu' vecchi, non generate dal designer attuale) portano un'action diretta { type: 'transition', targetStatusId }: quando l'evento arriva, l'item viene transizionato subito, senza passare da una regola eval.
Se pero' l'item e' parcheggiato in coda WIP (awaitingWip: true), questa transizione diretta non scavalca il gate: l'evento viene comunque registrato (sub marcata ricevuta, storico item, eval-trigger accodato) ma la transizione non viene rieseguita quando l'item esce dalla coda ed entra nella fase — e' un drop ratificato (decisione 03/08), non un bug da correggere.
Per un comportamento equivalente che sopravviva al rilascio dalla coda WIP, sostituire l'azione diretta con una regola di transizione automatica (XFlowStatusEval) che legge l'evento gia' ricevuto tramite _receivedEvents nella condizione — quel dato resta disponibile quando l'item viene valutato di nuovo al rilascio dalla coda.
Eventi di runtime
FlowSharp puo' emettere eventi anche quando il processo incontra una condizione operativa automatica. Sono utili per sottoscrizioni, trigger basati su evento e task Evento:
| Situazione | Nome evento |
|---|---|
| Timeout di una fase | <codiceFlow>.<codiceStato>.timeout |
| Limite WIP | <codiceFlow>.<codiceStato>.wip |
| Massimo tentativi raggiunto | <codiceFlow>.<codiceStato>.maxattempts |
| SLA del Flow superato | <codiceFlow>.sla |
Gli eventi vengono registrati automaticamente quando salvi o importi un Flow che usa quelle impostazioni, cosi compaiono direttamente nei selettori. Per WIP, il payload contiene wipEvent per distinguere reached, waiting, released e override. Un Super Admin puo' registrare in blocco gli eventi mancanti dei Flow esistenti tramite il backfill POST /admin/backfill-runtime-events.
4. Webhook task
Un task webhook permette a un flow di chiamare un sistema esterno.
Esempi:
- inviare dati a n8n;
- creare un record su CRM;
- aggiornare ERP;
- chiamare un servizio di scoring;
- notificare un portale cliente.
Buone pratiche:
- inviare solo i dati necessari;
- usare retry per sistemi instabili;
- rendere il task bloccante solo quando il processo deve davvero aspettare;
- salvare un risultato leggibile nell'item;
- usare callback quando l'operazione richiede tempo.
5. Callback asincrone e n8n
Per automazioni lunghe, il pattern consigliato e':
- FlowSharp avvia un task webhook.
- n8n riceve il payload.
- n8n esegue le integrazioni.
- n8n richiama FlowSharp quando il lavoro e' completato.
- FlowSharp aggiorna il task e continua il processo.
Questo evita di tenere bloccata una chiamata HTTP lunga e rende il processo piu' robusto.
Il blocco xflow nel payload
Le chiamate webhook verso un connector n8n includono automaticamente un blocco xflow nel body con il contesto per il ritorno: identificativo dell'item, istanza e codice task, riferimenti del Flow, URL di callback per ID e per codice e identificativo dell'esecuzione. Sul nodo Webhook di n8n il corpo HTTP sta sotto body, quindi l'envelope si legge come {{ $('Webhook').item.json.body.xflow... }} — referenziando il nodo per nome, non come $json corrente (vedi il riquadro sugli identificativi qui sotto).
La chiamata di ritorno si autentica con l'header x-api-key e una API key dotata di scope n8nBridge; il payload non contiene un token di callback firmato. L'header standard di autorizzazione HTTP non e' accettato su questa rotta: usarlo produce 401 AUTH_REQUIRED.
runId: obbligatorio nella callback (breaking change)
POST /tasks/callback richiede il campo runId nel body. FlowSharp lo genera a ogni dispatch webhook e lo consegna al workflow n8n in due punti equivalenti: nel blocco envelope (xflow.runId) e nell'header X-XFlow-Run-Id della chiamata in uscita. Il nodo n8n che richiama FlowSharp deve rimandarlo indietro nel body — il contratto di rientro accettato e' solo quello, l'header non viene letto in ingresso.
Se runId manca dal body, la callback e' rifiutata con:
// 400
{ "code": "RUNID_REQUIRED", "error": "runId mancante: rimanda il valore xflow.runId ricevuto nel payload del webhook" }
nessun task o history viene toccato. Se runId e' presente ma appartiene a un tentativo gia' superato (retry/force in mezzo), la callback e' rifiutata con 409 STALE_CALLBACK — il fence anti-callback-stantia resta invariato.
I tre identificativi vengono da un solo frame. $json e' l'input del nodo corrente: appena fra il Webhook e il nodo di risposta c'e' un altro nodo (Set, Code, IF, una chiamata HTTP), $json non e' piu' il payload originale. Prendere itemId/runId da $json e il taskId dal nodo Webhook significa combinare identificativi di esecuzioni e frame diversi. Si referenzia quindi sempre il nodo trigger per nome — $('Webhook'), da rinominare se il tuo nodo si chiama diversamente — e da li' si leggono tutti e tre.
Attenzione al campo taskId: la rotta di callback risolve sull'ID del task di design (xflowStatusTaskId), che l'envelope xflow non porta — xflow.taskInstanceId è l'ID dell'istanza runtime, un valore diverso, e rimandarlo indietro come taskId produce un 404 TASK_NOT_FOUND. L'ID corretto viaggia solo nell'header in ingresso X-XFlow-Task-Id della chiamata webhook originale. Sul nodo Webhook gli header stanno sotto headers e il corpo sotto body: da qui la forma delle tre espressioni.
{
"itemId": "{{ $('Webhook').item.json.body.xflow.itemId }}",
"taskId": "{{ $('Webhook').item.json.headers['x-xflow-task-id'] }}",
"runId": "{{ $('Webhook').item.json.body.xflow.runId }}",
"status": "Done",
"output": { "note": "Processed by n8n" }
}
L'header di autenticazione di questo nodo e' x-api-key con la API key di scope n8nBridge (vedi sopra). Gli snippet pronti in Gestione → Integrazioni generano gia' queste espressioni: se hai copiato un template piu' vecchio, rigenerali.
Breaking change dichiarato: prima di questa versione runId era opzionale (fence opt-in, compat con workflow che non lo conoscevano ancora). Oggi solo workflow di test chiamano l'endpoint senza runId: vanno aggiornati per includerlo, altrimenti ricevono 400 RUNID_REQUIRED su ogni callback.
Se il task webhook async non passa da un connector n8n (nessun n8nInstanceId sul connector, quindi nessun blocco xflow nel body uscente), runId arriva comunque — solo nell'header X-XFlow-Run-Id della chiamata originale: leggilo lì e rimandalo nel body della callback allo stesso modo del taskId.
Completare un task per codice
Oltre che tramite l'ID istanza, un task puo' essere completato indicando il suo codice (quello stabile assegnato in fase di progettazione). Da n8n basta dire "completa il task con codice APPROVA" sull'elemento, senza conoscere l'ID generato a runtime. In Gestione → Integrazioni e' disponibile lo snippet "Completa Task (per codice)" pronto da incollare; tutti gli snippet si incollano direttamente nel canvas di n8n.
6. n8n come automation fabric
n8n e' ideale per connettori e orchestrazione tecnica. FlowSharp resta il layer business:
| n8n | FlowSharp |
|---|---|
| Collega servizi e API | Governa stato e processo |
| Esegue workflow tecnici | Decide quando un task entra nel processo |
| Trasforma dati | Misura tempi, costi e ROI |
| Riceve webhook | Mantiene audit e responsabilita |
| Completa callback | Avanza item e task |
La frase utile in demo:
n8n muove i dati. FlowSharp governa il lavoro.
Comodita' operative dell'integrazione n8n:
- Apri il workflow con un click: sia dalla schermata Integrazioni (sui connettori n8n) sia dal task webhook, un link porta direttamente all'editor del workflow n8n collegato.
- Test guidato: il tasto Test apre una finestra con payload di esempio modificabile e interruttore Test/Produzione (predefinito: Test). In modalita' Test la chiamata usa il webhook di test di n8n (ricorda di attivare "Listen for test event"); avviare un test in Produzione richiede una conferma esplicita.
- Task allineati al connettore: un task webhook puo' "seguire" il body template del connettore n8n — dopo un resync le modifiche si propagano da sole, senza restare su una copia vecchia.
- n8n in locale: import, test ed esecuzione verso un'istanza n8n su localhost / rete privata (appliance/dev) sono consentiti, restando protetti verso Internet.
- URL mascherato: l'URL del connettore nell'elenco e' oscurato di default, con un bottone per mostrarlo su richiesta.
7. MCP e agenti AI esterni
FlowSharp puo' esporre strumenti ad agenti AI esterni tramite MCP.
Questo consente a un assistente autorizzato di:
- elencare flow;
- capire quando usare un flow;
- leggere item;
- avviare processi;
- eseguire transizioni consentite;
- lavorare rispettando ruoli e permessi.
Tra gli strumenti esposti c'e' anche flow_agent, che permette a un assistente esterno di dialogare con il Flow Agent: eredita la stessa Schermatura dati (Data Shield) della chat, quindi il provider AI vede solo dati pseudonimizzati quando la schermatura e' attiva.
Buone pratiche:
- creare chiavi MCP dedicate;
- limitare strumenti e permessi;
- documentare chiaramente cosa l'agente puo' fare;
- usare flow con intent e frasi di esempio;
- mantenere audit e data governance attivi.
Nota di sicurezza: la chiave MCP non viene accettata nella query-string sul canale principale (solo sul transport legacy che lo richiede) e viene oscurata nei log.
Gli schema dichiarati dai tool MCP sono applicati anche a runtime. Campi obbligatori
mancanti, UUID o date malformati, enum fuori contratto e proprieta' non dichiarate
restituiscono INVALID_ARGUMENT prima di eseguire query o mutazioni. Solo gli
oggetti business esplicitamente liberi, come data e payload, accettano chiavi
aggiuntive; anche questi restano soggetti alle policy dati del dominio.
8. Provider AI e assistenti
Gli Admin possono configurare provider AI e assistenti.
Provider tipici:
- OpenAI;
- OpenRouter;
- Ollama locale;
- provider compatibili con API OpenAI-like.
Gli assistenti permettono di standardizzare:
- prompt di sistema;
- template utente;
- output su campo o outcome;
- modello;
- temperatura;
- profondita conversazionale;
- stato attivo/inattivo.
9. Data governance nelle integrazioni AI
Quando un'integrazione usa AI, occorre ragionare su:
- quali campi sono sensibili;
- quali dati servono davvero al modello;
- se un secondo provider deve anonimizzare testo libero;
- se l'assenza di dati deve bloccare l'AI;
- dove salvare l'output;
- chi puo' vedere storico e dati.
FlowSharp supporta Data Shield, minimizzazione e Data Gate proprio per evitare automazioni AI non governate.
10. Estensione browser
L'estensione browser permette di avvicinare FlowSharp a portali e strumenti web.
Pattern tipici:
- leggere contesto da una pagina esterna;
- aprire il cockpit FlowSharp;
- collegare una pagina a un item;
- avviare un processo partendo da un sistema web;
- aggiornare o consultare una pratica senza uscire dalla pagina.
Per deploy o demo, conviene preparare un portale o pagina campione con dati coerenti con il tenant FlowSharp.
11. Webhook connector
I webhook connector permettono di gestire integrazioni riusabili invece di configurare URL e segreti ogni volta.
Usali quando:
- piu' flow chiamano lo stesso sistema;
- vuoi centralizzare configurazione e test;
- devi ruotare credenziali;
- vuoi separare logica di processo e dettaglio tecnico dell'integrazione.
API dei webhook connector (Admin)
| Endpoint | Metodo | Uso |
|---|---|---|
/settings/webhook-connectors | GET / POST | Lista e creazione connector. |
/settings/webhook-connectors/:id | PUT / DELETE | Modifica ed eliminazione. |
/settings/webhook-connectors/available | GET | Connector attivi selezionabili nel designer (anche FlowDesigner). |
/settings/webhook-connectors/import-n8n | POST | Import guidato da n8n: accetta URL webhook, URL editor o JSON workflow ({ "input": "...", "name": "..." }, ?preview=true per anteprima senza salvare). L'URL incollato deve appartenere all'istanza n8n configurata nel binding, altrimenti la richiesta viene rifiutata con N8N_HOST_MISMATCH. |
/settings/webhook-connectors/:id/test | POST | Test guidato: invia un payload di prova ({ "payload": {...}, "mode": "test" | "production" }). In modalita' test l'URL usa /webhook-test/ (richiede "Listen for test event" in n8n). |
/settings/webhook-connectors/:id/resync | POST | Risincronizza il connector dal workflow n8n (nome, path, body template); segnala il drift. |
/settings/webhook-connectors/:id/status | PATCH | Governance: draft → validated → deprecated. |
Contratto payload verso n8n
Il body inviato da un task webhook e' composto da item.data piu' l'envelope xflow (per i connector legati a n8n) con itemId, taskInstanceId, taskCode, runId, callbackUrl, flowDefCode e i metadati dell'item. Gli snippet n8n lo leggono dal frame del nodo trigger ($('Webhook').item.json.body.xflow.*); per i webhook generici gli identificativi viaggiano negli header X-XFlow-*.
Snippet n8n
POST /settings/n8n/snippets con { "action": "completeTask" | "completeTaskByCode" | "patchData" | "raiseEvent" | "transition" | "readItem" } restituisce un nodo HTTP Request incollabile in n8n e il curl equivalente, gia' configurati con l'autenticazione giusta per la rotta di destinazione:
completeTaskchiama il bridgePOST /tasks/callbacke si autentica con l'headerx-api-key+ API key di scopen8nBridge;- tutte le altre azioni colpiscono rotte utente e usano un JWT (le chiavi del bridge su quelle rotte non sono accettate e danno 401).
Gli identificativi negli snippet sono sempre presi dal frame del nodo trigger ($('Webhook').item.json...), mai da $json corrente: rinomina il nodo nelle espressioni se il tuo trigger ha un altro nome.
idempotencyKey di raiseEvent: retry e replay sono cose diverse. Lo snippet mostra il placeholder SOURCE_EVENT_ID-your.event.name e va sostituito con un identificativo stabile della sorgente (numero ordine, id documento, id messaggio). Il motivo: l'id di esecuzione n8n ($execution.id) copre solo il retry dello stesso run — se il nodo ritenta, la chiave e' la stessa e l'evento non si duplica. Non copre il replay del workflow: una riesecuzione manuale, un ritrigger della sorgente o un secondo webhook per lo stesso fatto producono un id di esecuzione nuovo, quindi una chiave nuova, quindi lo stesso evento logico entra due volte. Solo un id della sorgente e' stabile fra le due esecuzioni.
⚠️ Se il placeholder non viene sostituito, il workflow gira lo stesso: il primo evento entra, ma dal secondo in poi TUTTE le chiamate con quella chiave letterale vengono deduplicate per sempre (risposta
202condeduplicated: true, l'evento non viene piu' consegnato) — n8n vede un successo e la perdita e' silenziosa.
12. Endpoint principali
Questa tabella e' una mappa di orientamento, non sostituisce Swagger.
| Area | Endpoint principali | Uso |
|---|---|---|
| Auth | /auth/login, /auth/refresh, /auth/logout, /auth/me | Sessione utente. |
| Flow | /flows, /flows/:id, /flows/:id/design, /flows/:id/publish | Catalogo e designer. |
| Process Maps | /process-maps, /process-maps/:id/design, /process-maps/:id/discover-edges, /process-maps/:id/materialize-drafts, /process-maps/:id/copilot, /process-maps/:id/reconcile, /process-maps/:id/edges/:edgeId/wire, /process-maps/:id/activity | Macro-processi, rilevamento connessioni, creazione flussi bozza, Copilot AI, verifica cablaggio, traffico reale. |
| Items | /items, /items/:id, /items/:id/transition, /items/:id/history | Pratiche runtime. |
| Tasks | /tasks, task by item | Task operativi. |
| Trigger | /trigger/:flowCode, API keys | Avvio da sistemi esterni. |
| Events | /events/definitions, /events/raise, subscriber | Eventi e integrazioni. |
| Analytics | /analytics/overview, /analytics/flows/:id, ROI | Metriche e costi. |
| AI | /ai-providers, /ai-assistants | Provider e assistenti. |
| Variables | /variables, /flows/:id/variables | Variabili globali e di flusso. |
| Field registry | /flows/:id/fields | Campi dichiarati, osservati, promozione, ignore e conflitti. |
| Flow views | /flows/:id/views | Vista del team con colonne e ordinamento. |
| Flow KPI | /flows/:id/kpis | Definizioni, contesto, valori, serie, obiettivi e ricalcolo. |
| SOP | /sop, /sop/:id/versions, /sop/:id/coverage | Procedure versionate, copertura e generazione guidata. |
| Automation Plan | /automation-tasks | Iniziative di automazione, stato e verifica del saving. |
| Saving | /process-maps/:id/baselines, /baselines/:id/*, /saving-challenges | Baseline, simulazione, contratti, report ed export. |
| Alerts | /settings/alerts, /settings/alert-policies, /analytics/alerts/response-stats | Policy, finestre orarie e report di risposta. |
| Realtime | /realtime/stream | Segnali live tenant-scoped per riallineare i client. |
| MCP | /mcp-keys, /mcp/sse, /mcp/messages | Agenti esterni. |
| n8n | /settings/n8n, /settings/n8n/test, /settings/n8n/snippets | Binding, health check e snippet incollabili. |
| Webhook connector | /settings/webhook-connectors, /available, /import-n8n, /:id/test, /:id/resync, /:id/status | Integrazioni riusabili: CRUD, import da n8n, test guidato, resync, governance (vedi sez. 11). |
| Extension | /extension/* | Estensione browser e cockpit. |
| Admin | /admin/tenants, /admin/stats | Multi-tenant. |
| Diagnostica | /version | Versione attiva dell'installazione. |
13. Checklist per una buona integrazione
Prima di andare in produzione:
- usa chiavi dedicate per scenario;
- assegna scope minimi;
- abilita retry dove opportuno;
- configura timeout e callback;
- evita payload inutilmente grandi;
- verifica campi sensibili;
- usa idempotenza dove serve;
- testa errori e duplicati;
- monitora task falliti;
- documenta proprietario e scopo dell'integrazione;
- misura impatto in Analytics.
14. Glossario tecnico minimo
| Termine | Significato |
|---|---|
| API key | Chiave usata da un sistema esterno per avviare o completare operazioni. |
| Trigger | Punto di ingresso per creare un item da fuori FlowSharp. |
| Webhook | Chiamata HTTP inviata da FlowSharp a un altro sistema. |
| Callback | Chiamata di ritorno da un sistema esterno a FlowSharp per completare un task. |
| Event | Segnale applicativo che puo' attivare flow o subscriber. |
| Subscriber | Azione collegata alla ricezione di un evento. |
| MCP | Protocollo per far lavorare agenti AI con strumenti e permessi controllati. |
| Data Shield | Protezione dei dati sensibili prima dell'uso AI. |
| Data Gate | Controllo che impedisce al processo di procedere senza dati necessari. |
15. API variabili
Le variabili (globali e di flusso) sono gestibili via API. Consentono di centralizzare soglie, SLA e configurazioni richiamabili nei template con {{global.vars.chiave}} o {{flow.vars.chiave}}.
Variabili globali (ambito tenant):
| Metodo | Path | Uso |
|---|---|---|
GET | /variables | Elenca le variabili globali del tenant. |
POST | /variables | Crea una variabile globale (richiede Admin). |
PUT | /variables/:id | Aggiorna una variabile globale (richiede Admin). |
DELETE | /variables/:id | Elimina una variabile globale (richiede Admin). |
Variabili di flusso (ambito singolo flusso):
| Metodo | Path | Uso |
|---|---|---|
GET | /flows/:id/variables | Elenca le variabili del flusso. |
POST | /flows/:id/variables | Crea una variabile del flusso (richiede FlowDesigner). |
PUT | /flows/:id/variables/:varId | Aggiorna una variabile del flusso (richiede FlowDesigner). |
DELETE | /flows/:id/variables/:varId | Elimina una variabile del flusso (richiede FlowDesigner). |
Struttura del body (POST/PUT):
{
"key": "slaMinuti",
"label": "SLA minuti",
"value": "120",
"type": "number",
"description": "Limite di tempo per l'approvazione"
}
I tipi possibili sono string, number, boolean e secret. Il valore e' sempre una stringa nel database; il tipo governa la validazione in scrittura e il cast in lettura. La chiave deve essere univoca nello stesso ambito (globale o flusso specifico).
L'aggiornamento di una variabile richiede la revisione attesa: il campo intero expectedVersion, che ogni risposta (GET lista, POST, PUT) restituisce come version. Se manca, il server non scrive e risponde 428 VARIABLE_REVISION_REQUIRED con la revisione corrente; se non corrisponde, risponde 409 VARIABLE_VERSION_CONFLICT con currentVersion e currentValue. E' una rottura voluta del contratto precedente: una variabile globale alimenta formule KPI, regole e template di tutto il tenant, e una scrittura alla cieca puo' cancellare in silenzio il valore appena messo da qualcun altro. Il recupero costa un solo giro: rileggi version dalla risposta di errore e ripeti la PUT se la sovrascrittura e' quello che vuoi davvero.
Per le variabili di tipo secret il valore e' cifrato nel database e le risposte API restituiscono solo un valore mascherato. La rivelazione in chiaro e' un'operazione dedicata riservata agli Admin e tracciata nell'audit log; nei log di esecuzione dei task il valore viene redatto automaticamente. In aggiornamento, omettere il valore significa "invariato".
16. Superfici API per dati, KPI e lavoro operativo
Il registro campi espone il contratto dati del Flow:
| Metodo | Path | Uso |
|---|---|---|
GET / POST | /flows/:flowId/fields | Lista o dichiara un campo. |
POST | /flows/:flowId/fields/:path/promote | Promuove un campo osservato. |
POST | /flows/:flowId/fields/:path/ignore | Ignora un campo osservato. |
PATCH / DELETE | /flows/:flowId/fields/:path | Modifica o rimuove un campo dal contratto. |
La vista condivisa si legge da GET /flows/:flowId/views e si sostituisce con PUT /flows/:flowId/views/default. Gli override personali sono impostazioni dell'utente e non cambiano la vista del team.
Le rotte /flows/:flowId/kpis gestiscono definizioni item e Flow. Le sotto-risorse context, values, series, goals, goal e recalc supportano editor, dashboard, storico, previsioni, obiettivi e ricostruzione asincrona. I KPI sensibili dichiarano la dipendenza, ma il consumer non deve assumere che il valore calcolato sia mascherato.
Le procedure usano /sop: versioni, contenuto, copertura dei task, archiviazione/ripristino e generazione di guide. Le iniziative del Piano usano /automation-tasks; baseline e Saving Challenge usano /process-maps/:id/baselines, /baselines/:id/* e /saving-challenges.
17. Concorrenza, paginazione e chiavi
Le API di modifica supportano controlli di revisione per evitare sovrascritture:
- il patch dati dell'item puo' inviare
_expectedDataRevision; - il salvataggio del Flow (
PUT /flows/:id/design) e la modifica dei metadati (PATCH /flows/:id/meta) condividono la stessa guardia: possono inviareexpectedUpdatedAt(ISO diupdatedAt) oppureexpectedRevision(interorevision, forma preferita perche' due scritture nello stesso millisecondo condividerebbero il timestamp). Il conflitto e'409 FLOW_VERSION_CONFLICTconcurrentUpdatedAtecurrentRevision; - l'aggiornamento di una variabile DEVE inviare
expectedVersion(vedi sezione 15); - metadati e design della Process Map inviano rispettivamente la revisione attesa e la versione design attesa.
Se il token non corrisponde alla revisione corrente, il server risponde con conflitto e il client deve rileggere la risorsa prima di decidere come riapplicare la modifica. Non trasformare automaticamente un conflitto in un retry cieco.
Le liste di Task ed Eventi usano paginazione a cursore. Il consumer passa il cursore restituito dalla pagina precedente; l'offset non va ricostruito dal numero di righe, perche' inserimenti concorrenti possono cambiare le posizioni.
GET /flows mantiene invece una risposta array e usa limit + page zero-based,
con metadati negli header X-Total-Count, X-Page, X-Limit e X-Has-More;
offset non e' supportato. Il tool MCP list_flows usa il proprio contratto a
cursore { data, total, hasMore, nextCursor }.
Le API key hanno sempre una scadenza: 90 giorni per default, personalizzabile fino a 365. Usa chiavi diverse per trigger e bridge n8n, assegna lo scope minimo e pianifica la rotazione prima della scadenza.
18. Eventi, alert e aggiornamenti live
Una definizione evento separa il nome visualizzato, modificabile e leggibile, dalla chiave tecnica, stabile dopo la creazione. Ricerca e UI possono usare il nome visualizzato; routing, subscriber e integrazioni devono usare la chiave.
Oltre a timeout, WIP, massimo tentativi e SLA, ogni fase con task puo' esporre:
<codiceFlow>.<codiceStato>.task-completed;<codiceFlow>.<codiceStato>.task-failed.
Questi eventi valgono per task manuali e automatici e possono alimentare subscriber, notifiche o altri Flow. Le soglie e gli obiettivi KPI aggiungono eventi dedicati solo al cambio della relativa condizione.
GET /realtime/stream invia segnali tenant-scoped con identificatori, non payload di business. Il client usa il segnale per invalidare e rileggere le query interessate; deve mantenere un fallback di polling e riconnettersi senza assumere che lo stream sia una coda durabile.
Le policy alert si gestiscono con /settings/alerts e /settings/alert-policies; la presa in carico puo' avvenire tramite endpoint autenticato o link firmato. Le finestre orarie includono un fuso IANA e possono attraversare la mezzanotte.
19. Provider email
FlowSharp invia email in due casi diversi, ed è utile tenerli separati: i messaggi di autenticazione (invito, reset password, link di accesso) e le comunicazioni di processo (notifiche, promemoria, alert). I primi partono sempre dal provider di installazione, quello configurato da chi gestisce il server; i secondi possono partire da un provider del tuo tenant, se ne configuri uno.
Provider di installazione e provider del tenant
Il provider di installazione è unico per tutta l'installazione e non è modificabile dalla Gestione: la pagina lo mostra in sola lettura, con lo stato «Configurato» o «Non configurato». Serve come canale di base e come fallback.
I provider del tenant si aggiungono da Gestione → Provider email. Puoi averne più d'uno: quello con priorità più alta viene provato per primo, gli altri fanno da riserva se l'invio fallisce. Se non configuri alcun provider del tenant, le email di processo usano quello di installazione. Se non c'è né l'uno né l'altro, non esiste alcun canale di invio e nessuna email parte: la pagina te lo dice esplicitamente invece di lasciartelo scoprire da un promemoria mai arrivato.
Tipi supportati e cosa serve a ciascuno
- SMTP — host e porta (587 per STARTTLS, 465 per TLS implicito), più le credenziali se il server le richiede. La casella «connessione sicura» va spuntata per la 465; sulla 587 la cifratura si negozia dopo la connessione ed è il caso più comune.
- Mailgun — il dominio verificato sulla console Mailgun e la regione dell'account,
usoeu. La regione sbagliata produce un errore di autenticazione anche con la chiave giusta, perché le due regioni sono installazioni separate. - SendGrid — solo la chiave API.
- ZeptoMail — la zona dell'account:
.com,.euo.in. Vale la stessa avvertenza della regione Mailgun. - API — un endpoint HTTP tuo, tipicamente un webhook n8n, che riceve il messaggio e lo consegna come preferisci. Utile quando l'invio deve passare da un sistema che già possiedi.
Il dominio mittente va verificato
Mailgun, SendGrid e ZeptoMail rifiutano l'invio da domini non verificati. La verifica si fa sulla console del provider, non qui: si tratta di aggiungere i record DNS che il provider indica e attendere la propagazione. Finché il dominio non è verificato l'invio fallisce con un errore che sembra un difetto di FlowSharp e non lo è — per questo la pagina mostra un avviso quando scegli uno di quei tre tipi.
L'indirizzo mittente deve appartenere a un dominio verificato. Il nome mittente è facoltativo e serve solo a rendere leggibile chi scrive.
Credenziali
La credenziale (password SMTP o chiave API) si scrive una volta sola e non è più rileggibile: viene cifrata e la pagina mostra un segnaposto al suo posto. Se modifichi un provider senza toccare quel campo, la credenziale resta quella di prima; per sostituirla, scrivi il valore nuovo.
Template e priorità
L'opzione «usa il template» avvolge il messaggio nella grafica di FlowSharp — intestazione, piè di pagina, colori del tenant. Disattivandola il corpo del messaggio viene inviato così com'è: utile quando il contenuto arriva già formattato da un altro sistema.
Quando ci sono più provider attivi, l'ordine di tentativo segue la priorità. Un provider disattivato viene saltato senza essere provato.
Il test di invio
Il pulsante di test accoda un messaggio reale verso l'indirizzo mittente configurato: non è una simulazione. L'esito compare sul provider una volta che il messaggio è stato preso in carico, quindi può richiedere qualche secondo. Un test riuscito dice che la configurazione è valida e che il provider ha accettato il messaggio; non garantisce la consegna, che dipende anche da reputazione del dominio e filtri del destinatario.
20. Estensione self-service, federation v2 e break-glass MCP
L'estensione non richiede più uno zip preparato a mano. Un utente autenticato apre Gestione → Estensione, scarica il bundle versionato già configurato per l'origin corrente, lo estrae e usa Carica estensione non pacchettizzata in Chrome. Una scelta manuale dell'origin già salvata non viene sovrascritta.
L'accettazione federation fra installazioni usa protocollo v2. Il backend CASA registra POST /memberships/accept-remote/intents, conserva solo l'hash del token e restituisce uno snapshot; il browser rimuove token e client dalla cronologia. La consumazione invia { intentId, token }, usa lease e replay idempotente ed esige che l'email verificata coincida con quella invitata. Peer v1: 426 FEDERATION_PROTOCOL_UPGRADE_REQUIRED; identità diversa: 403 INVITED_IDENTITY_MISMATCH.
Per il recupero amministrativo MCP usare force_transition con itemId, toStatusId e reason. Il tool è presente solo per chiavi Admin e rispetta allowedFlows. Non aggiungere parametri force a transition_item: quel tool conserva routing, WIP e gate ordinari.
