Salta al contenuto

Integrazioni, contratto pubblico

Ti serve sapere come si usa l’app ogni giorno? Apri la Guida utente. Questa pagina è il contratto tecnico. Copre i lead in ingresso, i webhook firmati e MCP per gli assistenti, con una mappa di posta, WhatsApp e link pubblico del preventivo. Le chiavi le creano owner e admin in Impostazioni → Integrazioni. Qui trovi URL, header, JSON, HMAC, retry e catalogo eventi.

Ingresso

POST JSON → lead

Form, ads, Zapier, Make o n8n. Una chiave con permesso lead:write.

curl · lead in ingresso
curl -X POST 'https://app.kreoquotes.com/v1/integrations/public/leads' \
  -H 'Content-Type: application/json' \
  -H 'X-KREO-API-Key: kreo_YOUR_API_KEY' \
  -H 'Idempotency-Key: lead-unique-id-123' \
  -d '{"customer_name":"Mario Rossi","customer_email":"[email protected]"}'
Uscita

Evento → webhook HMAC

KREO chiama il tuo HTTPS. Verifica X-KREO-Signature sul body grezzo.

headers · consegna
X-KREO-Event-Id: evt_…
X-KREO-Event-Type: lead.created
X-KREO-Event-Origin: api
X-KREO-Timestamp: 1730000000
X-KREO-Signature: sha256=…
Base URL https://app.kreoquotes.com Header chiave X-KREO-API-Key Prefisso token kreo_

Cosa sono le integrazioni

In KREO non trovi un marketplace di app native per HubSpot, Slack App Store o gestionali proprietari. Colleghi i sistemi esterni in modi che puoi verificare: REST con chiave API, webhook HTTPS firmati e MCP per Claude e Cursor. Poi ci sono i canali del prodotto, cioè posta, webmail, WhatsApp e link pubblico del preventivo. Stanno in altre parti dell’app e rientrano comunque nel perimetro integrazioni.

Dove si configura cosa

Area Menu in app Chi può
Hub API, webhook, connettori, registro Impostazioni → Integrazioni Owner e admin
Chiavi lead e MCP Impostazioni → Integrazioni → API key avanzate Owner e admin
Webhook Impostazioni → Integrazioni → Webhook personalizzati Owner e admin
Posta OAuth o IMAP/SMTP Impostazioni → Posta Chi ha permesso Posta in scrittura
WhatsApp Business Impostazioni → Posta → WhatsApp Business Stesso + licenza WhatsApp
Uso posta e webmail Comunicazioni → Posta (tab Webmail) Utenti con modulo Posta
Uso WhatsApp Comunicazioni → WhatsApp Utenti con Posta e WhatsApp in licenza
Link pubblico preventivo Editor preventivo → Invio Chi gestisce preventivi
Accettazione OTP/firma Impostazioni → Preventivi Chi configura preventivi
MCP in Claude/Cursor Impostazioni → Integrazioni (snippet dopo creazione chiave) Owner e admin
AI tenant Impostazioni → AI Secondo permessi AI
Export CSV Azioni negli elenchi Clienti, Articoli, Preventivi Secondo permessi modulo

Quattro famiglie

Ingresso dati: form, ads e Zapier/Make/n8n mandano i lead in POST con una chiave lead:write. Se ti serve, puoi anche leggerli con lead:read.

Uscita eventi: webhook verso gli URL che registri. Puoi filtrare per tipo di evento, oppure lasciare la lista vuota e ricevere tutto ciò che è consegnabile.

Assistenti MCP: protocollo streamable HTTP su /v1/mcp, autenticazione Bearer con chiave MCP e un utente collegato.

Canali e cliente finale: posta, webmail, WhatsApp e pagina pubblica /p/{token} non sostituiscono le API qui sopra. Quando uno stato cambia in KREO, generano comunque eventi di dominio, per esempio preventivo accettato.

