API Reference / Workflow

Workflow

I workflow automatizzano azioni al verificarsi di un evento o su base pianificata. Le esecuzioni sono gestite da una coda affidabile con retry e dead-letter; questi endpoint ne coprono la configurazione e le operazioni.

Solo amministratori

Tutti gli endpoint dei workflow richiedono il ruolo amministratore (requireAdminRole). Un utente autenticato ma non admin riceve 403. Vedi le convenzioni per envelope ed errori; ogni richiesta richiede l'header Authorization: Bearer <accessToken>.

01L'oggetto Workflow

Un workflow è composto da tre parti: un trigger (evento on_create / on_update su un modulo, oppure time_based pianificato), un insieme di condizioni (le stesse dei filtri, valutate in AND/OR) e una lista di azioni eseguite in ordine. La struttura completa si legge da GET /:id. Le date sono stringhe ISO 8601 in UTC.

AttributoTipoDescrizione
idintegerIdentificativo univoco del workflow.
namestringNome del workflow. 1–150 caratteri.
moduleKeystringModulo bersaglio: accounts, contacts, leads, deals, activities, notes.
triggerstringon_create, on_update o time_based.
isActivebooleanSe false, il workflow non scatta sugli eventi.
descriptionstring | nullDescrizione libera. Max 1000 caratteri.
conditionLogicstringCome combinare le condizioni: and (default) o or.
triggerConfigobjectOpzioni del trigger, es. changedFields per on_update.
scheduleConfigobjectPianificazione per i trigger time_based.
conditionsarrayElenco di condizioni (max 25).
actionsarrayElenco di azioni (1–10, eseguite in ordine di position).
createdByinteger | nullUtente che ha creato il workflow.
updatedByinteger | nullUltimo utente che l'ha modificato.
createdAtstringData/ora di creazione (ISO 8601).
updatedAtstringData/ora ultima modifica (ISO 8601).
L'oggetto Condizione
CampoTipoNote
columnKeystringrichiestoColonna/campo da valutare. Max 80 caratteri.
operatorstringrichiestoOperatore di confronto (gli stessi dei filtri avanzati, es. eq, is_null).
valueanycondizionaleValore di confronto. Richiesto tranne che per is_null.
valueTypestringopzionaletext (default), integer, number, date, enum, boolean.
positionintegeropzionaleOrdine di valutazione.
L'oggetto Azione
CampoTipoNote
actionTypestringrichiestoTipo di azione. Deve corrispondere a un runner registrato (es. crea record, aggiorna campo, invia email, webhook). Max 60 caratteri.
actionConfigobjectopzionaleConfigurazione specifica dell'azione. Default {}.
positionintegeropzionaleOrdine di esecuzione.
json · l'oggetto Workflow
{
  "id": 12,
  "name": "Assegna nuovi lead al team vendite",
  "moduleKey": "leads",
  "trigger": "on_create",
  "isActive": true,
  "description": "Crea un task di follow-up quando arriva un lead.",
  "conditionLogic": "and",
  "triggerConfig": {},
  "scheduleConfig": {},
  "conditions": [
    { "columnKey": "status", "operator": "eq", "value": "nuovo", "valueType": "text", "position": 0 }
  ],
  "actions": [
    { "actionType": "create_activity", "actionConfig": { "subject": "Chiamare il lead" }, "position": 0 }
  ],
  "createdBy": 7,
  "updatedBy": 7,
  "createdAt": "2026-07-07T15:24:00.000Z",
  "updatedAt": "2026-07-07T15:24:00.000Z"
}

02Configurazione

MetodoPathCosa fa
GET/api/workflowsElenco dei workflow.
GET/api/workflows/:idUn singolo workflow con trigger, condizioni e azioni.
POST/api/workflowsCrea un workflow.
PATCH/api/workflows/:idModifica (incluso attivazione/disattivazione).
DELETE/api/workflows/:idElimina.
POST/api/workflows/:id/run-nowEsegue subito il workflow su un record.
POST/api/workflows/:id/dry-runSimula l'esecuzione su un record senza applicare effetti.

03Elencare i workflow

GET /api/workflows admin richiesto

Restituisce tutti i workflow. Opzionalmente filtra per modulo.

Parametri query
ParametroTipoDescrizione
modulestringopzionaleFiltra per moduleKey (es. leads).
Richiesta
curl "https://crm.tuodominio.it/api/workflows?module=leads" \
  -H "Authorization: Bearer <accessToken>"
const res = await fetch("https://crm.tuodominio.it/api/workflows?module=leads", {
  headers: { Authorization: `Bearer ${accessToken}` },
});
const { data } = await res.json();
Risposta · 200
json
{
  "success": true,
  "data": {
    "items": [ { "id": 12, "name": "Assegna nuovi lead…", "moduleKey": "leads", "isActive": true,  } ]
  }
}
Esiti
StatoCorpo
200{ success: true, data: { items: […] } }
401UNAUTHORIZED: token assente o scaduto.
403FORBIDDEN: l'utente non è amministratore.