Nota sui connettori in dashboard. Le schede Form sito web, Landing & ads, Zapier/Make, Slack, CRM esterno, Google Sheets ed ERP precompilano nomi, permessi e tipi evento. Sotto c’è sempre una chiave API, un webhook o tutti e due. Slack non verifica la firma HMAC. Se ti serve, filtra in un passaggio intermedio. L’ERP emette erp.quote.export. Da dashboard puoi lanciare anche un export manuale, che entra nello stesso flusso eventi. Una sync bidirezionale nativa con i gestionali non esiste.

Chiavi API

Una chiave si crea solo dalla dashboard. Il token in chiaro compare una volta, alla creazione. Poi resta solo un elenco (nome, permessi, attiva/revocata). Se lo perdi, revoca e creane un’altra: la revoca è definitiva.

  1. Apri KREO → Impostazioni → Integrazioni.
  2. Crea una chiave, assegna un nome e i permessi necessari.
  3. Copia il token (inizia con kreo_) e conservalo nel secret store del tuo runtime, non nel codice.
  4. Invialo in ogni richiesta pubblica come header X-KREO-API-Key.

Permessi

lead:write
Inserire lead con POST /v1/integrations/public/leads.
lead:read
Elenco, dettaglio e definizioni campi: GET /v1/integrations/public/leads e rotte collegate.

Una chiave può avere uno o entrambi i permessi. Senza il permesso richiesto la risposta è 403 con codice scope_required. Header assente: 401 api_key_required. Token sbagliato o revocato: 401 invalid_api_key.

Limiti

Per chiave, a finestra fissa di 60 secondi (valori di default): circa 60 scritture e 120 letture. I due contatori sono separati, così una sync in lettura non brucia il budget dei form. In caso di superamento: 429 e header Retry-After.

Per collegare Claude o Cursor ci sono anche i permessi mcp:read e mcp:write. Richiedono un utente collegato alla chiave e seguono i permessi di modulo di quell’utente. Dettagli, elenco dei tool ed esempi di configurazione li trovi più sotto, nella sezione MCP.

MCP per assistenti esterni

Endpoint pubblico: https://app.kreoquotes.com/v1/mcp
Protocollo: MCP over HTTP streamable, quello usato dai client Claude Desktop e Cursor.

Autenticazione

Header Authorization: Bearer kreo_YOUR_API_KEY
La chiave deve avere mcp:read, mcp:write o entrambi. Deve anche essere collegata a un utente KREO attivo del tenant. Se non colleghi un utente, la dashboard non crea la chiave. Il tenant è sempre quello della chiave e non puoi indicarne un altro.

Permessi

mcp:read
Tool di sola lettura e whoami.
mcp:write
Tool di scrittura, proposte massive e conferma azioni.

Contano i permessi di modulo dell’utente collegato. Una chiave MCP non bypassa RBAC.

Tool disponibili

Tool Descrizione
whoamiMostra utente collegato, tenant, scope chiave e moduli effettivi.
cerca_clientiCerca clienti per testo, restituisce id sintetici.
leggi_clienteDettaglio cliente per id.
cerca_articoliCerca nel catalogo articoli.
leggi_articoloDettaglio articolo per id.
cerca_preventiviElenca preventivi con filtri opzionali.
leggi_preventivoDettaglio preventivo con righe.
cerca_fornitoriCerca fornitori.
leggi_fornitoreDettaglio fornitore.
cerca_leadCerca lead CRM.
leggi_leadDettaglio lead.
cerca_ordini_acquistoElenca ordini d’acquisto.
leggi_ordine_acquistoDettaglio ordine d’acquisto.
timeline_comunicazioni_clienteEmail e messaggi recenti sul cliente.
cerca_bozze_emailBozze email salvate.
leggi_bozza_emailContenuto bozza per id messaggio.
crea_clienteCrea anagrafica cliente.
aggiorna_clienteAggiorna campi cliente.
crea_articoloCrea articolo a catalogo.
aggiorna_articoloAggiorna articolo.
crea_fornitoreCrea fornitore.
aggiorna_fornitoreAggiorna fornitore.
crea_leadCrea lead.
aggiorna_leadAggiorna lead.
crea_preventivoCrea testata preventivo.
aggiungi_riga_preventivoAggiunge riga.
aggiorna_riga_preventivoModifica riga.
rimuovi_riga_preventivoElimina riga.
aggiorna_testata_preventivoModifica campi testata.
imposta_stato_preventivoTransizione di stato ammessa.
salva_bozza_emailSalva bozza email collegata a cliente.
invia_preventivoPropone invio preventivo (richiede conferma).
invia_emailPropone invio email (richiede conferma).
invia_whatsappPropone messaggio WhatsApp (richiede conferma).
aumenta_prezzi_massivoPropone aumento percentuale prezzi catalogo (richiede conferma).
importa_da_filePropone import bulk da JSON righe (richiede conferma).
conferma_azioneEsegue una proposta pendente dopo conferma esplicita.

Le operazioni segnate come proposta restano ferme finché non chiami conferma_azione con l’id della proposta. L’AI in app si comporta allo stesso modo.

Esempio Claude (connettore custom)

Claude · connettore custom
URL: https://app.kreoquotes.com/v1/mcp
Header:
  Authorization: Bearer kreo_YOUR_API_KEY

Apri Claude → Impostazioni → Connettori → Aggiungi connettore custom e inserisci URL e header qui sopra. Usa una chiave creata in KREO con scope MCP e utente collegato.

Esempio Cursor (mcp.json)

Cursor · mcp.json
{
  "mcpServers": {
    "kreo": {
      "url": "https://app.kreoquotes.com/v1/mcp",
      "headers": {
        "Authorization": "Bearer kreo_YOUR_API_KEY"
      }
    }
  }
}

Il token in chiaro lo vedi una sola volta, quando crei la chiave in dashboard. Conservalo in un posto sicuro sul client e non incollarlo in file pubblici del tuo progetto.

Inviare un lead

POST https://app.kreoquotes.com/v1/integrations/public/leads

Crea un lead nello stato new. Emette lead.created (e, per compatibilità, l’alias lead.received solo verso chi lo ha sottoscritto per nome). La risposta è l’evento inbound, non un oggetto “Lead” nudo: contiene id, event_type, payload, status.

Corpo JSON

customer_name
Obbligatorio. 1–200 caratteri. Diventa nome e ragione sociale del lead.
customer_email
Opzionale. Email valida, max 254.
customer_phone
Opzionale. Max 40 caratteri.
message
Opzionale. Note, max 5000. Tipicamente il messaggio del form.
source
Canale. Default api, max 80. Es. sito-web.
external_ref
Opzionale. Id lato tuo (form, ads). Max 120. Utile in coppia con l’idempotenza.
project_name
Opzionale. Conservato nei campi aggiuntivi del lead.

Idempotenza

Header opzionale Idempotency-Key. Stessa chiave, stesso tenant: KREO non ricrea il lead e restituisce l’evento già registrato. Usalo sui retry del form o dell’automazione. Senza header, ogni POST è un lead nuovo.

fetch · browser o Node
await fetch('https://app.kreoquotes.com/v1/integrations/public/leads', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-KREO-API-Key': 'kreo_YOUR_API_KEY',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    customer_name: 'Mario Rossi',
    customer_email: '[email protected]',
    customer_phone: '+39 333 1234567',
    message: 'Richiesta preventivo per ristrutturazione',
    source: 'sito-web',
    project_name: 'Bagno primo piano',
  }),
})

Leggere i lead

Serve il permesso lead:read. I filtri coincidono con quelli della sezione Lead in dashboard: se confronti i due elenchi, devono combaciare.