04Creare un workflow

POST /api/workflows admin richiesto
Parametri body
CampoTipoNote
namestringrichiesto1–150 caratteri.
moduleKeystringrichiestoUno tra accounts, contacts, leads, deals, activities, notes. Accetta anche l'alias module.
triggerstringrichiestoon_create, on_update o time_based.
actionsarrayrichiestoAlmeno 1, massimo 10 azioni.
conditionsarrayopzionaleMassimo 25 condizioni. Default vuoto.
conditionLogicstringopzionaleand (default) o or.
triggerConfigobjectopzionaleEs. { "changedFields": ["status"] }.
scheduleConfigobjectopzionalePianificazione per time_based.
descriptionstringopzionaleMax 1000 caratteri.
isActivebooleanopzionaleDefault true.
Richiesta
curl -X POST https://crm.tuodominio.it/api/workflows \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Follow-up lead", "moduleKey": "leads", "trigger": "on_create", "actions": [{ "actionType": "create_activity", "actionConfig": { "subject": "Chiamare il lead" } }] }'
const res = await fetch("https://crm.tuodominio.it/api/workflows", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${accessToken}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Follow-up lead", moduleKey: "leads", trigger: "on_create",
    actions: [{ actionType: "create_activity", actionConfig: { subject: "Chiamare il lead" } }],
  }),
});
const { data } = await res.json();
Esiti
StatoCodiceQuando
201·Creato; in data.item l'oggetto completo.
422VALIDATION_ERRORCampo mancante/fuori misura, trigger o modulo non valido, nessuna azione, o actionType non registrato.
403FORBIDDENL'utente non è amministratore.

05Modificare ed eliminare

PATCH/api/workflows/:idadmin richiesto

Modifica parziale: invia solo i campi da cambiare (gli stessi del body di creazione, tutti opzionali; almeno uno è richiesto). Attivare/disattivare un workflow è un PATCH con { "isActive": false }. Se invii conditions o actions, l'array sostituisce quello esistente.

curl
curl -X PATCH https://crm.tuodominio.it/api/workflows/12 \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "isActive": false }'

Risponde 200 con { data: { item } }, 422 in validazione, 403 per i non-admin.

DELETE/api/workflows/:idadmin richiesto

Elimina il workflow. Risponde 200 con { success: true, data: { id } }.

06Esecuzione manuale

POST /api/workflows/:id/run-now admin richiesto

Accoda subito il workflow per un record specifico, ignorando il trigger. Le azioni vengono eseguite dal worker; la risposta riporta l'id del job accodato.

Parametri path
ParametroTipoDescrizione
idintegerId del workflow.
Parametri body
CampoTipoNote
recordIdintegerrichiestoId del record del modulo su cui eseguire il workflow.
Richiesta
curl -X POST https://crm.tuodominio.it/api/workflows/12/run-now \
  -H "Authorization: Bearer <accessToken>" \
  -H "Content-Type: application/json" \
  -d '{ "recordId": 843 }'
const res = await fetch("https://crm.tuodominio.it/api/workflows/12/run-now", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${accessToken}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ recordId: 843 }),
});
const { data } = await res.json();
Risposta · 200
json
{ "success": true, "data": { "jobId": 5120,  } }
Esiti
StatoCodiceQuando
200·Job accodato; in data.jobId il riferimento.
400VALIDATION_ERRORrecordId mancante o non intero positivo.
403FORBIDDENL'utente non è amministratore.

07Osservabilità e operazioni

MetodoPathCosa fa
GET/api/workflows/operations/statusStato di coda, scheduler e statistiche di esecuzione.
GET/api/workflows/execution-logsLog delle esecuzioni (successi, retry, dead-letter).
GET/api/workflows/diagnosticsDiagnostica dei fallimenti ricorrenti.

execution-logs accetta i parametri query limit, offset, workflowId e status. Tutti e tre gli endpoint rispondono 200 con l'envelope standard e 403 ai non-admin.

08Dead-letter

Un job che fallisce oltre i tentativi previsti finisce in dead-letter: non viene perso, resta lì per l'ispezione e il rilancio manuale.

MetodoPathCosa fa
GET/api/workflows/dead-letter-jobsElenco dei job falliti definitivamente (con stats della coda).
POST/api/workflows/dead-letter-jobs/:jobId/retryRilancia un job.
POST/api/workflows/dead-letter-jobs/purgeSvuota la coda dead-letter (opzionale workflowId per limitare).
Nota · Riprendi vs Da capo

Il retry di un job può riprendere saltando le azioni già completate (riprendi, default) oppure ripartire dall'inizio azzerando il registro delle azioni eseguite ({ "fromScratch": true }). La scelta evita di duplicare effetti collaterali come email o task già inviati.

Esiti · retry
StatoCodiceQuando
200·Job rilanciato; in data.item il job aggiornato.
400VALIDATION_ERRORjobId non intero positivo.
403FORBIDDENL'utente non è amministratore.