GET …/public/leads
Elenco impaginato. Query: status, q, stale_days (1–365), assigned (none, any o id utente), source, converted, limit (1–200, default 50), offset. Risposta: items, count, has_more.
GET …/public/leads/{id}
Dettaglio. Un id di un altro tenant risponde 404 lead_not_found, non 403.
GET …/public/lead-fields
Definizioni dei campi aggiuntivi del tenant (anche disattivati: i valori già scritti restano sui lead).

Ogni lead ha la stessa forma in lettura e nei webhook: id, anagrafica, status, assegnatario, note, conversione, timestamp, custom_fields e custom_field_labels.

curl · lettura
curl -G 'https://app.kreoquotes.com/v1/integrations/public/leads' \
  -H 'X-KREO-API-Key: kreo_YOUR_API_KEY' \
  --data-urlencode 'status=new' \
  --data-urlencode 'assigned=none' \
  --data-urlencode 'stale_days=7' \
  --data-urlencode 'limit=50'

curl 'https://app.kreoquotes.com/v1/integrations/public/leads/LEAD_ID' \
  -H 'X-KREO-API-Key: kreo_YOUR_API_KEY'

curl 'https://app.kreoquotes.com/v1/integrations/public/lead-fields' \
  -H 'X-KREO-API-Key: kreo_YOUR_API_KEY'

Webhook in uscita

In Impostazioni → Integrazioni registri un URL HTTPS, scegli i tipi di evento (lista vuota = tutti, tranne gli alias storici) e ricevi un segreto HMAC una sola volta. Poi si può solo ruotare: la rotazione invalida il segreto precedente.

KREO fa POST con JSON e questi header:

Content-Type
application/json
X-KREO-Event-Id
Id dell’evento. Usalo come chiave di deduplica.
X-KREO-Event-Type
Es. quote.accepted
X-KREO-Event-Origin
app (utente in dashboard), api (scrittura da chiave), system (lavoro interno). Scarta api se l’automazione ha appena scritto lei, per non ciclare.
X-KREO-Timestamp
Unix epoch in secondi, incluso nella firma.
X-KREO-Signature
sha256= seguito dall’hex HMAC-SHA256 di {timestamp}.{raw_body}.

Busta JSON

json · envelope
{
  "id": "evt_01234567-89ab-cdef-0123-456789abcdef",
  "event_type": "lead.created",
  "tenant_id": "ten_YOUR_TENANT",
  "created_at": "2026-08-23T15:04:05+00:00",
  "origin": "api",
  "data": {
    "lead_id": "lead_YOUR_LEAD_ID",
    "source": "sito-web",
    "external_ref": "form-42",
    "origin_detail": "public_api",
    "lead": {
      "id": "lead_YOUR_LEAD_ID",
      "full_name": "Mario Rossi",
      "email": "[email protected]",
      "status": "new"
    }
  }
}

Verifica la firma sul body grezzo della richiesta, non su un JSON ri-serializzato. Rispondi 2xx entro 10 secondi. Qualsiasi altro status o un timeout conta come fallimento.

python · verifica HMAC
import hmac
import hashlib

def verify_kreo_signature(secret: str, timestamp: str, body: bytes, header: str) -> bool:
    expected = hmac.new(
        secret.encode("utf-8"),
        f"{timestamp}.".encode("utf-8") + body,
        hashlib.sha256,
    ).hexdigest()
    provided = header.removeprefix("sha256=")
    return hmac.compare_digest(expected, provided)
node · verifica HMAC
import { createHmac, timingSafeEqual } from 'node:crypto'

export function verifyKreoSignature(secret, timestamp, rawBody, header) {
  const expected = createHmac('sha256', secret)
    .update(`${timestamp}.`)
    .update(rawBody)
    .digest('hex')
  const provided = String(header || '').replace(/^sha256=/, '')
  const a = Buffer.from(expected, 'utf8')
  const b = Buffer.from(provided, 'utf8')
  return a.length === b.length && timingSafeEqual(a, b)
}

Catalogo eventi

Nel webhook ti iscrivi agli eventi per nome. Se lasci la lista vuota ricevi tutti i tipi consegnabili, esclusi gli eventi interni AI. Gli eventi AI (ai.proposed_action.* e simili) restano interni e sui webhook non escono mai.

Alias legacy: per i lead arrivati dall’endpoint pubblico, lead.received è un doppione di lead.created. Lo riceve solo chi lo sottoscrive esplicitamente. Se ascolti «tutto» senza filtri, ricevi un solo evento per ogni nuovo lead.

Preventivi legacy: quote.reverted resta consegnabile. Per le nuove integrazioni usa quote.revised, che lo sostituisce.

Lead

  • lead.created Ogni nuovo lead, da form, API o dashboard
  • lead.received Alias storico, solo lead da POST pubblico
  • lead.updated Modifica che non cambia stadio né assegnatario
  • lead.status_changed Cambio di stadio nella pipeline lead
  • lead.assigned Assegnazione o rilascio
  • lead.deleted Eliminazione, payload con ultima fotografia completa
  • lead.converted Il lead è diventato cliente

CRM

  • opportunity.stage_changed L’opportunità è passata a un’altra colonna della pipeline
  • crm_task.created Attività con scadenza creata (promemoria, richiamata)
  • crm_task.completed Attività segnata come completata

Preventivi

  • quote.created Preventivo creato
  • quote.confirmed Preventivo confermato internamente
  • quote.sent Preventivo inviato al cliente
  • quote.accepted Preventivo accettato (anche via link pubblico /p/)
  • quote.rejected Preventivo rifiutato
  • quote.expired Preventivo scaduto
  • quote.cancelled Preventivo annullato
  • quote.revised Aperta nuova revisione collegata
  • quote.reverted Riportato in bozza (legacy, preferisci quote.revised)

Ordini d’acquisto

  • purchase_order.created Ordine creato
  • purchase_order.sent Ordine inviato al fornitore
  • purchase_order.confirmed Ordine confermato
  • purchase_order.received Ordine ricevuto
  • purchase_order.cancelled Ordine annullato

ERP

  • erp.quote.export Richiesta export verso gestionale (evento, non connettore nativo)

Retry, stati, registro

Ogni consegna webhook crea un evento in uscita tracciato. In Impostazioni → Integrazioni → Log eventi vedi tipo, stato, tentativi, ultimo codice HTTP e messaggio di errore. Un evento outbound fallito lo puoi rimettere in coda, anche se è finito in dead letter.

Gli eventi inbound, per esempio un lead appena arrivato via API, compaiono nel registro. Verso l’esterno non si «ri-consegnano», perché descrivono una ricezione già avvenuta.

pending retry delivered dead_letter processed

Retry: fino a 6 tentativi per endpoint, con backoff esponenziale. Si parte da 30 secondi e tra un tentativo e l’altro non passa mai più di un’ora. Il timeout HTTP verso il tuo URL è di 10 secondi.

Nessun subscriber: se nessun webhook attivo è iscritto a quell’evento, lo stato può risultare delivered con dettaglio no_subscribers. Il tuo server non ha sbagliato niente.

Header anti-loop: ogni consegna include X-KREO-Event-Origin (app, api, system), così sai da dove parte.

Posta, webmail e WhatsApp

Per collegare le caselle, firmare i messaggi e usare la webmail ogni giorno apri la Guida utente. Qui trovi solo requisiti e confini.

Posta (Google, Microsoft, IMAP/SMTP manuale)

Serve il modulo di licenza Posta webmail. Si configura in Impostazioni → Posta e si usa in Comunicazioni → Posta. Per OAuth la piattaforma KREO deve aver completato il consenso con Google o Microsoft. Lo scope è per azienda o per utente, secondo l’impostazione del tenant.

Webmail Roundcube

È la tab Webmail in Comunicazioni → Posta. Se la webmail Roundcube è installata nel tuo ambiente, entri con SSO dalla sessione KREO. Prima devi aver collegato una casella in Posta.

WhatsApp Business (Meta Cloud API)

Servono la licenza Posta webmail e la licenza WhatsApp. Si configura in Impostazioni → Posta → WhatsApp Business e si usa in Comunicazioni → WhatsApp. Colleghi token Meta, phone number id e verify token del webhook. Meta manda i messaggi inbound a KREO, che verifica la firma hub.

AI sulla posta

È un modulo AI posta a parte e dipende da Assistente AI e Posta. Non espone webhook. Trovi i dettagli nella Guida e in Impostazioni → AI.

Ricette in dashboard

I connettori in Impostazioni non sono OAuth verso HubSpot o Slack App Store. Precompilano nome, permessi e tipi di evento. Il meccanismo resta questo contratto.

Form sito web
Chiave lead:write + POST JSON dal form o dal backend della landing.
Landing & ads
Meta / Google / Typeform → passo HTTP di Zapier, Make o n8n → stesso POST.
Zapier / Make / n8n
Trigger “Webhook”: incolla l’URL Catch Hook in KREO. Lista eventi vuota = tutto.
Slack
Incoming Webhook Slack. Default: lead.created, quote.sent, quote.accepted. Slack non verifica HMAC: filtra in un passo intermedio se ti serve.
CRM / Sheets
Endpoint HTTPS del CRM, o Webhook → riga su foglio. Verifica la firma se il ricevente può.
ERP / gestionale
Stesso webhook su quote.accepted e erp.quote.export. Non è un connettore SAP/TeamSystem nativo.

Volutamente fuori da questa pagina

  • Token, segreti HMAC, credenziali tenant, chiavi di produzione.
  • Rotte autenticate a sessione (creazione chiavi, rotazione segreti, export ERP): si usano dalla dashboard, non da script pubblici.
  • Eventi AI interni, non consegnabili.
  • ?legacy=1 sull’ingresso lead: crea un cliente invece di un lead. Non usarlo per integrazioni nuove.

Limiti noti

  • Rate limit API lead: per chiave, su una finestra di 60 secondi. Di default circa 60 scritture e 120 letture, contate separatamente. Se superi il limite ricevi 429 con Retry-After.
  • Webhook: solo HTTPS. Timeout di 10 secondi e fino a 6 retry. Il payload è firmato e per verificare l’HMAC usi il body grezzo.
  • MCP: usa la chiave del tenant e richiede un utente. Operazioni massive e invii passano da conferma_azione. Lo storico resta quello esposto in app.
  • Slack Incoming Webhook: lato Slack nessuno verifica la firma KREO. Se ti serve, metti un filtro intermedio.
  • CRM e Google Sheets: si collegano con webhook HTTPS o con Zapier/Make in mezzo, non con connettori OAuth nativi in KREO.
  • ERP: c’è l’evento erp.quote.export con webhook verso il tuo endpoint. Oggi KREO non ha connettori nativi SAP, TeamSystem o Zucchetti.
  • Import strutturato: in UI non c’è un upload CSV generico. L’import passa dall’assistente AI o dal tool MCP importa_da_file, con conferma.
  • Export CSV: lo fai dalla selezione negli elenchi in app. Questa pagina non documenta un export via API pubblica.
  • Notifiche push: richiedono sottoscrizione del browser da parte dell’utente quando la funzione è attiva sulla piattaforma.
  • App mobile: è una PWA installabile dal browser su /m, con sync offline limitato.
  • Attività CRM con scadenza: generano crm_task.created e crm_task.completed, utili per promemoria esterni via webhook.

Pronto a collegare il primo form?

Crea la chiave in dashboard, incolla lo snippet, tieni d’occhio il registro consegne. Se stai valutando KREO, una demo mostra l’hub integrazioni sul tuo flusso reale.