Logistivo CLI: gestisci la tua operatività logistica dal terminale e dal tuo ERP
Un unico catalogo di comandi alimenta tre superfici: il client da terminale lg, l'assistente IA all'interno della dashboard e il canale a cui si collegano gli assistenti IA esterni. Una funzionalità viene scritta una sola volta e compare in tutte e tre — e ora ogni azione di scrittura del pannello ha un comando, quindi i tuoi script e i tuoi agenti IA possono svolgere il lavoro che il tuo team fa a schermo. Pagamenti, consensi legali e chiusura dell'account restano deliberatamente nel browser. Questa pagina è un contratto. La tabella dei comandi qui sotto non è scritta a mano: viene generata dal registro live dei comandi a ogni richiesta.
Che cos'è la Logistivo CLI?
La Logistivo CLI (lg) è un client a riga di comando che svolge il lavoro del tuo account Logistivo — carichi e viaggi, richieste di trasporto, offerte e gare, flotta e autisti, documenti, contatti e partitari clienti e fornitori, fatture e contabilità, magazzino e scorte, membri del team e tariffe doganali — da un terminale, da uno script o dal tuo agente IA. I comandi non sono incorporati nel client: il client scarica il catalogo dei comandi dal server e si costruisce a partire da esso. Gli stessi comandi possono essere chiamati via HTTP senza installare nulla — è la strada usata dalle integrazioni ERP e CRM — e tramite il canale MCP a cui si collegano gli assistenti IA esterni.
Una sola forma di comando: lg --parameter=value. Oggi il catalogo contiene 519 comandi in 125 domini; l'elenco più ampio visibile a un singolo ruolo è di 452 comandi in 112 domini.
Ogni azione di scrittura del pannello ha un comando — misurato sugli endpoint di scrittura del pannello, il 100% di quelli nel perimetro è coperto. Pagamenti (3D Secure), consensi legali e chiusura dell'account restano deliberatamente nel browser; per questi un comando restituisce invece un link.
I comandi che richiedono un documento o una foto funzionano anche fuori dal browser: scrivi --attachment_uuid=@./cmr.pdf e lg carica prima il file; via HTTP carichi il file su /api/common/commands:upload e passi l'attachment_uuid restituito.
Le chiavi di integrazione hanno un livello di accesso: employee (il predefinito per le nuove chiavi) per l'operatività quotidiana, manager per team, impostazioni, chiavi e denaro. Una chiave non ha mai più diritti della persona per conto della quale agisce.
I flag non vengono mai inventati: ogni flag è il nome di un parametro dello JSON Schema del comando stesso, e da lì vengono anche il suo tipo e la sua obbligatorietà.
I comandi di scrittura chiedono conferma; quelli irreversibili non vengono mai eseguiti senza (HTTP 409, exit code della CLI 4).
Ritentare non crea duplicati: una chiamata con un idempotency_key viene eseguita al massimo una volta.
Ogni esecuzione finisce in un unico registro di audit — resta agli atti se è partita da un terminale, dalla chat o da un assistente.
Cosa è live oggi e cosa è in arrivo
Questa sezione è in cima alla pagina di proposito. L'errore più costoso che un documento di integrazione possa fare è descrivere come disponibile un endpoint non ancora aperto: l'integratore scrive il codice, l'endpoint risponde 404 e la fiducia non torna più.
Poiché il contratto è congelato, il codice di integrazione che scrivi oggi continua a funzionare man mano che si aprono i pezzi mancanti. I campi che non conosci vanno ignorati; è questa regola che ci permette di aggiungere senza rompere.
Catalogo dei comandi e tabella delle identità — L'identità pubblica dominio/verbo di ogni comando è congelata e la versione del contratto è pubblicata come 1 in ogni risposta del catalogo e nell'header X-Contract-Version. La tabella di questa pagina è generata dal registro live: un comando aggiunto sul server compare qui da solo, e un comando rimosso scompare.
Endpoint di discovery senza autenticazione — GET /api/public/cli/catalog — nomi dei comandi, identità dominio/verbo, descrizione, parametri JSON Schema, flag di controllo e campi di versioning (since, deprecated_at, replaced_by, aliases). Nessuna autenticazione: generare un token è un passo che viene DOPO la decisione di integrare, non prima. La risposta non contiene alcun dato di tenant.
Endpoint autenticati di catalogo ed esecuzione — GET /api/common/commands, GET /api/common/commands/{name} e POST /api/common/commands/{name}. Il controllo del ruolo, il controllo di conferma, l'idempotenza e il registro di audit vivono in un unico punto di applicazione, attraverso cui passano anche la chat e il terminale.
Copertura del pannello: ogni azione di scrittura ha un comando — 519 comandi in 125 domini, verificati sugli endpoint di scrittura del pannello: ogni endpoint nel perimetro è coperto da un comando (uno specchio dell'endpoint o lo stesso servizio condiviso) e nessuno è privo di prova. Deliberatamente fuori perimetro: i pagamenti con 3D Secure, i consensi legali, la chiusura dell'account e l'accesso, che restano nel browser; la gestione di chiavi, webhook e sandbox, che sono comandi integrati di lg; e gli endpoint propri dell'app autisti.
Preflight (dry_run): vedilo senza eseguirlo — Con dry_run: true nel corpo della richiesta il comando non viene eseguito: validazione, controllo di ruolo/ambito, risoluzione del target e calcolo dei crediti vengono eseguiti e torna un'anteprima; non viene scritto nulla, non si spende alcun credito e la chiave di idempotenza non viene consumata. Lo accetta anche l'endpoint batch, per singolo batch. Un preflight non entra mai nell'handler del comando; al rilascio, 178 preflight su tutti i comandi di scrittura allora presenti nel catalogo non hanno prodotto nemmeno un'istruzione di scrittura.
Chiavi di integrazione — Chiavi API che agiscono per conto di un vero membro del team, emesse nel pannello o con lg keys create: ambito di lettura/scrittura, un livello di accesso (employee per impostazione predefinita, oppure manager), durata, ultimo utilizzo, rotazione, trasferimento e revoca. lg login --api-key, lg whoami e un lg logout che revoca lato server si basano su di esse.
Sandbox — prova le scritture senza toccare la produzione — Un tenant sandbox separato per ogni azienda, con lo stesso catalogo di comandi; si apre in self-service ed emette la propria chiave. Crediti, marketplace e instradamento dei webhook sono separati tra i due ambienti; l'ambiente è derivato dall'azienda della chiave e non può essere indicato nella richiesta.
Versioning, tassonomia degli errori, idempotenza e rate limit — I comandi riportano since / deprecated_at / replaced_by / aliases e un comando deprecato risponde con un header X-Deprecated. I fallimenti di business riportano un error_key stabile accanto all'error_code del livello di trasporto, e il dizionario delle chiavi è pubblicato nel catalogo. Le chiavi di idempotenza sono limitate alla tua azienda, legate a un solo comando e bloccate per 24 ore. I rate limit valgono per token, in tre bucket, e ogni 429 riporta Retry-After.
Webhook in uscita: una POST quando succede qualcosa — Il push firmato è live per 13 eventi. Le sottoscrizioni si gestiscono dal pannello o con lg webhooks; la firma contiene il proprio timestamp, il piano dei tentativi è di 60 · 300 · 1800 · 7200 · 21600 secondi e il motivo del silenziamento viene sempre registrato. Ogni nome di evento è coperto da una classe di evento effettivamente emessa — nulla viene annunciato per poi non essere mai inviato. Il canale pull (updated_since + cursore) non è stato rimosso: il push è stato aggiunto accanto, non al suo posto.
Comandi che accettano file — 33 comandi accettano un documento o una foto — un CMR, una fattura, un libretto di circolazione, foto di pallet. Carica una volta su POST /api/common/commands:upload, oppure lascia che lo faccia lg con --attachment_uuid=@./file.pdf, e passa l'attachment_uuid restituito; i client MCP usano lo strumento upload_attachment. Il tipo di file viene rilevato dal contenuto e un upload resta utilizzabile per 24 ore.
Il client da terminale lg — Pubblicato su npm con licenza MIT: installalo con `npm install -g @lgstv/lg`, oppure eseguilo senza installarlo con `npx @lgstv/lg`. È un unico file senza dipendenze e, poiché la superficie HTTP è aperta, puoi integrarti anche senza. Accede con un codice di approvazione che confermi nel browser e poi resta connesso, rinnovando la sessione da solo; carica per te i file locali (@path, --file, lg upload), gestisce le chiavi di integrazione (lg keys), non accetta mai un segreto sulla riga di comando, rispetta Retry-After, ritenta i 5xx con la stessa chiave di idempotenza e avvisa sui comandi deprecati e sulle versioni più recenti del contratto.
Sync incrementale: paginazione a cursore e updated_since — Il contratto qui sotto (limit + cursore opaco firmato, next_cursor, updated_since) è fissato e viene esteso progressivamente ai comandi di elenco. Finché un determinato comando di elenco non dichiara cursor e updated_since nel suo JSON Schema, consideralo una finestra piccola: massimo 20 righe, nessun cursore.
Cosa lo rende diverso: il client non conosce comandi, li disegna
È l'unica decisione che dà senso al resto della pagina. In una CLI ordinaria i comandi vivono dentro il client; in Logistivo vivono sul server.
Nell'impostazione classica, quando il server acquisisce una funzionalità il client ha bisogno di una nuova release e l'utente deve installarla. Nel frattempo le due parti sanno cose diverse — ed è la modalità di guasto più silenziosa nelle integrazioni: lo script gira, l'exit code è 0 e il comando semplicemente non descrive ciò che il server sa fare.
In Logistivo la definizione di un comando è un unico record: il nome, cosa fa, i parametri JSON Schema, quali ruoli possono vederlo, se richiede conferma e se il suo effetto è reversibile. All'avvio lg scarica quel catalogo e ne genera il testo di aiuto, i flag e la validazione dell'input. Nel momento in cui un comando viene aggiunto sul server, lg lo conosce — senza alcun aggiornamento del client.
Lo stesso catalogo alimenta l'assistente IA nella dashboard e il canale a cui si collegano gli assistenti IA esterni. Una funzionalità viene scritta una volta e compare in tre punti — e tutti e tre passano dallo stesso controllo del ruolo, dallo stesso controllo di conferma e dallo stesso registro di audit. Non esiste un inventario separato dei comandi CLI; se esistesse, entro sei mesi le tre superfici divergerebbero senza che nessuno se ne accorga.
Nessuna deriva di versione — L'elenco dei comandi che il client conosce è, per costruzione, l'elenco che ha il server. “Quale versione di lg ha questo comando?” è una domanda che non esiste.
I nomi dei flag non si indovinano mai — I flag di un comando sono esattamente i nomi dei parametri del suo JSON Schema. Per sapere cosa accetta un comando non si legge un documento, si legge il catalogo — e il catalogo è sempre aggiornato.
La tua CLI è grande quanto il tuo account — Il catalogo è filtrato per ruolo: un comando che il tuo ruolo non può vedere non compare mai nel tuo elenco. Un account autotrasportatore vede 452 comandi, un committente 448, un doganalista 312, e un account affiliato (partner di segnalazione) un insieme tutto suo di 55 comandi.
La documentazione non può restare indietro — La tabella dei comandi di questa pagina proviene dallo stesso registro. Non esiste da nessuna parte un elenco che una persona debba tenere allineato con la realtà.
La regola dei nomi — come crescono i nomi dei comandi
Il catalogo crescerà. I nuovi comandi non vengono nominati a caso; si applicano sei regole. Le pubblichiamo qui perché sono i nomi che la tua integrazione scriverà per anni, e la loro prevedibilità ha un valore per te.
Un dominio è un'entità al plurale — loads, demands, invoices, export-documents. I domini di due parole sono in kebab-case. L'unica eccezione è un nome non numerabile: stock non viene mai messo al plurale, perché “stocks” significa un'altra cosa.
Tutti i verbi di un'entità vivono in un solo dominio — loads raccoglie tutti i verbi che agiscono su un carico: create, list, get, update, set-status, assign-driver, list-problems, archive e altri. Aprire un nuovo dominio per ogni verbo (load-statuses, load-drivers) costringerebbe l'utente a cercare la stessa entità in tre posti.
Il verbo non finisce mai nel dominio; il dominio è ciò che CAMBIA — Assegnare un autista modifica il carico, non l'autista, quindi il comando è lg loads assign-driver. Il complemento indiretto (-driver) si aggancia al verbo, mai al dominio.
Una sotto-risorsa non ha mai un dominio proprio — Una riga di fattura e una voce di documento non possono essere elencate da sole; si raggiungono tramite il loro proprietario — lg invoices add-line, lg export-documents add-item. Lo decide un solo test: se non puoi elencare o leggere la cosa in modo indipendente, non è un dominio.
Restringere è un flag, non un nuovo verbo — lg fleet-documents list --days=30 è corretto; non esiste un verbo separato “list-expiring”, perché la finestra è già un parametro. Un verbo qualificato si usa solo quando le righe restituite non sono l'entità del dominio: loads list-problems restituisce segnalazioni di problemi, non carichi.
La coppia (dominio, verbo) è unica in tutto il catalogo — Anche per due comandi i cui ruoli non si sovrappongono mai. Se la stessa coppia fosse assegnata a due comandi, il tuo codice di integrazione guarderebbe un solo nome mentre la CLI eseguirebbe cose diverse a seconda di chi la invoca.
Copertura: tutto ciò che c'è nel pannello, da un comando
Molti team collegano Logistivo al proprio agente IA o al proprio sistema di automazione, e un agente è utile solo se riesce a portare a termine il lavoro. Per questo la regola è semplice: tutto ciò che un utente d'ufficio può modificare nel pannello, può modificarlo anche un comando — dietro lo stesso controllo del ruolo, lo stesso controllo di conferma e lo stesso registro di audit.
È misurato, non affermato. Ogni endpoint di scrittura dietro il pannello viene confrontato con il registro dei comandi, e un endpoint conta come coperto solo quando un comando lo dichiara come proprio specchio HTTP o chiama lo stesso servizio condiviso. Degli endpoint di scrittura nel perimetro, il 100% è coperto e nessuno è privo di prova. Ogni endpoint escluso ha un motivo scritto — passaggi di identità e di pagamento, il control plane dell'integrazione, gli endpoint propri dell'app autisti, la telemetria del client, copie morte senza chiamanti — e quelli che contano per un integratore sono elencati qui sotto.
I comandi che accettano un file rientrano nella stessa regola: 33 comandi della tabella accettano un documento o una foto, e funzionano tutti da lg, via HTTP e via MCP (vedi Comandi che accettano file).
Anche il lavoro di gestione è coperto, dietro una chiave più forte: 62 comandi della tabella — membri del team e ruoli, impostazioni aziendali, conti bancari, carte salvate, chiavi di integrazione — richiedono una chiave di integrazione di livello manager. Una chiave di livello employee, quella predefinita, svolge l'operatività quotidiana e per quei comandi viene rifiutata con INSUFFICIENT_KEY_LEVEL.
Gli account affiliato (partner di segnalazione) hanno un catalogo tutto loro: 55 comandi in 20 domini — segnalazioni, lead, note e attività CRM, presentazioni di vendita, guadagni e pagamenti, più i comandi di account e team che ha ogni ruolo. I comandi riservati agli affiliati non sono nella tabella pubblica qui sotto, che elenca i tre ruoli del pannello; un account affiliato li vede in GET /api/common/commands e in lg commands. Un'azienda che è sia affiliata sia committente, autotrasportatore o doganalista vede entrambi gli insiemi.
Un agente dovrebbe iniziare con lg users get (nome API get_current_user): restituisce il ruolo, il livello di accesso della chiave in uso, i permessi effettivi e se un'approvazione legale in sospeso o un numero di telefono non verificato stanno bloccando le scritture — così l'agente può prevedere un rifiuto invece di collezionarlo.
La copertura è misurata da un report che confronta il registro dei comandi con gli endpoint di scrittura del pannello; un endpoint del pannello aggiunto senza un comando vi compare come privo di prova. Se trovi un'azione del pannello che non riesci a raggiungere da un comando, segnalala al supporto.
1. Chiedi il link — Il lavoro che deve avvenire nella sessione del browser della persona non è un comando, ma la superficie dei comandi ne è consapevole. lg handoff-links generate (nome API get_browser_handoff_link) restituisce un link a logistivo.com per gli scopi che il tuo ruolo consente: package_purchase, payment_cards, legal_documents, integration_keys, affiliate_demo_accounts e account_close. È gratuito, non scrive nulla e il link non contiene alcun segreto — la persona accede come al solito.
2. Consegnalo alla persona — Mostra il link all'utente o invialo attraverso il tuo canale. La persona completa lì il passaggio: l'approvazione del contratto e il pagamento con 3D Secure di un pacchetto, l'aggiunta di una carta, l'approvazione dei testi legali in sospeso, l'emissione di una chiave API il cui segreto viene mostrato una sola volta, oppure la chiusura del proprio account.
3. Leggi l'esito con un comando — Una volta completato il passaggio, il suo risultato torna visibile ai comandi: il pacchetto e il saldo crediti, la carta salvata (mascherata, solo le ultime quattro cifre), la nuova chiave nell'elenco delle chiavi. Un agente non riceve mai in una chat un numero di carta, un pagamento o un consenso.
Pagamenti e 3D Secure — Acquistare o aggiornare un pacchetto e aggiungere una carta richiedono 3D Secure nel browser. I comandi elencano pacchetti e prezzi, leggono il saldo e il suo storico, elencano le carte salvate (mascherate), impostano la carta predefinita e ne rimuovono una; l'acquisto vero e proprio passa dal link di handoff.
Consenso legale — L'approvazione dei testi legali la fa la persona, nel browser. lg users get ti dice che un'approvazione è in sospeso; nessun comando può darla.
Chiusura dell'account, accesso e password — Chiudere il proprio account, accedere e cambiare la password sono passaggi di identità e restano nel browser. lg user-accounts preview mostra cosa comporterebbe la chiusura dell'account, senza eseguirla.
Chiavi di integrazione, webhook e sandbox — Gestirli restituisce segreti che devono essere mostrati una sola volta, nel tuo terminale, quindi sono comandi integrati di lg (lg keys, lg webhooks, lg sandbox) su endpoint HTTP propri anziché comandi del catalogo. Il catalogo contiene solo i due comandi sulle chiavi privi di segreti: integration-keys list e integration-keys revoke.
La chat dell'assistente nella dashboard — Le chiavi di integrazione non possono guidare la chat dell'assistente IA all'interno della dashboard; avviare o proseguire un'esecuzione con una chiave risponde 403. Un agente si collega invece tramite gli endpoint dei comandi, lg o il canale MCP — lì ogni comando viene eseguito al livello di accesso della chiave e le sue scritture vengono registrate come scritture di integrazione.
L'app autisti — Gli account autista non hanno un catalogo di comandi, e l'app autisti mantiene i propri endpoint. Gli utenti d'ufficio gestiscono gli autisti, i loro documenti, le spese e i viaggi tramite comandi.
Installazione e identità
lg è uno script Node in un unico file, senza dipendenze (Node 18+), pubblicato su npm come @lgstv/lg. Il pacchetto installa due comandi identici, lg e logistivo — usa logistivo se sulla tua macchina lg è già un alias. Essendo un unico file, funziona anche copiare lg.mjs sul server ERP di un cliente. Non ti serve il client per costruire un'integrazione ERP/CRM — gli stessi comandi sono disponibili via HTTP.
1. Installa — Ti basta Node 18 o successivo; non ci sono altre dipendenze. Installalo globalmente oppure eseguilo senza installarlo tramite npx.
2. Accedi con un codice di approvazione — lg login mostra un breve codice di approvazione e apre logistivo.com/connect nel tuo browser; via SSH, in CI o con --no-browser stampa solo l'indirizzo, che puoi aprire su qualsiasi dispositivo, compreso il tuo telefono. Lì accedi come al solito, controlla che il codice sulla pagina sia lo stesso del tuo terminale, scegli l'accesso in sola lettura o in lettura e azione e approva. Nel terminale non si digita nulla di segreto: nessuna password, nessuna chiave, nessun codice monouso. La sessione resta poi attiva su quel computer — chiudere il terminale non ti disconnette, e lg rinnova da solo il token di accesso prima che scada. lg logout chiude la sessione anche sul server, e puoi rimuoverla nel pannello in Settings › Integration keys › AI and CLI connections. lg login --password (email e password) resta disponibile come alternativa di riserva. Richiede lg 0.11 o versioni successive.
3. Per server e CI: una chiave, non un codice di approvazione — Su un server o in un job di CI non c'è nessuno che possa approvare un codice in un browser. Emetti una chiave nel pannello (Settings › Integration keys) o con lg keys create — eventualmente per conto di un membro del team dedicato e con permessi ristretti — e mettila in LOGISTIVO_TOKEN, oppure salvala con lg login --api-key. Finché la variabile è impostata, il file di configurazione non viene mai letto. Dettagli: la sezione “Connettersi con una chiave API”.
4. Verifica ed esplora il catalogo — lg commands elenca tutti i comandi che il tuo ruolo può vedere, raggruppati per dominio; lg help stampa i verbi di quel dominio e lg help stampa l'elenco completo dei parametri di un comando, con i tipi e quelli obbligatori. Nessuno di questi testi vive dentro il client — tutto viene dal catalogo. Ricorda che l'elenco dipende dal tuo ruolo: i verbi di un dominio non sono gli stessi per un autotrasportatore e per un committente (loads set-status, per esempio, è solo nel catalogo dell'autotrasportatore). Se manca un verbo, controlla il tuo ruolo prima della tua installazione.
Non mettere mai la chiave nel controllo di versione, in un log della CI o in una finestra di chat. Se hai effettuato l'accesso con un codice di approvazione o una chiave di integrazione, lg logout chiude l'accesso anche sul server; in una sessione con password (lg login --password) cancella solo la copia LOCALE e lo dice esplicitamente. Il registro di audit memorizza i tuoi argomenti ma maschera come *** ogni campo il cui nome contiene token, password, IBAN, card o OTP, e ogni parametro che un comando dichiara segreto.
LOGISTIVO_TOKEN — Token di accesso personale. Quando è impostato, il file di configurazione non viene mai letto — è la strada preferita in CI e sui server.
LOGISTIVO_BASE_URL — Radice del server. Il valore predefinito è https://logistivo.com. Cambialo solo se punti a un tuo ambiente; il flag --base-url fa lo stesso per un singolo comando.
LOGISTIVO_HOME — Directory del file di configurazione e della cache del catalogo. Il valore predefinito è ~/.logistivo. Separala se lavori con due account sulla stessa macchina.
LOGISTIVO_PROFILE — Il profilo con cui eseguire. `lg profile use` è la scelta persistente; questa variabile vale per una singola esecuzione ed è il modo più rapido per passare da un profilo live a uno sandbox in CI. Un nome di profilo sconosciuto non viene ignorato in silenzio — genera un errore.
NO_COLOR — Se impostata, non viene stampato alcun colore ANSI (la forma permanente del flag `--no-color`). Attivala per un bridge che scrive in un file di log o nell'output della CI; le sequenze di escape dei colori rompono gli strumenti che leggono quei log in seguito.
Ergonomia del client
Queste funzioni rendono più comodo l'uso quotidiano del client `lg`. Nessuna di esse modifica il contratto HTTP — salta questa sezione se ti integri direttamente via HTTP.
Più ambienti e più chiavi — Tieni staging e produzione, oppure i bridge verso clienti e autotrasportatori, in profili separati. L'elenco dei profili non stampa mai un token; ogni riga mostra l'impronta sha256 del token. Il catalogo dei comandi è in cache per profilo, host e token, quindi due ruoli non possono mai vedere l'uno l'elenco comandi dell'altro.
Sync incrementale: lg sync — Esegue in un solo comando il ciclo di sync della guida pratica: un watermark per entità, updated_since con un cursore, output JSONL e un margine di sicurezza di cinque minuti. Usa --full per il primo caricamento completo. Il comando è di sola lettura; non esiste un flag --write. lg sync --list ricava dal catalogo le entità sincronizzabili per il tuo ruolo.
Gestione degli errori e completamento della shell — Su 422 il client indica il campo rifiutato con il flag che hai digitato, insieme all'error_key stabile e alla spiegazione che ne dà il catalogo stesso. Su 409 stampa la riga di comando pronta con --yes; su 429 attende quanto indicato da Retry-After. Il completamento della shell copre domini, verbi, flag e valori enum, e funziona offline.
I parametri segreti non vanno mai sulla riga di comando — Alcuni comandi richiedono un segreto — collegare l'integrazione contabile Paraşüt, per esempio, richiede le credenziali client e la password di quel sistema. lg non accetta mai un valore del genere come flag, perché finirebbe nella cronologia della shell e nell'output di ps: lo chiede senza eco, oppure lo legge da ---file=PATH o da stdin (---file=-), e lo tiene solo in memoria. Un comando il cui parametro obbligatorio è segreto si esegue solo da lg: chiamato dalla chat, via MCP o dentro lg batch viene rifiutato con SECRET_REQUIRES_CLI. Il registro di audit registra sempre il valore come ***.
Connettersi con una chiave API
Un ERP, un CRM, uno script o un agente IA si collega a Logistivo con una chiave di integrazione emessa nel pannello o con lg keys create. La chiave agisce per conto di un vero membro del team: il ruolo di quella persona decide l'elenco dei comandi, il livello di accesso della chiave decide quanto può essere pesante il lavoro, e quando quella persona lascia il team la chiave muore con lei. Non esiste un “account di servizio” sintetico e non ce ne sarà mai uno — l'isolamento multi-tenant è legato all'utente, e un bridge senza proprietario è quello che continua a scrivere in silenzio per anni.
1. Emetti una chiave nel pannello — Settings › Integration keys › New key. Dalle un nome (“Sync notturna ERP”), scegli l'ambito e il livello di accesso e, se vuoi, accorcia la durata. La chiave viene mostrata una sola volta, solo in quella schermata; il server non la memorizza. Se la perdi, Rotate ne emette una nuova — quella vecchia diventa subito non valida.
2. Connettiti dal terminale — lg login --api-key convalida la chiave, stampa l'identità e l'ambito e scarica il catalogo dei comandi. lg whoami chiede al server con quale utente, azienda, ruolo e ambito stai operando. lg logout revoca la chiave anche sul server, così come vi chiude una sessione aperta con un codice di approvazione (solo il lg logout di una sessione con password non può farlo).
3. Oppure HTTP puro — La chiave è un token di accesso trasmesso nell'header Authorization: Bearer e funziona direttamente con i tre endpoint dei comandi. Su un server o in CI mettila in LOGISTIVO_TOKEN; finché quella variabile è impostata, il file di configurazione non viene mai letto.
4. Oppure gestisci le chiavi dal terminale: lg keys — lg keys è il gemello da terminale della schermata del pannello: stessi endpoint, stesso controllo (il permesso di gestione del team e, quando lo chiami con una chiave, una chiave di livello manager). create, rotate e transfer restituiscono un nuovo token una sola volta: con --save-profile=NAME finisce direttamente in un profilo locale e non viene mai stampato; altrimenti lg lo stampa una volta. In modalità --json il token è incluso solo se aggiungi --show-secret, e una chiamata --json senza nessuno dei due flag viene rifiutata prima che la richiesta parta, così il token non può finire in silenzio nell'output di uno script. rotate, transfer e revoke chiedono conferma (--yes); una chiave si indica con il suo nome esatto o con il suo uuid, mai per approssimazione. Il livello di accesso passa invariato a una chiave ruotata o trasferita.
L'ambito è applicato sull'intera superficie dell'API, non solo sul catalogo dei comandi: una chiave di sola lettura supera le richieste di lettura (GET/HEAD/OPTIONS) e ogni altra richiesta di scrittura risponde 403 forbidden. Ci sono due eccezioni deliberate, entrambe protette da un controllo più fine: l'endpoint di esecuzione dei comandi (la decisione viene dal flag read_only del comando stesso, perché anche i comandi che non scrivono si chiamano con POST) e una chiave che revoca se stessa (lg logout, consentito anche su una chiave di sola lettura). Ambito, autorizzazioni per dominio e livello di accesso sono tre assi indipendenti e devono essere superati tutti: una chiave read non può scrivere nemmeno a livello manager, una chiave write di livello employee non può gestire il team, e un'autorizzazione di dominio loads:write non apre il lavoro di gestione. Emetti la chiave per conto del membro con meno privilegi che copre le tue esigenze: è il ruolo a decidere quali record puoi vedere in assoluto.
read — Il catalogo dei comandi e i comandi che non scrivono (list, search, preview). Un comando di scrittura restituisce 403 forbidden — prima del controllo di conferma; una chiave di sola lettura non vede mai nemmeno un 409. La scelta giusta per la sync notturna e la reportistica.
write — Tutti i comandi. I comandi che richiedono conferma la chiedono comunque con 409; confirm: true (--yes nella CLI) funziona esattamente come prima. L'ambito non allenta mai il controllo di conferma.
employee — Il predefinito per ogni nuova chiave. Operatività quotidiana: carichi, richieste di trasporto, offerte, viaggi, flotta e documenti di flotta, documenti, contatti — ogni comando che non richiede un permesso di gestione, più i permessi di flotta. Un comando che richiede di più risponde 422 con error_key INSUFFICIENT_KEY_LEVEL e required_key_level: manager; l'endpoint REST corrispondente risponde 403 con la stessa chiave. Il livello giusto per una sync notturna di un ERP, un bridge telematico o uno script operativo.
manager — Tutto ciò che può fare la persona per conto della quale agisce la chiave, gestione compresa: membri del team e ruoli, impostazioni aziendali, chiavi di integrazione, conti bancari e la loro verifica, carte salvate, relazioni tra aziende, pagamenti agli affiliati. Una chiave manager non aggiunge mai un diritto che la persona non ha — senza il permesso di gestione del team non può comunque gestire il team. Le chiavi che esistevano prima dell'introduzione dei livelli di accesso sono chiavi manager, quindi si comportano esattamente come prima.
Una chiave per integrazione — Se CRM ed ERP condividono una chiave, tagliarne fuori uno significa tagliare fuori anche l'altro. Dai a ogni bridge la sua chiave; l'elenco le mostra comunque per nome.
Rotazione — Emette un nuovo token e revoca subito quello vecchio; la durata residua viene mantenuta. Usala in caso di sospetta fuga e a intervalli regolari. L'integrazione riceve 401 finché non viene aggiornata con il nuovo token.
Revoca — La chiave viene chiusa definitivamente; non si può annullare, emetti una nuova chiave se serve. Se il membro per conto del quale agisce la chiave viene rimosso dal team o disattivato, la chiave decade da sola.
Durata e limite — La validità predefinita è di 180 giorni; puoi accorciarla alla creazione, mai estenderla. Un utente può avere al massimo 10 chiavi attive. L'orario dell'ultimo utilizzo è visibile nell'elenco; una chiave mai usata lo dice esplicitamente.
Chi le gestisce — Emettere, ruotare, trasferire e revocare è consentito ai responsabili con il permesso di gestione del team — lo stesso controllo usato per aggiungere o rimuovere membri del team — e, quando lo si fa con una chiave di integrazione, quella chiave deve essere di livello manager. Un responsabile può emettere una chiave per conto di un altro membro; per un bridge è consigliato un membro dedicato e con permessi ristretti.
I primi dieci minuti: dal pannello alla tua prima chiamata
I minuti più costosi di un'integrazione sono i primi dieci. I quattro passaggi qui sotto descrivono quel percorso in ordine; lo stesso ordine esiste nel pannello come procedura guidata (Settings › Integration › Setup wizard), e la procedura guidata chiama esattamente gli endpoint descritti qui. Uno sviluppatore senza accesso alla procedura guidata arriva allo stesso punto leggendo questa sezione.
Nessuno dei quattro passaggi finisce con “l'ho inviato”. Se la chiave funziona davvero lo dice il registro delle richieste; se il webhook arriva davvero lo dice il registro delle consegne. Entrambi sono consultabili nel pannello e in lg. Una configurazione mai misurata è una configurazione che si crede soltanto funzionante.
1. Decidi cosa farai — imposta prima l'ambito — Non si decide dopo cosa può vedere una chiave: l'ambito lo scegli quando la emetti. Gli assi sono due. L'ambito generale (read / write) risponde solo alla domanda “può scrivere?”. L'ambito fine (autorizzazioni per dominio: loads:read, invoices:write) dice quali domini può toccare, e nel momento in cui viene impostato la chiave diventa fail-closed — ogni dominio che non hai selezionato, e ogni endpoint che non corrisponde ad alcun dominio, restituisce 403. L'elenco dei domini nel pannello non è scritto a mano; deriva dal catalogo live dei comandi del tuo ruolo e mostra quanti comandi ed endpoint REST apre ciascun dominio. Gli endpoint del catalogo dei comandi, di “chi sono” (current) e di “esci” sono sempre esenti dall'ambito: una chiave deve sempre poter descrivere e chiudere se stessa. Il terzo asse è il livello di accesso: employee (il predefinito) svolge l'operatività quotidiana, manager si occupa anche di team, impostazioni, chiavi e denaro. Scegli employee a meno che il bridge non svolga lavoro di gestione.
2. Emetti la chiave — il token viene mostrato una sola volta — Settings › Integration › New key. Dalle un nome (“Sync notturna ERP”), scegli l'utente per conto del quale opera e il livello di accesso, e accorcia la durata se vuoi. Il token grezzo viene restituito solo in quella risposta; il server non lo memorizza e nel pannello non esiste un “mostra di nuovo”. Se lo perdi, ruotalo per ottenerne uno nuovo e quello vecchio muore all'istante. Non mettere mai il token nel controllo di versione, in un log della CI o in una finestra di chat; mettilo nel secret store del sistema di destinazione.
3. Fai la prima chiamata — e verifica che sia arrivata DAVVERO — Bastano due richieste. La prima prova la tua identità (è esente dall'ambito e funziona con ogni chiave): l'ambito è quello che ti aspettavi, lo stato è attivo, expires_at si sta avvicinando? La seconda legge dati reali dal dominio che hai scelto. Se passa, identità, ambito, controllo dell'email e percorso di rete sono tutti corretti. Se non passa, non tirare a indovinare: il registro delle richieste della chiave mostra, riga per riga, quale endpoint è stato rifiutato, con quale codice e con quale chiave di errore stabile (INSUFFICIENT_SCOPE, IP_NOT_ALLOWED, KEY_ACTOR_BLOCKED …). Nel pannello quel registro è la finestra “Recent requests”; nel terminale è lg logs. La procedura guidata osserva esattamente questo registro e si rifiuta di rendere verde il passaggio finché non vede una vera chiamata riuscita.
4. Configura il webhook — e verifica la firma prima di fare qualsiasi altra cosa — Aspettare gli eventi costa meno che chiedere ogni minuto. Registra un indirizzo https, scegli gli eventi che ti interessano e collega la sottoscrizione alla tua chiave: se la chiave viene revocata, si interrompono anche le consegne. Il segreto viene mostrato una sola volta, alla creazione. Il tuo endpoint ricevente deve prima di tutto verificare la firma: la stringa firmata è "{t}.{raw body}" (il corpo grezzo) e l'algoritmo è HMAC-SHA256; il timestamp è DENTRO la firma, quindi scarta ogni richiesta più vecchia di 300 secondi anche quando la firma è valida. Confronta in tempo costante e non riserializzare mai il corpo — nel momento in cui analizzi il JSON e lo stampi di nuovo, la firma smette di corrispondere. Dal pannello, “Send test” invia un vero ping firmato e puoi seguire la consegna tentativo per tentativo.
Sandbox: esercitati a scrivere senza toccare la produzione
Il preflight (dry_run) ti dice cosa FAREBBE un comando; ma se l'idempotenza riproduce davvero, se il webhook viene davvero consegnato, come appaiono i rami di errore e da dove arriva il credito lo si vede solo in una scrittura REALE. È a questo che serve la sandbox: un tenant separato che rispecchia la tua azienda — stesso codice, stesso catalogo di comandi — e non tocca mai il tuo registro live.
La sandbox non è un flag della richiesta, è un TENANT. Un'azienda Logistivo separata aperta per la tua: un proprio utente, un proprio pacchetto, un proprio registro dei crediti, proprie sottoscrizioni webhook. L'ambiente è DERIVATO dall'azienda della chiave e non può essere indicato da chi chiama, quindi anche se scegli il profilo sbagliato la richiesta si ferma lato server con 403 ENVIRONMENT_MISMATCH. “Pensavo di scrivere nella sandbox e ho scritto in produzione” è strutturalmente impossibile.
La superficie è identica — misurato: il catalogo che ottiene una chiave sandbox è lo stesso che ottiene la tua chiave live (con una chiave da committente, 448 comandi da entrambe le parti). Un bridge che funziona nella sandbox funziona in produzione; nulla di ciò che impari deve essere imparato due volte.
La sandbox non si apre vuota: contiene dati iniziali generati (NON copiati) — contatti, carichi in entrambe le direzioni e richieste di trasporto. I nomi sono dichiaratamente inventati e gli indirizzi email appartengono al dominio @sandbox.invalid; nessuna riga di un tenant reale viene mai letta, clonata o usata come modello.
Deliberatamente NON esiste un pulsante di reset, e nessun record, file o documento viene mai cancellato. Se vuoi ripartire da zero, il rinnovo apre una nuova generazione e quella vecchia resta, ritirata. Qualche centinaio di righe di prova accumulate non costa nulla rispetto a una routine di cancellazione collegata al tenant sbagliato.
1. Apri la sandbox — Una sandbox per azienda. L'endpoint richiede il permesso di gestione del team (team.manage), quindi lo fa un amministratore della tua azienda. Se esiste già, lo stesso endpoint risponde via GET con il suo stato: id dell'azienda, credito residuo, numero di chiavi attive, sottoscrizioni, storico delle generazioni e limiti.
2. Emetti una chiave sandbox e tienila come secondo profilo — La chiave viene emessa per conto dell'utente bridge della sandbox stessa e torna con il timbro environment: sandbox; il token grezzo compare solo in quella risposta. Dal lato di lg non sostituire la tua chiave live — tieni ENTRAMBE come profili separati; --sandbox e --live sono selettori validi per una singola esecuzione.
3. Scrivi davvero — Qui niente --dry-run; scrivere è proprio lo scopo. Invia due volte la stessa chiave di idempotenza e guarda la seconda risposta tornare come status: replayed — è il risultato misurato nella sandbox. Chiama di proposito un comando soggetto a conferma senza conferma e leggi il corpo del 409; prova un comando fuori dal tuo ambito e leggi il rifiuto. Niente di tutto questo lascia traccia nel tuo registro live: il tuo saldo live resta invariato durante la stessa esecuzione.
4. Leggi la checklist prima di andare live — L'endpoint di go-live risponde in base a ciò che hai DAVVERO fatto nella sandbox: hai scritto, hai visto i rami di errore, è stato consegnato un webhook, hai spostato il ricevitore dall'indirizzo di prova, hai impostato una scadenza sulla chiave? Ogni voce torna come pass / todo / unknown. La stessa risposta contiene anche una PROPOSTA DI AMBITO derivata dai comandi che hai effettivamente chiamato — usala per emettere la tua chiave live non più ampia del necessario.
Crediti e fatturazione — La sandbox ha un proprio registro dei crediti e il tuo saldo live non si muove. È una struttura, non un controllo: il credito è contato per azienda e la sandbox è un'azienda separata. Si apre sul piano gratuito, non ha un metodo di pagamento ed è fuori dalla finestra di incasso mensile — non può arrivare a una fattura per nessuna via.
Marketplace — Una richiesta di trasporto aperta nella sandbox NON compare sulle schermate degli autotrasportatori reali e NON raggiunge la loro email o le loro notifiche push; e tu non vedi nemmeno le richieste reali. La separazione è simmetrica e applicata in due query distinte: a chi una richiesta è VISIBILE e a chi viene INVIATA sono domande diverse.
Webhook — Anche le sottoscrizioni portano il timbro dell'ambiente. Un evento della sandbox non viene mai consegnato a una sottoscrizione live e un evento live non raggiunge mai una sottoscrizione sandbox; per una sottoscrizione il cui timbro non corrisponde più non viene aperta alcuna consegna. Poiché il limite di sottoscrizioni è per azienda, le tue sottoscrizioni di prova non intaccano la tua quota live.
Dati iniziali — I record di esempio nella sandbox sono GENERATI, mai copiati da tenant reali. Il seeding è idempotente: una seconda chiamata non stende un secondo strato di dati sopra i tuoi record.
Lo stesso catalogo — Il tuo ruolo è il tuo ruolo anche nella sandbox, e l'elenco dei comandi è identico — misurato, 448 comandi da entrambe le parti. La sandbox non è una demo ridotta; è un gemello della tua azienda.
Il limite di oggi: le sottoscrizioni webhook non si possono gestire con una chiave sandbox — Gli endpoint delle sottoscrizioni richiedono il permesso di gestione del team (team.manage), e l'utente bridge della sandbox non ha alcun ruolo nel team, quindi oggi `lg --sandbox webhooks …` risponde 403. L'intera superficie dei comandi funziona — la restrizione riguarda solo il registro delle sottoscrizioni. Se vuoi provare i webhook nella sandbox, chiedi al supporto; la cosa è misurata e registrata come lacuna aperta.
GET /api/common/integration-sandbox — Stato: se esiste, quale azienda, credito residuo, numero di chiavi attive e di sottoscrizioni, storico delle generazioni, i limiti e una guida agli inneschi che mostra quale comando genera quale evento.
POST /api/common/integration-sandbox — Apre la sandbox (una per azienda, idempotente). Richiede il permesso team.manage.
POST /api/common/integration-sandbox/keys — 201 + la chiave e il token grezzo (solo qui, una sola volta). Il timbro environment: sandbox è derivato dall'azienda; chi chiama non può indicarlo.
GET /api/common/integration-sandbox/go-live — La checklist di go-live e una proposta di ambito — calcolate dal tuo traffico reale nella sandbox.
POST /api/common/integration-sandbox/renew — Apre una nuova GENERAZIONE della sandbox e ritira quella precedente.
Il modello dei comandi
Esiste una sola grammatica e non ha eccezioni. Per sapere come chiamare un comando ti serve soltanto ciò che il catalogo dice di lui.
lg loads list --status=in_transport --limit=20 --json
I nomi dei flag sono i nomi dei parametri dello schema, e lg accetta entrambe le grafie: --load_code e --load-code arrivano allo stesso campo (lg help stampa la forma kebab-case). Vedendo un flag sai quindi in quale campo JSON finisce, e passare dalla CLI a HTTP non richiede alcuna traduzione di nomi. Un parametro booleano scritto senza valore vale true (--only_open); il contrario è --no-only_open. Scrivi un argomento il cui valore inizia con un trattino come --flag=value, altrimenti un flag dimenticato ingoia in silenzio il successivo come proprio valore. Su un comando che accetta un file, metti @ davanti a un percorso locale (--attachment_uuid=@./cmr.pdf) — vedi Comandi che accettano file.
lg — Il client.
loads — Il dominio — l'entità su cui lavori, al plurale.
list — Il verbo — cosa fai a quell'entità, preso da un vocabolario chiuso che cresce solo per decisione esplicita: verbi semplici (list, get, create, update, delete, search, preview, generate, extract …) e verbi composti che indicano cosa viene collegato o modificato (add-document, set-status, assign-driver). lg help elenca i verbi di un dominio.
--status=in_transport — Un parametro — il suo nome è esattamente il nome del parametro nello JSON Schema e il suo valore deve corrispondere al tipo dello schema. Un valore non valido su un campo enum non arriva mai al server.
--limit=20 — Numero di righe nei comandi di elenco. Il limite massimo è indicato nella descrizione dei parametri di ogni comando — tipicamente 20 in una normale chiamata di elenco e fino a 100 in modalità sync (con cursor o updated_since).
--json — Output JSON grezzo.
--json — Stampa JSON grezzo. È l'unica forma corretta per gli script: la tabella allineata predefinita è pensata per le persone, sceglie le colonne in base ai dati e può cambiare layout senza preavviso. Non scrivere mai uno script che analizza l'output in tabella.
--yes, -y — Supera il controllo di conferma (confirm: true via HTTP). Usalo solo in uno script che sa cosa sta per fare; su un comando irreversibile questo flag equivale a dire “non si torna indietro”.
--idempotency-key= — Rende sicuro ritentare un comando di scrittura. Una seconda chiamata con la stessa chiave non riesegue il comando; restituisce il primo risultato. Se costruisci un ciclo di retry, genera la chiave TU e invia la stessa a ogni tentativo.
--dry-run — Esegue un preflight al posto del comando: vengono eseguiti la validazione, i controlli e il calcolo dei crediti, ma non viene scritto nulla (vedi la sezione sul preflight). Valido su ogni comando e su lg batch.
--refresh — Forza l'aggiornamento del catalogo. lg tiene in cache il catalogo per un'ora; se sai che un comando è appena stato aggiunto sul server, usa questo invece di aspettare.
--help, -h — Stampa la descrizione del comando dal catalogo, ogni parametro, il suo tipo, i valori enum e se è obbligatorio. Dentro il client non c'è alcun file di aiuto.
--profile=, --sandbox, --live — Il profilo con cui eseguire questa singola chiamata. --sandbox e --live scelgono il profilo che contiene una chiave sandbox o live; l'ambiente viene derivato dalla chiave sul server, quindi una discrepanza si ferma con 403 ENVIRONMENT_MISMATCH invece di scrivere nel posto sbagliato.
--base-url, --timeout, --verbose, --no-color, --version — Rispettivamente: punta un singolo comando a un altro server, un timeout in secondi, il dettaglio di richiesta/risposta, disattiva il colore ANSI e la versione del client.
Esempi reali
Ogni comando qui sotto esiste oggi nel catalogo; nessun nome o parametro è inventato. Gli output sono abbreviati e mostrano il livello `data.result`; via HTTP lo stesso oggetto arriva dentro l'envelope (involucro di risposta) `{success, data:{…}}` (vedi l'API HTTP dei comandi).
Carichi attualmente in viaggio — lg loads list --status=in_transport --limit=20
Un carico completo, JSON grezzo — lg loads get --load_code=FSK2158 --json
Segnalazioni aperte di incongruenza documentale — lg loads list-problems --only_open=true --limit=10
Risolvi il paese — lg countries search --query=Germany --json
Filtra con l'id risolto — lg loads list --receiving_country_id=57 --date_from=2026-09-01 --limit=20
Trova un codice HS dal nome di un prodotto — lg tariffs search --query="aluminium profile"
Fai avanzare un carico (solo ruolo autotrasportatore) — lg loads set-status --load_code=FSK2158 --status=transit --date=2026-08-21 --yes
Bozza — lg export-documents create --doc_type=proforma-invoice --currency_code=EUR --json
Generalo (con conferma) — lg export-documents generate --document_id=8412 --yes
Senza il client: l'API HTTP dei comandi
lg è una comodità, non la porta d'ingresso. Catalogo ed esecuzione passano entrambi da tre endpoint HTTP (i file ne hanno un quarto, l'endpoint di upload — vedi Comandi che accettano file); un'integrazione ERP o CRM si collega qui direttamente. L'identità è un token di accesso personale trasmesso in Authorization: Bearer. OGNI risposta arriva nello stesso envelope: `{ "success": bool, "data": { … }, "code": "…", "message": { … } }`. L'intero contratto vive dentro `data` — `contract_version`, `command`, `status` e, come output del comando, `result`; in caso di errore `error_code`, `error_key` ed `error`. Per risparmiare spazio, gli esempi di risposta in questa pagina mostrano l'oggetto `data` anziché l'envelope; non dimenticare di estrarre `data` nel tuo codice. Anche `lg --json` stampa l'envelope COMPLETO, ed è per questo che i percorsi jq iniziano con `.data.result…`. L'unica eccezione è `/api/public/status`: quell'endpoint è privo di envelope, così i sistemi di monitoraggio possono dare l'allarme senza analizzarlo.
Chiedere conferma con 200 + ok:false è vietato e non accadrà mai. Il motivo è semplice: i client trattano 200 come un successo, quindi una richiesta di conferma restituita con 200 bloccherebbe il flusso in silenzio e nessuno se ne accorgerebbe. La conferma è sempre 409.
GET /api/common/commands — L'intero catalogo visibile al tuo ruolo: contract_version; per ogni comando name, domain, verb, description, JSON Schema, read_only, confirmation_needed, irreversible, credit_cost, since, deprecated_at, replaced_by, aliases e i campi di accesso key_level, permission, file_params, secret_parameters e cli_only; al livello superiore il dizionario error_keys, rate_limits, idempotency_ttl_hours, i ruoli del tuo catalogo, il contratto degli allegati (upload) e il livello di accesso della chiave con cui stai chiamando. Invia un ETag; If-None-Match risponde 304. ?domain= trova anche un dominio vecchio (alias). Costruisci il tuo client a partire da qui; non scrivere nel codice un elenco fisso di comandi.
GET /api/common/commands/{name} — Un comando completo. name è il nome congelato del comando nel catalogo (list_loads), non l'identità CLI. Un comando deprecato risponde con un header X-Deprecated.
POST /api/common/commands/{name} — Esecuzione. Corpo: { args, confirm?, idempotency_key? }. Lo stato HTTP della risposta è il risultato stesso — qualsiasi cosa diversa da 200 è informazione, non rumore. Gli errori riportano error_code (trasporto) e, per i rifiuti di business, error_key.
Comandi che accettano file
33 comandi della tabella accettano un documento o una foto: allegare un CMR a un carico, leggere i codici HS da una fattura, creare un veicolo dal suo libretto di circolazione, stimare un pallet dalle foto, caricare un documento aziendale, confrontare una fattura con una packing list. Nel browser trascini il file in un modulo; altrove servono due passaggi — carica il file, poi passa il suo id al comando.
Un parametro accetta un file quando il suo nome termina in attachment_uuid o attachment_uuids — photos[].attachment_uuid dentro un elenco, front_attachment_uuid su un assegno. Non devi ricordartelo: ogni riga del catalogo riporta file_params con i percorsi esatti, lo schema contrassegna quei campi (format: uuid, x-logistivo-file: true) e la risposta del catalogo contiene un blocco attachments con l'indirizzo di upload, i tipi accettati, i limiti di dimensione e la durata di validità. Anche lg help li mostra.
Caricare è una scrittura, quindi una chiave con ambito di lettura non può caricare; qualsiasi chiave con ambito di scrittura può farlo, a entrambi i livelli di accesso. Gli upload appartengono all'utente, non alla chiave: due chiavi dello stesso utente vedono gli stessi upload, e nessuno può usare quelli di un altro. Un id sconosciuto, scaduto o non tuo semplicemente non viene trovato, e il motivo non viene rivelato.
Gli allegati della chat della dashboard e gli upload dei comandi sono spazi separati: un file allegato nella chat dell'assistente non può essere passato a un comando tramite id, e un upload di un comando non compare mai in un thread della chat.
Un upload non è un comando e da solo non ha alcun effetto di business: ai tuoi dati non succede nulla finché un comando non usa l'id. È anche per questo che caricare non chiede mai conferma — è il comando che consuma il file a portare il controllo.
1. lg: metti @ davanti a un percorso locale — lg carica prima il file, poi esegue il comando con l'id restituito; un valore senza @ è l'id di un file che hai caricato in precedenza. Gli elenchi accettano percorsi separati da virgole o un flag ripetuto, i campi annidati accettano JSON, e --file è una scorciatoia quando il comando ha esattamente un campo file di primo livello. lg verifica ogni file in locale (esistenza, dimensione, tipo) prima di inviare qualsiasi cosa, e lg batch carica una sola volta ogni file distinto prima che il batch venga eseguito.
2. HTTP: carica, poi passa attachment_uuid — Invia il file come multipart/form-data in un campo chiamato file. Un nuovo upload risponde 201; lo stesso file caricato di nuovo dallo stesso utente risponde 200 con stato replayed e lo stesso id, e non viene scritto nulla. Come ovunque in questa pagina, l'esempio mostra l'oggetto data all'interno dell'envelope.
3. MCP: lo strumento upload_attachment — Un client MCP non può inviare multipart, quindi il canale offre uno strumento in più che non è nel catalogo: upload_attachment accetta un nome di file e il contenuto in base64 e restituisce lo stesso attachment_uuid. Chiama lo stesso servizio dell'upload HTTP, con le stesse regole.
Il tipo viene dal contenuto — Il nome del file e il tipo dichiarato vengono ignorati; l'estensione memorizzata è quella rilevata. Accettati per l'upload: jpg, jpeg, png, webp, heic, heif, pdf, xlsx, xls, csv, txt, doc, docx, xml, zip. Ogni comando applica poi il proprio elenco, più ristretto, prima che venga eseguito qualcosa e risponde UNSUPPORTED_FILE_TYPE con i tipi accettati, oppure FILE_TOO_LARGE.
Dimensione — Immagini fino a 10 MB, altri file fino a 15 MB.
Durata di validità — Un upload può essere usato per 24 ore. Dopo non viene più risolto (ATTACHMENT_NOT_FOUND) — non viene cancellato. Carica di nuovo se un comando fallisce per questo motivo.
Stesso file, stesso id — Caricare di nuovo lo stesso file (stesso nome, dimensione e contenuto) restituisce l'id esistente invece di scriverne uno nuovo, purché gli resti almeno un'ora, e non consuma il tuo limite giornaliero.
Limiti giornalieri — 300 upload per utente al giorno (TOO_MANY_FILES) e 2 GB per azienda al giorno (DAILY_LIMIT_REACHED); entrambi rispondono 429 con retry_after.
POST /api/common/commands:upload — Upload multipart nel campo file. 201 per un nuovo upload, 200 con stato replayed per lo stesso file. Restituisce data.attachment: attachment_uuid, filename, mime_type, size_bytes, sha256, extraction_status, expires_at e reused.
Il controllo di conferma e i comandi irreversibili
Ogni comando del catalogo porta due flag: confirmation_needed (richiede un'approvazione esplicita prima di essere eseguito?) e irreversible (il suo effetto si può annullare?). Sono due domande distinte, ed entrambe sono applicate sul server invece di essere lasciate alla buona educazione del client.
Il controllo riguarda la responsabilità, non le regole di business. Presentare un'offerta è il primo passo verso un contratto di trasporto; emettere una fattura crea una scrittura contabile; un movimento di magazzino modifica un registro. Nessuna di queste cose dovrebbe mai poter essere eseguita due volte per sbaglio.
Il controllo si legge dal comando EFFETTIVO. Quando un comando ne avvolge un altro — come fa l'esecutore generico nella chat — il controllo deriva dai flag del comando che verrà davvero eseguito, non dall'involucro. Con un flag fisso uno dei due fallimenti sarebbe inevitabile: o il comando di fatturazione verrebbe eseguito senza conferma, oppure ogni ricerca di un paese farebbe comparire una scheda di conferma.
read_only e senza conferma non sono la stessa cosa. Esistono tre stati distinti: invoices preview non richiede conferma e non scrive nulla; loads create richiede conferma e scrive; invoices create non richiede conferma ma scrive — nasce una bozza. Lo decide un solo test: quando il comando termina, è cambiata una riga nel database?
Alcune azioni non sono dietro questo controllo perché non sono affatto comandi: acquistare un pacchetto, aggiungere una carta con 3D Secure, approvare i testi legali e chiudere un account avvengono nel browser della persona. Per queste, lg handoff-links generate restituisce un link a logistivo.com — gratuito, senza scrivere nulla, senza alcun segreto — e la persona completa il passaggio lì. Nessun flag, comunque impostato, trasforma un pagamento o un consenso in una chiamata API.
Tecnicamente un'integrazione può superare il controllo in automatico a ogni chiamata, ma non è consigliabile. Lo schema corretto è automatizzare il controllo solo per i comandi che sai essere reversibili e instradare quelli irreversibili nella coda di una persona.
1. Chiamalo — Chiama il comando soggetto a conferma senza confirm. Non cambia nulla.
2. Leggi il riepilogo — Ricevi un 409; confirmation.summary nel corpo è una frase scritta per una persona (“Sto per emettere una fattura: X Ltd, 1.200,00 TRY”), non un elenco di argomenti grezzi. I comandi monetari riportano anche un'anteprima strutturata: righe, totali, avvisi.
3. Conferma — Ripeti la stessa chiamata con confirm: true (--yes nella CLI). I comandi irreversibili sono contrassegnati in modo da essere eseguiti al massimo una volta.
Preflight: vedi cosa farebbe un comando di scrittura, senza eseguirlo
Il passaggio più costoso nel collegare un bridge ERP è scoprire se il tuo corpo è corretto eseguendo DAVVERO il comando: una bozza di fattura nel registro live, un credito bruciato, una pulizia manuale. dry_run mette fine a tutto questo — aggiungi un campo alla richiesta, il comando non viene eseguito e leggi cosa succederebbe.
Oggi il registro contiene 519 comandi; 233 di essi leggono soltanto e non scrivono nulla. Dei restanti 286 comandi di scrittura, 251 sono soggetti a conferma: chiamati senza confirm rispondono già 409 e descrivono cosa farebbero. La lacuna erano gli altri 35 — bozze di fattura, bozze di documenti di esportazione, righe: esattamente la catena che un bridge collega per prima. Per questi, chiamare significava eseguire.
C'era una seconda lacuna anche sui comandi soggetti a conferma: la validazione dello schema viene eseguita DOPO il controllo. Così una chiamata con un argomento mancante riceveva prima la scheda di conferma, la confermava, e solo allora si sentiva dire “manca questo campo”. Un preflight risponde a entrambe le cose in un solo giro.
E il bug di bridge più comune — e scoperto più tardi — è questo: invii un campo che non è nello schema (customer_id dove è atteso recipient_contact_id), il server lo scarta in silenzio, il comando risponde 200 e il record finisce nel posto sbagliato. La risposta del preflight elenca quei campi per nome sotto arguments.ignored; nessun messaggio di errore lo farà mai.
Un preflight non scrive nulla, e prima ancora di essere una misura è una proprietà strutturale: il percorso del preflight non entra mai nell'handler del comando, quindi vale per ogni comando, compresi quelli aggiunti in seguito. È stato anche misurato al rilascio: è stata catturata ogni istruzione SQL emessa durante il preflight di tutti i comandi di scrittura allora presenti nel catalogo (due insiemi di argomenti, due ruoli, 178 preflight). Nemmeno un INSERT/UPDATE/DELETE, nemmeno un job in coda, nemmeno un'email; il numero di righe di 31 tabelle e il saldo crediti sono rimasti invariati.
L'exit code è lo stesso che produrrebbe la chiamata reale — eseguibile 0, controllo di conferma 4, conflitto di idempotenza 2, qualsiasi altra cosa 1 — quindi "lg … --dry-run || exit" è un controllo significativo in uno step di CI.
1. Chiamalo con dry_run — Aggiungi "dry_run": true al corpo della richiesta. Validazione, controllo di ruolo e ambito, risoluzione del target e calcolo dei crediti vengono eseguiti; il comando no.
2. Leggi would_execute — È l'unico flag su cui basare la logica. Quando è false, would_stop.at indica dove si fermerebbe una chiamata reale: idempotency, target_precheck, confirmation_gate oppure arguments.
3. Correggi il corpo — arguments.ignored indica i campi che verrebbero scartati in silenzio, missing_required quelli obbligatori che hai omesso, e would_charge quanti crediti verrebbero spesi e se il saldo li copre.
4. Togli dry_run — Ripeti finché would_execute è true, poi rimuovi il flag ed effettua la chiamata reale. La chiave di idempotenza inviata durante il preflight non è stata consumata, quindi la chiamata reale viene eseguita normalmente.
HTTP è sempre 200 — “Il comando fallirebbe” non arriva mai come 4xx — il preflight in sé è riuscito e la previsione è nel corpo. L'eccezione è un rifiuto a livello di trasporto, e lì si comporta esattamente come una chiamata reale: 404 comando sconosciuto, 403 ruolo/ambito, 429 rate limit.
Una chiave con ambito di lettura non può fare il dry run di un comando di scrittura — Riceve 403. Un preflight risponde alla domanda “cosa succede se lo chiamo CON QUESTA CHIAVE, adesso”; dare luce verde a una chiave di lettura e poi un 403 sulla chiamata reale sarebbe proprio la sorpresa che il preflight esiste per evitare.
La chiave di idempotenza non viene consumata — Una chiave inviata durante un preflight non apre alcuna riga nel registro, e un blocco scaduto non viene rilasciato. Quindi invia la chiave che intendi usare davvero: il preflight ti dice se è ancora libera, se riprodurrebbe un'esecuzione precedente o se entra in conflitto con un altro comando.
Si combina con confirm — Invia dry_run e confirm insieme e la domanda diventa “se confermo, cosa succede?”. Anche così non viene eseguito nulla.
Il preflight di un batch vale per l'intero batch — Anche commands:batch accetta dry_run, ma il flag appartiene al batch, non a una singola voce (inviarlo su una voce dà 422). Ricevi un rapporto per ogni voce più il costo totale in crediti del batch; un saldo insufficiente viene segnalato, non rifiutato.
Non è gratuito — Ogni preflight esegue query reali (anteprima, saldo) e conta ai fini del rate limit. Non fare il preflight dell'intero catalogo a ogni deploy; fai il preflight dei comandi che hai modificato.
Idempotenza: perché ritentare non crea duplicati
Un ERP non legge il tuo messaggio di errore, non vede il tuo schermo e reinvierà la stessa richiesta dopo un timeout. Questa sezione esiste esattamente per questo comportamento.
Una chiamata con un idempotency_key viene eseguita al massimo una volta. La seconda chiamata non riesegue il comando; restituisce il risultato registrato con stato replayed. Quando la rete cade, quando una richiesta va in timeout o quando una coda prende due volte lo stesso job, ricevi il primo risultato invece di una fattura duplicata.
Usa una chiave su ogni comando di scrittura. Il campo read_only del catalogo ti dà questa distinzione gratis: ogni comando con read_only: false merita una chiave di idempotenza.
La tua strategia di retry dovrebbe usare un backoff esponenziale e portare la STESSA chiave a ogni tentativo. Generare una chiave nuova per ogni tentativo equivale a non usare affatto l'idempotenza. Non inviare la stessa chiave in parallelo: l'esecuzione al massimo una volta è garantita per retry sequenziali, non per due richieste in competizione tra loro.
Trappola 1 — anche il fallimento resta bloccato — Se la prima esecuzione è stata rifiutata da una regola di business (failed), una seconda chiamata con la stessa chiave restituisce lo stesso errore e lo stesso error_key, e non ritenta. Per correggere l'argomento e riprovare serve una chiave NUOVA. Una chiave rappresenta un tentativo, non un'intenzione.
Trappola 2 — un risultato grande viene riprodotto senza corpo — Il registro memorizza un risultato solo se è inferiore a 64 KB. Un risultato più grande viene riprodotto con stato replayed ma con il corpo vuoto. La tua integrazione dovrebbe basarsi sul segnale “replayed” anziché sul corpo, e recuperare i dati con il comando get corrispondente.
Trappola 3 — una chiave appartiene a un solo comando — Inviare la stessa chiave con un comando diverso restituisce 409 idempotency_conflict con il conflicting_command; non viene eseguito né riprodotto nulla. Un client che condivide una chiave tra due verbi è difettoso, e lo scopre da un errore, non da un replay silenzioso.
Trappola 4 — il blocco dura 24 ore, non per sempre — Dopo 24 ore la stessa chiave dà luogo a una nuova esecuzione. I retry di rete arrivano nel giro di minuti; i numeri di documento ricorrenti ogni anno in un ERP non devono restare “replayed” per sempre. Il catalogo pubblica la finestra come idempotency_ttl_hours.
Trappola 5 — un errore del server non blocca la chiave — Un 5xx server_error non è un rifiuto di business: la chiave non viene vincolata, quindi un retry con la stessa chiave esegue davvero il comando. Solo failed blocca (trappola 1).
Ambito e formato — la tua azienda, qualsiasi stringa, meglio un UUID — L'unicità è applicata su (la tua azienda, chiave): l'INV-1001 di un altro tenant non collide mai con il tuo e non può mai riprodurre il tuo risultato. Usa un semplice UUID o una chiave composta unica per costruzione, come {ERP-document-no}:{verb}.
Sync incrementale e paginazione
Un bridge ERP/CRM dovrebbe scaricare ciò che è cambiato, non tutto ogni ora. Ogni comando di elenco — loads list, demands list-own, contacts list, invoices list, teammates list, load-groups list, reservations list, drivers list, tenders list, products search, warehouses search — accetta due parametri comuni e restituisce un campo comune.
Perché non c'è un offset: su una tabella live un offset scivola. Una riga inserita tra due pagine ti fa saltare o contare due volte un record, in silenzio. Il cursore va solo in avanti, quindi un record inserito o aggiornato a metà percorso finisce in fondo all'elenco: non si perde nulla, non si duplica nulla.
Un caricamento iniziale completo usa lo stesso meccanismo: parti da updated_since=1970-01-01T00:00:00Z e segui next_cursor finché non è null. Non esiste un endpoint di “esportazione” separato perché non serve.
Lo stesso con lg: lg loads list --updated_since=2026-09-01T00:00:00Z --limit=100 --json, poi lg loads list --cursor= --json.
Per la sync successiva imposta updated_since sul valore di updated_at più alto che hai visto. I timestamp hanno una precisione di un secondo, quindi un record sul confine può arrivare due volte — innocuo purché dalla tua parte tu faccia upsert per external_ref o code. Senza updated_since né cursor un comando gira in modalità chat: ordinamento pensato per le persone, al massimo 20 righe, next_cursor null e truncated che dice “c'è altro”. Non usare quella modalità per la sync.
Chiavi di errore leggibili dalle macchine per questa sezione: INVALID_CURSOR, INVALID_UPDATED_SINCE, DUPLICATE_EXTERNAL_REF, EXTERNAL_REF_TOO_LONG, EXTERNAL_REF_INVALID. Tutte rispondono HTTP 422 con error_code: "failed" e result.error_key nel corpo. Basa la logica sulla chiave, mai sul testo.
updated_since — Timestamp ISO-8601 (consigliato UTC, ad es. 2026-09-01T00:00:00Z). Le righe aggiornate in quell'istante o dopo. Porta il comando in modalità sync: ordine fisso (updated_at, id) crescente, limit con un massimo di 100.
cursor — Il next_cursor della risposta precedente, così com'è. È opaco e firmato: non costruirne né modificarne mai uno, non riutilizzare mai il cursore di un'altra azienda o di un altro comando; tutti questi casi vengono rifiutati con INVALID_CURSOR.
limit — Dimensione della pagina. 1-100 in modalità sync (predefinito 10).
next_cursor (risposta) — Cursore per la pagina successiva. null significa che l'elenco è completo; è l'unica risposta corretta alla domanda “c'è altro?”.
total (risposta) — Righe che corrispondono ai filtri, indipendentemente dalla pagina — per mostrare l'avanzamento.
La tua chiave: external_ref
Non usare i nostri id auto-incrementali (invoice_id, contact_id) come chiave di business nel tuo ERP; sono opachi e privati della tua azienda. Carichi, richieste, contatti, fatture, prodotti e magazzini portano invece la tua chiave.
Impostala in scrittura — loads create, demands create, contacts create e contacts update, invoices create accettano un external_ref facoltativo (massimo 120 caratteri) e lo restituiscono invariato.
Usala in lettura — loads get --external_ref=ORD-2026-0917, invoices get --external_ref=..., contacts get --external_ref=..., demands get --external_ref=... funzionano tutti; nei comandi di elenco e di ricerca --external_ref= è un filtro a corrispondenza esatta.
Unica per azienda — Un secondo record con la stessa chiave viene rifiutato con 422 e result.error_key = DUPLICATE_EXTERNAL_REF; la chiave di un'altra azienda per te risponde “non trovato”. Il confronto non distingue maiuscole e minuscole (ord-1 = ORD-1). Un record archiviato mantiene la sua chiave; ripristinalo prima di riutilizzare la chiave.
Invia anche un idempotency_key — Un retry dopo un timeout di rete restituisce il primo risultato invece di creare un duplicato. I due non sono intercambiabili: external_ref è la tua chiave di business, idempotency_key identifica un singolo tentativo.
Webhook in uscita: quando succede qualcosa, facciamo noi una POST verso di te
Fin qui era tutto pull: tu chiedi, noi rispondiamo. Un bridge ERP doveva chiedere una volta al minuto per sapere che un carico aveva cambiato stato, che una fattura era stata emessa o che era arrivata un'offerta. Non più: registra un indirizzo https, scegli gli eventi che ti interessano e quando accadono arriva una POST firmata.
Il push è stato aggiunto ACCANTO al pull, non al suo posto. La sync incrementale (updated_since + cursore) è intatta ed è ancora lo strumento giusto: il primo caricamento completo, il recupero dello storico e la risposta a “mi sono perso qualcosa?” stanno tutti lì. I webhook riducono la latenza da minuti a secondi. Un bridge sano usa entrambi — il webhook come innesco, la sync come rete di sicurezza.
Il payload è un SEGNALE, non una copia del record. Contiene gli identificativi (id, il tuo external_ref, stato, orario); il dettaglio lo recuperi con la tua chiave via GET, e quella chiamata passa già dai tuoi controlli di autorizzazione. La superficie di esposizione resta quindi a livello di identificativi. Due campi mancano deliberatamente: l'identità dell'azienda che ha presentato un'offerta (le offerte cieche compaiono nel pannello con uno pseudonimo; mettere l'identità in un webhook infrangerebbe quella riservatezza attraverso un secondo canale) e i dati di contatto delle prenotazioni (non serve far passare dati personali da un canale in più).
I nomi degli eventi sono CONGELATI. Se il significato di un nome cambia, si apre un nome nuovo e quello vecchio sopravvive per una finestra di deprecazione. Aggiungere un nuovo campo al payload NON incrementa la versione del contratto — un consumatore deve ignorare i campi che non conosce.
GET /api/common/integration-webhooks — Il registro più il catalogo degli eventi, i limiti e i nomi degli header. Ogni riga riporta il motivo del silenziamento e un riepilogo delle consegne degli ultimi 7 giorni.
POST /api/common/integration-webhooks — 201 + { webhook, secret, shown_once: true }. Il segreto compare solo qui.
PATCH /api/common/integration-webhooks/{uuid} — Nome / indirizzo / eventi / flag di attivazione. NON tocca il segreto.
DELETE /api/common/integration-webhooks/{uuid} — La rimuove: la riga viene eliminata in modo logico (soft delete, lo storico resta consultabile) e le consegne in sospeso vengono annullate.
POST /api/common/integration-webhooks/{uuid}/rotate-secret — 201 + un nuovo segreto. Il vecchio valore smette di funzionare in quell'istante.
POST /api/common/integration-webhooks/{uuid}/test — Un evento ping — firma reale, percorso reale, piano dei tentativi reale.
GET /api/common/integration-webhooks/{uuid}/deliveries — Le consegne più recenti: stato, numero del tentativo, codice HTTP, durata, etichetta di errore.
POST /api/common/integration-webhooks/deliveries/{uuid}/replay — Reinvia una singola consegna: event_id viene MANTENUTO, l'id della consegna è nuovo, il payload viene copiato così com'è.
Catalogo degli eventi
Ognuno dei 13 eventi qui sotto è coperto da una classe di evento EFFETTIVAMENTE emessa. Nel catalogo non ci sono nomi “che sarebbe bello avere”: un evento annunciato ma mai emesso è un evento che l'integratore aspetta per sempre, ed è un fallimento silenzioso. Neanche questa tabella è scritta a mano — viene ricavata dal catalogo live a ogni caricamento della pagina.
invoice.payment_recorded è deliberatamente ASSENTE: quella classe di evento esiste nel codice ma non viene emessa da nessuna parte. L'evento di pagamento verrà aggiunto il giorno in cui la classe verrà davvero emessa — non prima. Annunciare un evento in anticipo è peggio che non aggiungerlo mai.
load.created — A load became visible to your company (created by you or shared with you). (load)
load.status_changed — A load moved to a new status (pending, in_transport, transit, done). (load)
load.driver_assigned — A driver was assigned to a load. (load)
demand.created — A freight demand was created by your company. (demand)
demand.status_changed — A freight demand changed status. (demand)
demand_bid.created — A bid was placed on a demand you are party to. (demand_bid)
demand_bid.revised — A bid was revised (a new revision replaced the previous one). (demand_bid)
demand_bid.accepted — A bid was accepted. (demand_bid)
invoice.created — An invoice draft was created. (invoice)
invoice.issued — An invoice was issued (it now carries an invoice number). (invoice)
invoice.cancelled — An invoice was cancelled. (invoice)
warehouse_reservation.created — A warehouse dock/area reservation was created. (warehouse)
warehouse_reservation.status_changed — A warehouse reservation was approved, rejected or otherwise moved. (warehouse)
Verificare la firma
Ogni richiesta porta un header X-Logistivo-Signature: t=,v1=. La stringa firmata è "." (il corpo grezzo) e l'algoritmo è HMAC-SHA256. Il prefisso v1 rende lo schema versionabile: se un giorno arrivasse un secondo schema, l'header riporterebbe t=…,v1=…,v2=… e tu sceglieresti quello che conosci.
Pubblichiamo due ricevitori di riferimento senza dipendenze, uno per Node e uno per PHP puro. Entrambi applicano le quattro regole qui sopra e si verificano da soli con --selftest: firma valida, corpo manomesso, segreto sbagliato, timestamp fuori finestra, header malformato, la trappola della riserializzazione ed entrambi i tipi di ripetizione (stessa consegna / stesso fatto). Il verificatore è l'esatta controparte del codice che usiamo noi stessi — consumiamo il contratto che pubblichiamo.
Verifica il corpo GREZZO — La firma è calcolata sui byte. Decodificare e riserializzare il corpo (JSON.stringify(req.body), json_encode($request->all())) trasforma gli stessi DATI in BYTE diversi e la firma smette di corrispondere. In Node la trappola è la formattazione dei numeri (1.50 sul filo diventa 1.5; i numeri interi grandi perdono precisione), in PHP è l'escape dei caratteri (/ diventa \/, İ diventa \u0130). Usa express.raw in Express e $request->getContent() in Laravel. È l'errore più comune in assoluto quando si scrive un ricevitore.
Controlla il timestamp — t è DENTRO la firma. Verificare solo la firma permette a chiunque abbia intercettato una richiesta valida di riprodurla ore dopo, e il ricevitore la conterebbe come evento verificato. Scarta ogni richiesta in cui |now − t| > tolleranza, anche se la firma è corretta. La finestra consigliata è di 300 secondi.
Confronta in tempo costante — hash_equals / timingSafeEqual. Confrontare con == permette a un attaccante di indovinare la firma byte per byte.
Deduplica su event_id, non su id — event_id identifica il FATTO: è lo stesso per due iscritti che ricevono lo stesso evento, e viene MANTENUTO nel replay. id (= X-Logistivo-Delivery) identifica la CONSEGNA e cambia nel replay. Rispondi alla domanda “l'ho già gestito?” con event_id; rispondere con id fa sì che un replay esegua due volte lo stesso lavoro.
Consegna, tentativi e silenziamento
Il tuo ricevitore non sarà sempre attivo. Il sistema lo dà per scontato: un errore temporaneo entra nel piano dei tentativi, uno permanente silenzia la sottoscrizione — e il MOTIVO del silenziamento viene sempre registrato.
Il motivo del silenziamento è leggibile dalle macchine e stabile (delivery_failures, endpoint_gone, unsafe_target, key_revoked, by_user) e compare sia nel pannello sia in `lg webhooks list`. Un silenziamento senza motivo lascerebbe senza risposta la domanda “perché non arriva niente?”. La riattivazione azzera il contatore e il timbro.
Tu scrivi l'indirizzo; è il NOSTRO server a fare la richiesta. Senza un controllo, un tenant che inserisse l'indirizzo di metadati di un cloud potrebbe farci emettere richieste dall'interno della nostra rete. Per questo l'indirizzo viene verificato sia al momento della registrazione sia a OGNI consegna:
Timeout — 8 s in totale, 4 s per la connessione — un ricevitore lento non deve occupare un worker. Metti il lavoro in coda e rispondi subito 2xx.
Piano dei tentativi — 60 · 300 · 1800 · 7200 · 21600 secondi → 6 tentativi, una finestra di circa 8,6 ore.
L'unico errore permanente: 410 Gone — Significa “cancellami”: nessun nuovo tentativo, la sottoscrizione viene silenziata subito. Non restituire MAI 410 per un errore di firma.
Ogni altro errore — Vengono ritentati TUTTI, 4xx compresi. Perdere un evento di business costa più di qualche richiesta in più: un ricevitore che restituisce 403 mentre si aggiorna una regola WAF perderebbe in silenzio un evento “fattura emessa” su un sistema che tratta i 4xx come permanenti.
Retry-After — Rispettato su 429 e 503 (con un massimo di 6 ore).
Redirect — NON vengono seguiti. Saltare a un indirizzo interno tramite un 302 aggirerebbe il controllo degli indirizzi per una seconda via.
Silenziamento automatico — Dopo 10 consegne consecutive esaurite. Un 410, una destinazione non sicura e la revoca della chiave di integrazione collegata silenziano SUBITO.
solo https, solo le porte 443/8443, credenziali incorporate (https://user:pass@…) rifiutate;
localhost, nomi a etichetta singola e suffissi interni come .internal / .local / .svc vengono rifiutati — l'intento viene rifiutato prima ancora di guardare il risultato della risoluzione, quindi un DNS split-horizon non può aggirare il controllo;
gli IP letterali e TUTTI i record della risoluzione DNS devono essere pubblici. Se un nome si risolve sia in un indirizzo pubblico sia in uno privato, nessuno ci chiede quale scegliere → il nome viene rifiutato senz'altro;
al momento della consegna l'indirizzo viene risolto una sola volta e la connessione viene vincolata all'indirizzo verificato: la finestra del DNS rebinding è chiusa;
il CORPO della risposta del ricevitore non viene mai memorizzato da nessuna parte (solo codice di stato, durata e una breve etichetta di errore) — così il percorso di “lettura”, che è ciò che vale davvero una falla nel controllo degli indirizzi, resta chiuso.
Deliberatamente NON esiste un'opzione di configurazione per “consentire indirizzi privati”: un'opzione del genere un giorno resta attiva per sbaglio.
Viene restituito UNA SOLA VOLTA, solo alla creazione della sottoscrizione e con rotate-secret. È memorizzato cifrato sul server e non può mai essere riletto; non esiste un “mostra di nuovo”.
lg lo stampa a schermo e lo lascia lì — non lo scrive in alcun file di configurazione o di cache.
Se lo perdi, lo ruoti; il vecchio valore smette di funzionare IN QUELL'ISTANTE. Per un passaggio senza interruzioni, durante la transizione il tuo ricevitore dovrebbe provare entrambi i segreti.
Cambiare l'indirizzo NON tocca il segreto: una manutenzione ordinaria come “l'URL si è spostato” non deve rompere la verifica dal lato ricevente.
Salute e stato: nessuno dovrebbe accorgersi di un bridge silenzioso prima di te
Un bridge di integrazione raramente muore in modo rumoroso. Di solito si zittisce nelle ore piccole: un token scade, la persona per conto della quale agisce la chiave lascia il team, un ambito viene ristretto, oppure l'endpoint ricevente inizia a restituire 403. Il primo ad accorgersene è quasi sempre il cliente. lg status esiste per invertire quest'ordine.
Un solo comando risponde a due domande contemporaneamente, perché durante un'interruzione vengono poste entrambe nello stesso momento: la piattaforma è attiva, e il mio bridge è sano? La riga della piattaforma funziona senza token — durante un guasto il primo sospettato è proprio il token, e legare la domanda sullo stato al token ti lascerebbe senza risposta esattamente quando ti serve.
Il riepilogo di salute non tiene alcun registro nuovo; riunisce in un'unica frase tre fonti esistenti: il contatore di utilizzo giornaliero (quante chiamate hai fatto e quante sono fallite), il registro delle richieste (quale richiesta, quando e perché è stata rifiutata) e il registro delle consegne dei webhook in uscita (l'evento è arrivato al ricevitore?). Il tasso di errore viene sempre letto dal contatore giornaliero; il registro di dettaglio ha un limite e lo dice chiaramente quando il limite viene raggiunto.
Lo stesso riepilogo compare nel pannello: in Settings › Integration › Keys ogni riga ha un badge e, sotto, il motivo. Le soglie non vengono calcolate lato client; il livello assegnato dal server è quello che mostrano sia il pannello sia lg status, quindi le due schermate non possono mai dire cose diverse sulla stessa chiave.
Il tuo sistema di monitoraggio non ha bisogno di un token. L'endpoint restituisce solo parole di stato; non contiene versione, nome host, nome della coda, numero di job, testo degli errori o dati dei clienti — e non può contenerli.
Il riepilogo di salute viene prodotto con un numero costante di query per richiesta; il numero di query non cresce con il numero di chiavi. Per il dettaglio, leggi le richieste recenti di quella chiave con lg logs e il bridge in uscita con lg webhooks list.
FUNZIONANTE — Nessun guasto misurato e abbiamo una prova di successo: una chiamata riuscita nel registro, oppure traffico rimasto privo di errori nel contatore.
ATTENZIONE — Qualcosa ha iniziato a rompersi: il tasso di errore o la serie di fallimenti consecutivi ha superato una soglia, le richieste vengono rifiutate al controllo, la chiave è vicina alla scadenza, oppure un bridge che comunicava regolarmente è diventato silenzioso.
IN ERRORE — Il bridge non funziona in questo momento: il token è stato revocato involontariamente, una chiave chiusa viene ancora chiamata, ci sono cinque fallimenti di fila, il tasso di errore supera il cinquanta per cento, oppure una sottoscrizione webhook è stata silenziata.
CHIUSO — La chiave è stata chiusa deliberatamente e nessuno la sta chiamando. È una decisione, non un guasto — e non viene colorata di rosso.
NESSUN DATO — Non c'è alcuna misurazione: la chiave non è mai stata chiamata, oppure la misurazione stessa è fallita. Nessuno dei due casi è verde.
Nessun falso verde. Il badge FUNZIONANTE richiede una prova di successo misurata; una chiave mai chiamata non diventa mai verde, perché nemmeno una misurazione dimostra che funziona.
Nessun falso rosso. Le chiavi che hai chiuso di proposito compaiono come CHIUSO. Colorare tutto di rosso rende il rosso privo di significato; una chiave chiusa diventa rossa solo se viene ancora chiamata dopo la chiusura — e allora un bridge è davvero rotto.
Non riuscire a misurare non equivale a non avere dati. Se una query fallisce lato server, la riga non mostra zero in silenzio; dice che non è stato possibile effettuare la misurazione.
Il silenzio viene sempre segnalato ma mai trasformato alla cieca in un avviso. Un bridge di fine mese che tace per trenta ore è normale; un bridge che ha comunicato in almeno cinque degli ultimi sette giorni e poi tace è un guasto. Il ritmo viene misurato, non presunto.
La query di stato stessa non inquina i numeri di salute. Le chiamate fatte da lg status compaiono nel registro delle richieste ma sono escluse dal calcolo della salute — altrimenti la tua stessa query di stato riuscita azzererebbe la serie di fallimenti e nasconderebbe proprio il guasto che la schermata esiste per mostrare.
Ogni riga è misurata: sul database viene eseguita una query reale, il catalogo dei comandi viene costruito davvero, il record live del worker della coda viene letto davvero. Nulla è presunto.
Anche la risposta stessa è una misurazione: se riesci a leggere il corpo, il livello web è attivo.
Il livello superiore deriva solo dai componenti obbligatori. Quando la coda si ferma la risposta è degraded, non down — una chiamata API sincrona non ha bisogno della coda, e dichiarare la piattaforma down sarebbe un falso allarme.
Quando lo stato della coda non può essere misurato, il livello superiore resta invariato: non sapere non equivale a misurare che qualcosa è rotto.
Se la piattaforma è down l'endpoint restituisce HTTP 503. Il corpo è privo di envelope, così gli strumenti di monitoraggio possono dare l'allarme senza analizzarlo, e la risposta non viene mai memorizzata in alcuna cache.
Errori ed exit code
Ciò su cui una macchina basa le sue decisioni è una stringa stabile. Il testo nel campo error è rivolto a una persona, è localizzato e cambia senza preavviso — un'integrazione che decide in base al testo del messaggio non è supportata, e il fatto che si rompa non è un bug.
Due tassonomie, due campi. error_code è il livello di trasporto (la tabella qui sopra) ed è il primo su cui basare la logica. error_key è la chiave stabile della regola di business dentro failed — INSUFFICIENT_CREDITS, NOT_FOUND, DUPLICATE_CONTACT, INSUFFICIENT_STOCK — pubblicata come dizionario nel catalogo (error_keys) e qui sotto. Un comando che non emette ancora una chiave restituisce error_key: null; tratta una chiave assente dal dizionario come un fallimento generico.
ok — HTTP 200 · error_code — · CLI 0 · —
replayed — HTTP 200 · error_code — · CLI 0 · Replay idempotente; il lavoro NON è stato eseguito di nuovo.
failed — HTTP 422 · error_code failed · CLI 1 · No — l'ha rifiutato una regola di business (vedi error_key). Inutile finché l'argomento non cambia.
idempotency_conflict — HTTP 409 · error_code idempotency_conflict · CLI 2 · No — la chiave è stata usata la prima volta per un altro comando (conflicting_command). Genera una nuova chiave.
forbidden — HTTP 403 · error_code forbidden · CLI 3 · No — controllo del ruolo, oppure una chiave con ambito di lettura su un comando di scrittura.
not_found — HTTP 404 · error_code not_found · CLI 2 · No — nome del comando errato o rimosso.
(schema) — HTTP 422 · error_code invalid_request · CLI 2 · No — il corpo della richiesta o un argomento non ha superato la validazione dello schema (errors{}); non è una regola di business.
server_error — HTTP 500 · error_code server_error · CLI 6 · Sì — backoff esponenziale con la STESSA chiave di idempotenza; la chiave non è stata bloccata.
401 unauthenticated — Il token è scaduto o è stato revocato. Ritentare non serve; il token va sostituito.
429 rate_limited — Rate limit raggiunto per questo token. La risposta riporta sempre Retry-After e un corpo con retry_after, limit e bucket; rispettalo invece di inventare un ritardo fisso. lg attende e ritenta fino a tre volte, poi termina con 5.
5xx server_error / errore di rete — Ritenta con backoff esponenziale e la STESSA chiave di idempotenza. Cambiare la chiave riesegue un lavoro che il server potrebbe aver già completato. lg ritenta tre volte (1 s, 2 s, 4 s), poi termina con 6 e con error_code network_error o server_error.
Promessa di stabilità
La domanda più costosa in un contratto di integrazione è “il codice che scrivo oggi funzionerà ancora domani?”. Risponde un solo numero: contract_version nel catalogo, e l'header X-Contract-Version in ogni risposta. Risponde esattamente a una domanda — il codice scritto in precedenza funziona ancora senza modifiche? Se il numero non è aumentato, sì. Se è aumentato, no: qualcosa su cui facevi affidamento è stato rimosso o ristretto.
Perché un annuncio non rimuove nulla: il codice esistente funziona esattamente come prima, anche il giorno dopo. Incrementare la versione all'annuncio emetterebbe due segnali per una sola modifica e ti abituerebbe a ignorare il primo — indebolendo il segnale che conta davvero. L'annuncio viaggia già sulla chiamata che stai facendo: deprecated_at e replaced_by sulla riga del catalogo, un header X-Deprecated più un blocco deprecated nella risposta di quel comando, e un avviso di una riga su stderr se usi lg. Non devi fare nulla per sapere che qualcosa sta per sparire; è già nel tuo log.
Tra l'annuncio e la rimozione passano almeno due trimestri di calendario. Per tutta la finestra il vecchio comando risponde ancora, e avvisa a ogni chiamata. Quando un nome CLI viene ritirato, il suo successore ne eredita il nome come alias: durante la finestra il vecchio nome raggiunge il vecchio comando, e il giorno in cui viene rimosso la stessa chiamata arriva a quello nuovo — senza che tu debba rilasciare una nuova versione del client.
preview_invoice → get_invoice (annunciato il 3 settembre 2026). get_invoice restituisce lo stesso blocco di anteprima e aggiunge le righe, il dettaglio delle imposte, i pagamenti registrati, il saldo residuo e l'accesso tramite la chiave del tuo ERP (external_ref). preview_invoice continua a funzionare, così come lg invoices preview — entrambi avvisano.
nessuna variazione — Un nuovo comando · un nuovo parametro FACOLTATIVO · un nuovo campo di risposta · una nuova chiave di errore · un nuovo endpoint — Non fare nulla. Devi ignorare i campi che non conosci; un parser che fallisce su un campo sconosciuto non è conforme.
nessuna variazione — Un ANNUNCIO di deprecazione: l'avviso che un comando sta per sparire — Il tuo codice continua a funzionare. Metti un'attività in calendario — la finestra è di almeno 6 mesi.
aumenta — Rimozione di un comando · ritiro di un vecchio nome CLI · eliminazione di un campo di risposta · un parametro facoltativo che diventa obbligatorio · restringimento di un enum — Significa che hai mancato la finestra; l'avviso ti era arrivato in tre punti diversi.
Il nome API di un comando (come list_loads) è congelato per sempre; è il nome che usi nelle chiamate HTTP.
error_code (trasporto) ed error_key (regola di business) sono stringhe stabili. Possono comparirne di nuove — tratta una chiave che non trovi nel dizionario come un fallimento generico, non come una rottura.
La corrispondenza tra lo stato HTTP e il campo status nel corpo è fissa.
Il numero di versione non diminuisce mai ed è leggibile in ogni risposta — compresi i 304 e i 429 senza corpo.
Il TESTO degli errori e delle descrizioni. È localizzato e cambia senza preavviso; decidere in base al testo del messaggio non è supportato.
L'assenza di campi che non conosci. Aggiungere un campo non incrementa la versione.
Gli id auto-incrementali come chiavi di business. Porta la tua chiave con external_ref.
Le chiavi di errore dinamiche derivate dai nomi delle classi; non fanno parte del contratto.
Tabella delle identità dei comandi
La tabella qui sotto non è scritta a mano: viene generata dal registro live dei comandi ogni volta che questa pagina viene servita. Un comando aggiunto sul server compare qui da solo. La colonna “Controllo” ti dice se un comando chiede conferma e se il suo effetto può essere annullato; la colonna “Ruoli” ti dice quali tipi di account lo troveranno nel loro catalogo. I badge segnalano i comandi che richiedono una chiave di livello manager, quelli che accettano un file e quelli che si eseguono solo da lg.
Il nome API (list_loads) è congelato e non cambierà; è il nome che usi nelle chiamate HTTP. L'identità CLI (loads list) è regolata dalla politica di versioning: una volta annunciata cambia solo con un incremento di versione e una finestra di migrazione, durante la quale il catalogo serve la vecchia coppia come alias. Le descrizioni qui provengono dal record di ciascun comando e sono abbreviate — per il testo completo, i tipi dei parametri e i valori enum, leggi l'endpoint del catalogo oppure esegui lg help . I comandi riservati agli affiliati non sono elencati qui; un account affiliato li vede nel proprio catalogo.
lg account-settings get — Read the account settings (Settings → Account): the company display name (and legal name, read-only), the signed-in user's own name and e-mail (e-mail is read-only here), the saved load code prefix and how the company… (lettura · — · committente · API: get_account_settings) [chiave manager]
lg account-settings update — Change account settings (Settings → Account): company_name (the company's display name, company-wide), first_name / last_name (the signed-in user's own name — when only one is given the other part is kept),… (scrittura · conferma · committente · API: update_account_settings) [chiave manager]
lg accounting-settings get — Read the company's accounting and invoicing settings and say whether they are set up (muhasebe ayarları, fatura ayarları, e-fatura / e-invoice profile, KDV / VAT tax regime, fatura numaralandırma serisi / invoice… (lettura · — · tutti · API: get_accounting_settings)
lg accounting-settings set-status — Turn the company's accounting module on or off (muhasebe modülünü aç/kapa). (scrittura · conferma · tutti · API: set_accounting_module)
lg accounting-settings update — Update the company's accounting/invoicing settings (muhasebe ve fatura ayarlarını değiştir): legal name, default currency, provider (local/parasut), country, tax regime (KDV/VAT/GST/none), default invoice line… (scrittura · conferma · tutti · API: update_accounting_settings)
lg addresses list — Loading and delivery addresses already used on this company's previous loads (newest first): address_id, name, street, city and country. query filters by name, street or city. limit 1-50 (default 20). (lettura · — · tutti · API: list_worked_addresses)
lg addresses search — Find a place for a route plan stop: the company's own address book first, then a geocoder (counted against the daily routing allowance) when the book has fewer than 3 hits. (lettura · — · autotrasportatore · API: lookup_address)
lg ai-settings get — Read our company's AI switches (Settings → AI), e.g. ai_file_classify ("AI document analysis"): whether files posted into our load chats are read by AI, sorted into document types and split into company documents, or… (lettura · — · committente · API: get_ai_settings) [chiave manager]
lg ai-settings update — Turn our company's AI switches on or off (Settings → AI) — e.g. "stop AI from analysing the files in our load chats" → settings=[{"slug":"ai_file_classify","enabled":false}]. settings is a list of {slug, enabled}; slugs… (scrittura · conferma · committente · API: update_ai_settings) [chiave manager]
lg announcements list — Show the system announcements Logistivo sent to this user (new features, maintenance, policy changes) — newest first. (lettura · — · tutti · API: list_announcements)
lg announcements mark-read — Mark system announcements as read for this user. (scrittura · — · tutti · API: mark_announcements_read)
lg attachments get — Read a file the user attached to THIS conversation (listed in the user message as [Attachments] with their attachment_uuid). (lettura · — · tutti · API: read_attachment) [accetta un file: attachment_uuid]
lg background-jobs get — Check a background job that another command queued and returned a job_id for (document consistency re-analysis, file classification, tariff inquiry, tariff invoice reading, receipt pack…): status pending / running /… (lettura · — · tutti · API: get_background_job)
lg bank-accounts create — Add one of YOUR OWN company bank accounts to the account book (the accounts you get paid into). (scrittura · conferma + irreversibile · tutti · API: create_company_bank_account) [chiave manager]
lg bank-accounts delete — Delete one of OUR OWN company bank accounts (for example a closed account). (scrittura · conferma + irreversibile · tutti · API: delete_company_bank_account) [chiave manager]
lg bank-accounts extract — Read a supplier's bank accounts (IBAN, bank, holder, currency) from one of ITS invoices and save them on that business contact. (scrittura · conferma + irreversibile · tutti · API: extract_supplier_bank_accounts) [accetta un file: attachment_uuid]
lg bank-accounts list — List bank accounts. (lettura · — · tutti · API: list_bank_accounts)
lg bank-accounts preview — Check an IBAN without saving anything: is it valid (country, length, checksum) and which bank it belongs to (detected offline from the bank code where known). (lettura · — · tutti · API: preview_bank_account_iban)
lg bank-accounts set-default — Make one of OUR OWN bank accounts the default — the IBAN printed on our invoices and e-invoices. (scrittura · conferma + irreversibile · tutti · API: set_default_company_bank_account) [chiave manager]
lg bank-accounts set-status — Confirm or reject a bank account that was read from a document by AI or written by an integration — your own account or a business contact's account (find the ones waiting with list_bank_accounts… (scrittura · conferma + irreversibile · tutti · API: decide_bank_account_verification) [chiave manager]
lg bank-accounts update — Update one of OUR OWN company bank accounts (the accounts customers pay us into): IBAN, bank, account holder, branch code, account number or currency. (scrittura · conferma + irreversibile · tutti · API: update_company_bank_account) [chiave manager]
lg banks list — List the banks of Turkey with their bank_id and SWIFT/BIC code — the bank_id that create_company_bank_account and update_company_bank_account need. (lettura · — · tutti · API: list_banks)
lg bids accept — Accept a carrier's bid on one of this company's demands. (scrittura · conferma + irreversibile · committente · API: accept_demand_bid)
lg bids calculate — Before bidding: what this carrier would earn and how many credits a bid would cost if the customer accepts it. (lettura · — · autotrasportatore · API: calculate_bid_earnings)
lg bids cancel — Withdraw (geri çek) one of THIS carrier company's PENDING bids. (scrittura · conferma + irreversibile · autotrasportatore · API: cancel_demand_bid)
lg bids create — Submit a bid (teklif ver) on an open demand. amount_per_vehicle is the freight PER VEHICLE, not the total. (scrittura · conferma + irreversibile · autotrasportatore · API: create_demand_bid)
lg bids get — Detail of ONE bid this carrier company submitted: demand, status (pending / accepted / revised / cancelled / price_too_high), price per vehicle and total, currency, vehicle count, customs included or customs price,… (lettura · — · autotrasportatore · API: get_my_demand_bid)
lg bids list — List the bids (teklif) THIS carrier company has submitted, newest first, with their outcome. (lettura · — · autotrasportatore · API: list_my_bids)
lg bids revise — Revise this carrier's own PENDING bid on a demand: the old bid is marked revised and a NEW bid replaces it (it gets a new bid code). (scrittura · conferma + irreversibile · autotrasportatore · API: revise_demand_bid)
lg carbon-reports calculate — Calculate the CO2 emission of an EXISTING load (load_code: weight and route from the load, including its Ro-Ro leg) OR of a route you describe (transport_mode road|roro + weight_kg + departure_address + arrival_address,… (lettura · — · tutti · API: calculate_load_carbon_emission)
lg carbon-reports download — Export ALL of the company's saved CO2 emission reports to one Excel file (one row per report: date, route, mode, weight, distance, emission, factor, method) and return a short-lived download link. (lettura · — · tutti · API: export_carbon_emission_reports)
lg carbon-reports generate — Produce the signed CO2 emission report (PDF, with QR code) for a load OR for a route, save it to the company's report list and return a download link. (scrittura · conferma + irreversibile · tutti · API: generate_carbon_emission_report)
lg carbon-reports get — Read one CO2 emission report in full: total emission in kg, transport mode, weight, distance, emission factor, calculation method and source, the departure/arrival addresses, the leg breakdown for multi-modal routes… (lettura · — · tutti · API: get_carbon_emission_report)
lg carbon-reports list — List the CO2 emission reports this company has generated (newest first): report number, file name, who created it and when. (lettura · — · tutti · API: list_carbon_emission_reports)
lg carrier-routes get — This carrier's route definitions (Rota Yönetimi): the countries served — always ↔ Türkiye in both directions — and the vehicle types and load types operated, with ids and names. (lettura · — · autotrasportatore · API: get_carrier_routes)
lg carrier-routes set — REPLACE this carrier's route definitions (Rota Yönetimi) with the given FULL sets: countries served (each to/from Türkiye, both directions), vehicle types and load types. (scrittura · conferma · autotrasportatore · API: set_carrier_routes) [chiave manager]
lg chart-of-accounts list — List the chart of accounts available to this company (Turkish uniform chart: 100 Kasa, 102 Bankalar, 120 Alıcılar, 320 Satıcılar, 391 Hesaplanan KDV, 600/601 Satışlar…), optionally filtered by code/name text or type. (lettura · — · tutti · API: list_chart_of_accounts)
lg checks assign-invoices — Allocate a pending, field-confirmed cheque to one or more open LOCAL invoices of the same contact and currency: in = sales invoices (collection), out = purchase invoices (payment). (scrittura · conferma + irreversibile · tutti · API: attach_check_to_invoices) [chiave manager]
lg checks bounce — Record that a cheque BOUNCED (came back unpaid). (scrittura · conferma + irreversibile · tutti · API: mark_check_bounced)
lg checks cancel — CANCEL a pending cheque (e.g. registered by mistake, returned before use): no journal entry is written and any invoice reservation is released. (scrittura · conferma + irreversibile · tutti · API: cancel_settlement_check) [chiave manager]
lg checks collect — Record that a cheque was COLLECTED (money reached the bank for an incoming cheque, or left the bank for an outgoing one) on its due date. (scrittura · conferma + irreversibile · tutti · API: mark_check_collected)
lg checks create — Register a cheque in the cheque portfolio. (scrittura · conferma · tutti · API: create_settlement_check) [chiave manager] [accetta un file: front_attachment_uuid, back_attachment_uuid]
lg checks get — Read one cheque in full: its identity (number, serial, bank and branch, drawer with tax number, IBAN), the face amount and currency, issue and due dates, the counterparty, the status with every timestamp (executed,… (lettura · — · tutti · API: get_settlement_check)
lg checks list — List the cheque portfolio of this company: cheque number, direction (in = received from a customer, out = given to a supplier), drawer and bank, face amount with its currency, issue and DUE date, the counterparty… (lettura · — · tutti · API: list_settlement_checks)
lg checks remove-invoices — Release a pending cheque's invoice allocation: the reservations are removed (invoices become payable again) and the cheque goes back to the unallocated pending cheques. (scrittura · conferma · tutti · API: detach_check_from_invoices) [chiave manager]
lg checks run — EXECUTE a pending, allocated cheque against its invoices: the reservations become payments (the invoice balances close), and the notes receivable (121, received cheque) or notes payable (321, given cheque) journal… (scrittura · conferma + irreversibile · tutti · API: execute_settlement_check) [chiave manager]
lg checks update — Correct a pending cheque's fields and CONFIRM them — the human sign-off on what AI read from the photo (or on a manual entry). (scrittura · conferma · tutti · API: update_settlement_check) [chiave manager]
lg companies add-role — Add a role to this company (firmaya rol ekle): customer (shipper), carrier, customs (customs broker) or affiliate. (scrittura · conferma + irreversibile · tutti · API: add_company_role) [chiave manager]
lg companies delete-logo — Remove this company's logo (firma logosu) from the branded login portal, documents and the panel. (scrittura · conferma + irreversibile · tutti · API: delete_company_logo) [chiave manager]
lg companies get — This company's own profile (firma profili): legal name, tax number and tax office, address and postal code, city/country, payment term (vade), the company roles it has (customer/carrier/customs/affiliate) and the roles… (lettura · — · tutti · API: get_company_profile)
lg companies invite — Invite a company that is NOT on Logistivo yet by e-mail (e.g. a carrier we want to give a load to). (scrittura · conferma + irreversibile · tutti · API: invite_company_to_platform)
lg companies list — Logistivo platform companies this company has already worked with on loads (shared load chats), by company_type: customer (shippers), carrier or customs (customs brokers). (lettura · — · tutti · API: list_platform_companies)
lg companies search — Check whether a company is on Logistivo — by EXACTLY ONE of: tax_number (exact VKN / tax id), vat_number (exact EU/UK VAT number) or email (any e-mail of that company, matched by its domain; then company_type is… (lettura · — · tutti · API: search_platform_companies)
lg companies set-brand-colors — Set the two colours of this company's branded login portal (markalı giriş portalı, /p//login) — primary_color and secondary_color as #RRGGBB hex. (scrittura · conferma · autotrasportatore, doganalista · API: set_company_brand_colors) [chiave manager]
lg companies set-logo — Make an uploaded image this company's logo (firma logosu) — shown on the branded login portal, documents and the panel. attachment_uuid is a JPEG or PNG image (max 8 MB) uploaded to this conversation or with `lg upload`. (scrittura · conferma + irreversibile · tutti · API: set_company_logo) [chiave manager] [accetta un file: attachment_uuid]
lg companies update — Update this company's profile (firma profili) — send ONLY the fields that change: legal_name (ticaret unvanı), tax_number (VKN / VAT id), tax_branch (vergi dairesi), address_street, postal_code, city_id, country_code… (scrittura · conferma · tutti · API: update_company_profile) [chiave manager]
lg company-documents create — File a document the user attached (in this chat, or uploaded to the command surface) as one of the company's own documents (firma evrakı yükle): tax certificate (vergi levhası), signature circulars (imza sirküleri),… (scrittura · conferma · tutti · API: upload_company_document) [accetta un file: attachment_uuid]
lg company-documents delete — Remove one of the company's own documents (tax certificate, signature circular, trade registry gazette, permits…) from its document list — e.g. a wrong or outdated upload. document_id is the one shown by… (scrittura · conferma + irreversibile · tutti · API: delete_company_document)
lg company-documents list — List this company's own filed documents (tax certificate, signature circulars, trade registry gazette, contracts, TIO/L2 permits, files uploaded to chats…) with their type, number, validity date and verification status. (lettura · — · tutti · API: list_company_documents)
lg company-documents list-missing — Which company documents (tax certificate, signature circulars, trade registry gazette, TIO/L2/C2 permits …) this company is REQUIRED to have for its company type and country, which of them are on file and verified, and… (lettura · — · tutti · API: list_missing_company_documents)
lg company-domains create — Add an e-mail domain to our company (e.g. firma.com.tr) and e-mail a 6-digit verification code to a mailbox ON that domain. (scrittura · conferma + irreversibile · tutti · API: create_company_domain) [chiave manager]
lg company-domains delete — Remove one of our UNVERIFIED company domains (e.g. added by mistake). (scrittura · conferma + irreversibile · tutti · API: delete_company_domain) [chiave manager]
lg company-domains list — List our company's e-mail domains (Company settings → Domains): each row has company_domain_id, domain, verified (true once the 6-digit code was entered) and, for unverified ones, the mailbox the last code was sent to. (lettura · — · tutti · API: list_company_domains)
lg company-domains resend — E-mail a NEW 6-digit verification code for one of our unverified company domains (the previous code stops working). (scrittura · conferma + irreversibile · tutti · API: resend_company_domain_code) [chiave manager]
lg company-domains verify — Verify one of our unverified company domains with the 6-digit code that was e-mailed to the mailbox on that domain. (scrittura · conferma + irreversibile · tutti · API: verify_company_domain) [chiave manager]
lg company-relationships accept — Accept a connection proposal another company sent us (relationship_id from list_company_relationships direction=incoming). (scrittura · conferma + irreversibile · tutti · API: accept_company_relationship) [chiave manager]
lg company-relationships create — Send a connection proposal to link one of our business contacts with its company on the Logistivo platform (company_id from search_platform_companies). (scrittura · conferma + irreversibile · tutti · API: create_company_relationship) [chiave manager]
lg company-relationships list — List our company connections on the platform (direction=outgoing, default: the connections in our directory, with status and roles such as carrier/customs_broker/supplier) or the connection proposals other companies… (lettura · — · tutti · API: list_company_relationships)
lg company-relationships reject — Reject a connection proposal another company sent us (relationship_id from list_company_relationships direction=incoming). (scrittura · conferma + irreversibile · tutti · API: reject_company_relationship) [chiave manager]
lg company-relationships revoke — End a company connection we are a party of (either side may end it), or withdraw a pending proposal. (scrittura · conferma + irreversibile · tutti · API: revoke_company_relationship) [chiave manager]
lg contacts add-address — Add an address to a business contact (e.g. a warehouse or branch): a label, the full street address and the country (ISO-2 code); postal code optional. (scrittura · conferma · tutti · API: add_business_contact_address)
lg contacts add-bank-account — Add a bank account (IBAN) to a business contact so it can be used on payment instructions and invoices. (scrittura · conferma + irreversibile · tutti · API: add_business_contact_bank_account)
lg contacts add-person — Add a person (yetkili kişi) to a business contact: first name, last name and e-mail are required; phone, phone country code, job title and a note are optional. (scrittura · conferma · tutti · API: add_business_contact_person)
lg contacts archive — Archive a business contact (cariyi arşivle): it disappears from lists and pickers and becomes read-only, but nothing is deleted — invoices, loads and bank accounts stay linked, and restore_business_contact brings it… (scrittura · conferma · tutti · API: archive_business_contact)
lg contacts create — Create a new business contact (cari) in the company directory. (scrittura · conferma · tutti · API: create_business_contact)
lg contacts delete-address — Delete one of a business contact's addresses. (scrittura · conferma + irreversibile · tutti · API: delete_business_contact_address)
lg contacts delete-bank-account — Delete one of a business contact's bank accounts (for example an old or wrong IBAN). (scrittura · conferma + irreversibile · tutti · API: delete_business_contact_bank_account)
lg contacts delete-person — Delete a person from a business contact, together with that person's notification preferences. (scrittura · conferma + irreversibile · tutti · API: delete_business_contact_person)
lg contacts extract — Read a business card, letterhead or invoice header (image or PDF) and return the company details on it — legal name, tax number and office, VAT number, e-mail, phone, IBAN (checksum-checked, bank detected), address,… (lettura · — · tutti · API: extract_business_contact_from_image) [accetta un file: attachment_uuid]
lg contacts extract-text — Read pasted text (Excel/CSV rows, e-mail signatures, a typed list) and return up to 100 draft records of ONE kind: companies, persons, addresses or bank_accounts. (lettura · — · tutti · API: extract_business_contacts_from_text)
lg contacts get — Read one business contact in full (identity, tax data, address, e-mail/phone, bank accounts, platform link) together with its account summary: ledger balance (positive = they owe us), open receivables and open payables. (lettura · — · tutti · API: get_business_contact)
lg contacts invite — Invite a business contact to join Logistivo by e-mail. (scrittura · conferma + irreversibile · tutti · API: invite_business_contact)
lg contacts list — List the company's business contacts (customers, carriers, suppliers, consignees) with optional text search over name, legal name and tax number. (lettura · — · tutti · API: list_business_contacts)
lg contacts list-addresses — List the saved addresses of one business contact (label, street address, postal code, country) with address_id, needed by update/delete. (lettura · — · tutti · API: list_business_contact_addresses)
lg contacts list-person-notifications — Show which load notifications a contact person receives and on which channel (e-mail, push, SMS), plus the notification types that can be chosen with their allowed channels — use those slugs with… (lettura · — · tutti · API: list_business_contact_person_notifications)
lg contacts list-persons — List the people (yetkili kişiler) saved on one business contact: name, e-mail, phone, job title, note, and which load notifications each one receives. (lettura · — · tutti · API: list_business_contact_persons)
lg contacts list-routes — Show which countries a business contact that is linked to a carrier on the platform serves: its declared route pairs (from-country → to-country) and the distinct country list. (lettura · — · tutti · API: list_business_contact_routes)
lg contacts remove-company-link — Remove the link between a business contact and its company on the Logistivo platform. (scrittura · conferma + irreversibile · tutti · API: unlink_business_contact_company) [chiave manager]
lg contacts restore — Bring an archived business contact back (cariyi arşivden geri al): it returns to lists and pickers and can be edited again. (scrittura · conferma · tutti · API: restore_business_contact)
lg contacts search — Resolve a business contact (customer/partner/recipient) by name, legal name or tax number to its contact_id. (lettura · — · tutti · API: lookup_business_contact)
lg contacts set-default-bank-account — Make one of a business contact's bank accounts its DEFAULT account — the one pre-selected when you pay this contact. (scrittura · conferma + irreversibile · tutti · API: set_default_business_contact_bank_account)
lg contacts set-person-notifications — Turn load notifications on or off for a contact person, per notification type and channel (e-mail, push, SMS). (scrittura · conferma · tutti · API: set_business_contact_person_notifications)
lg contacts update — Update fields of an existing business contact. (scrittura · conferma · tutti · API: update_business_contact)
lg contacts update-address — Correct one of a business contact's addresses. (scrittura · conferma · tutti · API: update_business_contact_address)
lg contacts update-bank-account — Correct one of a business contact's bank accounts: IBAN, account holder, bank name, BIC/SWIFT, currency, label, account type, branch code or account number. (scrittura · conferma + irreversibile · tutti · API: update_business_contact_bank_account)
lg contacts update-person — Correct a contact person's details. (scrittura · conferma · tutti · API: update_business_contact_person)
lg containers calculate — Decode and validate a container number (konteyner numarası) per ISO 6346 — owner code, category, serial, check digit (is it correct, and what it should be) and, when known, the operating line with its public tracking… (lettura · — · tutti · API: decode_container_number)
lg conversations add-file — Post a file into an OFFER (demand-bid) chat as this user — e.g. a price sheet or a vehicle photo for the other company. conversation_code comes from list_conversations (rows whose subject is demand_bid). (scrittura · conferma + irreversibile · tutti · API: send_conversation_file) [accetta un file: attachment_uuid]
lg conversations add-invitation — Invite a person from ANOTHER company into a load chat by e-mail (sohbete dışarıdan davet). (scrittura · conferma + irreversibile · tutti · API: invite_to_conversation)
lg conversations add-message — Post a message into a load/bid conversation AS THIS USER (not as an assistant). (scrittura · conferma + irreversibile · tutti · API: send_conversation_message)
lg conversations add-participants — Add people to a load/demand conversation (sohbete kişi ekle) — "Ayşe'yi FKZ8515 sohbetine ekle". (scrittura · conferma · tutti · API: add_conversation_participants)
lg conversations create — Open the freight chat with a carrier that bid on one of OUR demands (navlun sohbetini başlat) — bid_code comes from get_demand / the bids of a demand. (scrittura · conferma + irreversibile · committente · API: start_bid_conversation)
lg conversations list — List the chat conversations this user is a member of (load chats, bid chats and private carrier channels), newest activity first. (lettura · — · tutti · API: list_conversations)
lg conversations list-files — List the files shared in a load/bid chat, newest first: document type, title, file name, who posted it and when. (lettura · — · tutti · API: list_conversation_files)
lg conversations list-invitations — Show the e-mail invitations to a load chat that have not been accepted yet: who was invited, by whom and when, and what they will be allowed to see. (lettura · — · tutti · API: list_conversation_invitations)
lg conversations list-messages — Read the most recent messages of one conversation — give it a load code (e.g. (lettura · — · tutti · API: list_conversation_messages)
lg conversations list-participants — Who is in this conversation — name and company of every participant. (lettura · — · tutti · API: list_conversation_participants)
lg conversations mark-read — Mark one conversation as read for this user (clears its unread badge), or with all=true every load, bid and direct-message chat at once. (scrittura · — · tutti · API: mark_conversation_read)
lg conversations remove-message — Delete one of THIS user's own messages from a conversation (message_id from list_conversation_messages with `mine` true). (scrittura · conferma + irreversibile · tutti · API: delete_conversation_message)
lg conversations remove-participant — Remove someone from a load/bid chat, cancel a pending e-mail invitation to it, or leave it yourself (give your own user_id). (scrittura · conferma + irreversibile · tutti · API: remove_conversation_participant)
lg conversations update-message — Edit one of THIS user's own messages in a conversation (message_id comes from list_conversation_messages, where `mine` is true). (scrittura · conferma · tutti · API: update_conversation_message)
lg countries search — Resolve a country by name (Turkish, English or the local/native name) or ISO 3166-1 alpha-2 code to its country_id, for the sending/receiving country on a load. (lettura · — · tutti · API: lookup_country)
lg currencies list — The currencies the platform knows (currency_id, code, name, symbol) with the latest exchange rate against the Turkish lira (buying / selling, rate date). currency_id is what forms such as bank accounts take. (lettura · — · tutti · API: list_currencies)
lg custom-reports generate — Custom report counted server-side over ALL records of a dataset: filter, group (dates by month etc.), count/sum/avg/min/max (money per currency) or list rows; format=xlsx|pdf|csv gives a file. (lettura · — · tutti · API: build_report)
lg customs-companies list — Customs broker companies this customer can assign when accepting a bid (accept_demand_bid customs_company_id): the Logistivo customs companies you already work with in your chats. (lettura · — · committente · API: list_customs_companies)
lg customs-locations search — Search customs offices / customs locations (gümrük müdürlüğü, gümrük lokasyonu) by name or street — for the exit and destination customs of a load. (lettura · — · tutti · API: lookup_customs_location)
lg demand-bid-reports get — Bid report across ALL demands at once, counted server-side: for a customer the bids RECEIVED on its demands, for a carrier the bids it PLACED. (lettura · — · committente, autotrasportatore · API: get_demand_bid_report)
lg demand-reports get — Demand report (Talep Raporu) with optional filters: status, demanding company, transport mode, pickup / delivery countries, loading-date window. (lettura · — · committente, autotrasportatore · API: get_demand_report)
lg demand-settings get — This carrier company's demand settings: whether demands opened by forwarder companies reach the company (accept_demands_from_forwarders). (lettura · — · autotrasportatore · API: get_demand_settings) [chiave manager]
lg demand-settings update — Change this carrier company's demand settings. accept_demands_from_forwarders=false stops demands opened by forwarder companies from reaching the company (only shippers' demands remain); true lets them in again. (scrittura · conferma · autotrasportatore · API: update_demand_settings) [chiave manager]
lg demand-targets search — Resolve a pickup/delivery location for a demand to a target token ("5-" = district/postal area, "10-" = seaport address). (lettura · — · committente · API: lookup_demand_target)
lg demands create — Open a freight demand (talep) so carriers can bid. (scrittura · conferma + irreversibile · committente · API: create_demand) [accetta un file: attachment_uuids]
lg demands download — File for ONE demand owned by this company. export_type=details_pdf: the demand's detail sheet (route, dates, cargo, pallets) as PDF. export_type=sales_xlsx: the sales report workbook — demand information, every bid… (lettura · — · committente · API: download_demand_export)
lg demands extract — Read a freight request text (an e-mail body, a note, a voice transcript) and return the demand fields it contains in the demand wizard's shape: transport mode, countries, ports, locations, dates, load type, vehicle… (lettura · — · committente · API: extract_demand_from_text)
lg demands get — Detail of ONE freight demand. (lettura · — · committente, autotrasportatore · API: get_demand)
lg demands list — List freight demands (talep) this carrier is allowed to bid on, newest first. (lettura · — · autotrasportatore · API: list_open_demands)
lg demands list-own — List the freight demands (talep) OWNED by this customer company, newest first, with route, dates, vehicles, status and bid count. (lettura · — · committente · API: list_demands)
lg demands options — Reference lists needed to build a freight demand (talep) with create_demand: vehicle types (id, name, transport mode), payment maturity options (id + days; company_default_maturity_option_id is what the company normally… (lettura · — · committente · API: get_demand_form_options)
lg demands set-status — Close (make passive) one of this company's ACTIVE demands so carriers stop bidding. (scrittura · conferma + irreversibile · committente · API: close_demand)
lg demands update — Edit one of this company's ACTIVE demands that has NO bids yet (a demand with bids or a closed one cannot be edited). (scrittura · conferma · committente · API: update_demand) [accetta un file: attachment_uuids]
lg direct-conversations add-message — Send a direct message AS THIS USER (never as an assistant) — either into an existing chat (conversation_code from list_direct_conversations) or to one person (to_user_id from list_direct_message_contacts; their private… (scrittura · conferma + irreversibile · tutti · API: send_direct_message)
lg direct-conversations create — Start a direct chat. (scrittura · conferma + irreversibile · tutti · API: create_direct_conversation)
lg direct-conversations download — Produce the whole direct-message or group chat as a PDF (the same file as the panel's export button: participants and every message with date and time) and return a short-lived download link. (lettura · — · tutti · API: export_direct_conversation_pdf)
lg direct-conversations list — List this user's direct-message (DM) chats and group chats — person-to-person messaging, separate from load/bid chats (those are list_conversations). (lettura · — · tutti · API: list_direct_conversations)
lg direct-conversations list-contacts — List the people this user can direct-message: their own teammates plus people they share a load/bid chat with. (lettura · — · tutti · API: list_direct_message_contacts)
lg direct-conversations list-messages — Read the latest messages of one direct-message or group chat (conversation_code from list_direct_conversations), oldest→newest, with who wrote them. `mine: true` marks this user's own messages; only those, and only… (lettura · — · tutti · API: list_direct_conversation_messages)
lg direct-conversations mark-read — Mark one direct-message or group chat as read for this user (clears its unread badge). (scrittura · — · tutti · API: mark_direct_conversation_read)
lg direct-conversations remove-message — Delete one of THIS user's own direct messages (message_id from list_direct_conversation_messages, mine and editable true), only within 5 minutes of sending. (scrittura · conferma + irreversibile · tutti · API: delete_direct_message)
lg direct-conversations update — Rename a GROUP direct chat (private one-to-one chats have no title). (scrittura · conferma · tutti · API: rename_direct_conversation)
lg direct-conversations update-message — Edit one of THIS user's own direct messages (message_id from list_direct_conversation_messages, where mine and editable are true). (scrittura · conferma · tutti · API: update_direct_message)
lg document-checks run — Cross-check documents the user attached to THIS conversation against each other and report the discrepancies: mismatched party names, quantities, weights, amounts, dates, container or reference numbers between an… (scrittura · — · tutti · API: check_document_compliance) [accetta un file: attachment_uuids]
lg document-types list — List the platform's document types (slug and name) — the values document_type_slug accepts in upload_company_document, add_driver_document and the vehicle document commands. (lettura · — · tutti · API: list_document_types)
lg documents download — Get a short-lived (15 minute) download/preview link for one document by its document_id (from list_load_documents or list_company_documents). (lettura · — · tutti · API: get_document_link)
lg drive-rest-estimates get — One driver's GPS-ESTIMATED driving/rest status and driving time left under EU 561/2006 / AETR: current activity and since when, driving_left_today_s = the legal driving time left today under the daily, weekly (56 h) AND… (lettura · — · autotrasportatore · API: get_driver_drive_rest_estimate)
lg drive-rest-estimates list — Fleet overview of the GPS-ESTIMATED driving/rest status and driving time left (EU 561/2006 / AETR): per driver the current activity, driving_left_today_s = the legal driving time left today under the daily, weekly (56… (lettura · — · autotrasportatore · API: list_driver_drive_rest_estimates)
lg driver-accounts get — Answer "how much do we owe this driver / how much does the driver owe us". (lettura · — · committente, autotrasportatore · API: get_driver_account_summary)
lg driver-accounts list-candidates — Before opening or filling a driver settlement statement: which of ONE driver's receipts and advances can go on it, and why the others cannot. (lettura · — · committente, autotrasportatore · API: list_driver_account_candidates)
lg driver-advances cancel — Cancel (void) a recorded driver money movement that did not really happen or was entered with the wrong amount. (scrittura · conferma + irreversibile · committente, autotrasportatore · API: cancel_driver_advance)
lg driver-advances create — Record a money movement between the company and a driver: an advance handed to the driver, money the driver gave back, a closing payout, or a carry-forward opening balance. (scrittura · conferma · committente, autotrasportatore · API: create_driver_advance) [accetta un file: attachment_uuid]
lg driver-advances delete — Delete a driver money movement that was entered by mistake (duplicate, wrong driver). (scrittura · conferma + irreversibile · committente, autotrasportatore · API: delete_driver_advance)
lg driver-advances list — List the money movements between the company and its drivers: cash advances handed out, money paid back by the driver, closing payouts and carry-forward opening balances. (lettura · — · committente, autotrasportatore · API: list_driver_advances)
lg driver-advances update — Correct the non-money details of a recorded driver money movement: its reference, note, or the load it belongs to. (scrittura · conferma · committente, autotrasportatore · API: update_driver_advance)
lg driver-availabilities create — Record that a driver is unavailable on some days — "Ali is on leave 14-20 November", "Mehmet rests at home next week", "Kemal is sick from today". (scrittura · conferma · autotrasportatore · API: create_driver_availability)
lg driver-availabilities delete — Delete ONE availability period (id from list_driver_availabilities) — the driver counts as available again on those days. (scrittura · conferma + irreversibile · autotrasportatore · API: delete_driver_availability)
lg driver-availabilities list — List drivers' leave, home-rest, sick and other unavailability periods (newest planning input), optionally for one driver and/or a date window. (lettura · — · autotrasportatore · API: list_driver_availabilities)
lg driver-availabilities update — Correct one availability period (id from list_driver_availabilities): kind, dates, Schengen presence or note. (scrittura · conferma · autotrasportatore · API: update_driver_availability)
lg driver-expense-settings get — Read this company's driver expense module settings: is the module switched on, which currency receipts and advances are converted into, whether receipts need approval (and above which amount), whether drivers may… (lettura · — · committente, autotrasportatore · API: get_driver_expense_settings)
lg driver-expense-settings update — Change this company's driver expense module settings — only the fields you pass change. (scrittura · conferma · committente, autotrasportatore · API: update_driver_expense_settings) [chiave manager]
lg driver-expenses create — File one or MANY expense receipts the user attached to this conversation (fuel, toll, ferry, parking, repair, meal…) into the driver expense ledger as pending expenses of ONE of this company's drivers. (scrittura · conferma + irreversibile · committente, autotrasportatore · API: process_receipt) [accetta un file: attachment_uuid, attachment_uuids]
lg driver-expenses declare — Record a driver expense WITHOUT a receipt (fişsiz şoför harcaması) — "Mehmet dün 40 EUR otopark ödedi, fişi yok", "log 120 PLN toll for driver X". (scrittura · conferma · committente, autotrasportatore · API: create_driver_expense)
lg driver-expenses delete — Delete a driver expense entered by mistake (duplicate receipt, wrong driver, test entry). (scrittura · conferma + irreversibile · committente, autotrasportatore · API: delete_driver_expense)
lg driver-expenses download — Get the download link of a receipt pack that generate_driver_receipt_pack prepared in the background. (lettura · — · committente, autotrasportatore · API: download_driver_receipt_pack)
lg driver-expenses generate — Produce ONE PDF that contains the driver receipts of a selection — for a trip, a load, a driver statement or a date window — e.g. to hand to accounting or the customer. (lettura · — · committente, autotrasportatore · API: generate_driver_receipt_pack)
lg driver-expenses get — Read one driver expense (receipt) by its id: merchant, amount, currency, converted amount, category, payment channel, whether it is charged to the driver, and the approval status. (lettura · — · committente, autotrasportatore · API: get_driver_expense)
lg driver-expenses list — List driver expense receipts (fuel, toll, ferry, parking, food, repair…) with a converted total. (lettura · — · committente, autotrasportatore · API: list_driver_expenses)
lg driver-expenses list-loads — For ONE driver: which loads they carried and, per load, how many receipts there are, how many still await approval, how much is reimbursable to the driver, how much is company-billed (fuel card / DKV / UTA — never the… (lettura · — · committente, autotrasportatore · API: list_driver_expense_loads)
lg driver-expenses list-trips — For ONE driver: which trips (load groups) they drove and, per trip, the number of loads and the driver's OWN receipt figures (count, awaiting approval, reimbursable, company-billed fuel-card / DKV / UTA, still… (lettura · — · committente, autotrasportatore · API: list_driver_expense_trips)
lg driver-expenses review — Approve or reject ONE driver expense (receipt) from the chat, or send an already-decided one back to pending. status=approved means the company accepts the expense (an approved reimbursable receipt can then be counted… (scrittura · conferma · committente, autotrasportatore · API: review_driver_expense)
lg driver-expenses set-in-account — Count driver receipts INTO the driver's account (include=true, default) or take them OUT of it (include=false). (scrittura · conferma · committente, autotrasportatore · API: set_driver_expenses_in_account)
lg driver-expenses update — Correct a recorded driver expense (receipt or no-receipt): amount, currency, date, category, how it was paid, merchant, description or the load it belongs to — "the parking was 45 EUR not 40", "that fuel was paid with… (scrittura · conferma · committente, autotrasportatore · API: update_driver_expense)
lg driver-expenses update-conversion — Retry the currency conversion of ONE driver receipt whose exchange rate could not be resolved (it then sits outside every total and cannot go into a driver statement). (scrittura · — · committente, autotrasportatore · API: retry_driver_expense_conversion)
lg driver-schedules accept — Apply ONE schedule suggestion (suggestion_id from get_driver_schedule): the proposed driver is assigned to the load (or every consignment of the trip — consignments still held by another driver are taken over, and the… (scrittura · conferma · autotrasportatore · API: apply_driver_schedule_suggestion)
lg driver-schedules generate — Compute schedule suggestions for a 7-90 day window starting within 30 days: which driver should take each unassigned load, trip and route plan so that nobody runs out of Schengen days, leave is respected and vehicles do… (scrittura · conferma · autotrasportatore · API: generate_driver_schedule)
lg driver-schedules get — Read one schedule run (schedule_id from generate_driver_schedule / list_driver_schedules): summary (jobs covered, unassignable jobs and why, vehicle idle days before → after, lowest Schengen margin), the suggestions in… (lettura · — · autotrasportatore · API: get_driver_schedule)
lg driver-schedules list — List the company's schedule-suggestion runs, newest first: id (schedule_id), status (queued | running | completed | failed), the planned window, objective and whether the run is out of date (is_stale — planning inputs… (lettura · — · autotrasportatore · API: list_driver_schedules)
lg driver-schedules reject — Dismiss ONE open schedule suggestion (suggestion_id from get_driver_schedule) so it is no longer offered; nothing is assigned or changed elsewhere. (scrittura · — · autotrasportatore · API: dismiss_driver_schedule_suggestion)
lg driver-statements cancel — Cancel a statement that should not exist (opened by mistake, duplicated). (scrittura · conferma + irreversibile · committente, autotrasportatore · API: cancel_driver_account)
lg driver-statements create — Open a NEW draft settlement statement for a driver. (scrittura · conferma · committente, autotrasportatore · API: create_driver_account)
lg driver-statements download — Give a short-lived download link to the PDF statement of a FINALISED driver settlement statement — the document the driver sees and signs, with every line, the fuel-card block that is outside the driver maths, and the… (lettura · — · committente, autotrasportatore · API: download_driver_account_pdf)
lg driver-statements finalize — FINALISE a draft settlement statement — it freezes the document, makes it visible to the driver and (for settle_cash) writes the counter-entry into the advance ledger. (scrittura · conferma + irreversibile · committente, autotrasportatore · API: finalize_driver_account) [chiave manager]
lg driver-statements get — Read one driver settlement statement in full: its status and revision, the driver, the currency, every total (expenses, advances, repayments, receiptless declarations), the NET balance with the sentence that says which… (lettura · — · committente, autotrasportatore · API: get_driver_account)
lg driver-statements list — List the driver settlement statements (mutabakat belgesi) of this company: code, which driver, status (draft / finalized / cancelled), currency, the net balance and what it means, how many expense and advance lines it… (lettura · — · committente, autotrasportatore · API: list_driver_accounts)
lg driver-statements reopen — Reopen a FINALISED statement so it can be corrected (a late receipt arrived, a line was wrong). (scrittura · conferma · committente, autotrasportatore · API: reopen_driver_account) [chiave manager]
lg driver-statements update — Change the note printed on a DRAFT driver settlement statement (e.g. "September trips, fuel excluded"). (scrittura · conferma · committente, autotrasportatore · API: update_driver_account)
lg driver-statements update-lines — Attach receipts/advances to a DRAFT statement, or detach ones that should not be on it. (scrittura · conferma · committente, autotrasportatore · API: update_driver_account_lines)
lg driver-statuses list — Fleet command centre — every driver's live operational status in one list: last position and its AGE, signal health (streaming / delayed / stale / no_signal / permission_denied / app_missing), duty (on_trip / assigned /… (lettura · — · committente, autotrasportatore · API: list_fleet_driver_statuses)
lg drivers add-document — Record a driver paper — visa, passport, residence permit, driving licence, SRC certificate, psychotechnic certificate, travel health insurance — for ONE of this carrier's drivers, so its expiry is tracked. (scrittura · conferma · autotrasportatore · API: add_driver_document) [accetta un file: attachment_uuid]
lg drivers archive — Archive (deactivate) a driver: their account is disabled, open mobile sessions are revoked and the login link stops working. (scrittura · conferma + irreversibile · autotrasportatore · API: archive_driver)
lg drivers calculate — Check whether ONE driver can take a job: Schengen 90/180 days left at the end of the trip (expected and worst case, counting the drive back out and the driver's later planned work), leave / home-rest / sick periods,… (lettura · — · autotrasportatore · API: check_driver_for_trip)
lg drivers create — Create a new driver account for this carrier company. (scrittura · conferma · autotrasportatore · API: create_driver)
lg drivers delete-document — Remove a driver paper from the driver's file. (scrittura · conferma + irreversibile · autotrasportatore · API: delete_driver_document)
lg drivers get — Full detail of ONE driver of this carrier: identity, archive state, mobile app state, last GPS position, assigned load codes, ALL driver documents (passport, visa, licence, SRC… with expiry and days_to_expiry) and the… (lettura · — · autotrasportatore · API: get_driver)
lg drivers list — List this carrier company's drivers with their status, current country, expiring/expired document counts, assigned load codes and vehicle plates. (lettura · — · autotrasportatore · API: list_drivers)
lg drivers list-candidates — Rank the company's drivers for a job — which drivers are available and can do it (Schengen days at trip end incl. the drive back, leave/home-rest, other jobs, estimated driving/rest readiness, distance to the start)… (lettura · — · autotrasportatore · API: list_trip_driver_candidates)
lg drivers list-documents — List ONE driver's documents (passport, visa, residence permit, licence, SRC, ADR, health insurance…) with document number, issuing country, valid_until, days_to_expiry, is_expired and AI extraction status. (lettura · — · autotrasportatore · API: list_driver_documents)
lg drivers list-locations — A driver's GPS trail — the raw position pings from the driver app in a time window, oldest to newest, with the first and last timestamps and the point count. (lettura · — · autotrasportatore · API: list_driver_locations)
lg drivers login-link — Produce the driver's 48-hour mobile app login link (sensitive credential). (scrittura · conferma · autotrasportatore · API: get_driver_login_link)
lg drivers request-location — Ask a driver's phone for a fresh position ("where is Ahmet right now — ping him"). (scrittura · — · autotrasportatore · API: request_driver_location)
lg drivers search — Resolve one of this company's drivers by name to its driver_id. (lettura · — · autotrasportatore · API: lookup_driver)
lg drivers update — Correct a driver's first/last name. (scrittura · conferma · autotrasportatore · API: update_driver)
lg drivers update-document — Correct a driver paper already on file — most often its expiry date (valid_until) after a renewal, but also the document number, the issuing country, the type or the note. (scrittura · conferma · autotrasportatore · API: update_driver_document)
lg drivers update-login-link — Generate a NEW 48-hour mobile login link for a driver and kill the old one (lost phone, expired or leaked link). (scrittura · conferma + irreversibile · autotrasportatore · API: refresh_driver_login_link)
lg equipment-damages create — Open a damage record on one of the company's own vehicles or trailers (dorse hasar kaydı aç) — "33ABC12 dorsesinin sol arka kapısında ezik var", "record a scratch on the rear bumper of the truck". (scrittura · conferma · tutti · API: create_equipment_damage)
lg equipment-damages delete — Delete a damage record that was opened by mistake (a duplicate, the wrong vehicle). (scrittura · conferma + irreversibile · tutti · API: delete_equipment_damage)
lg equipment-damages generate — Produce the equipment damage ledger as an Excel file (the same file as the panel's export button) and return a short-lived download link — e.g. "give me this year's open trailer damages as Excel". (lettura · — · tutti · API: export_equipment_damages)
lg equipment-damages list — List the equipment/trailer damages recorded for this company: which vehicle, where on it (area and angle), damage type and severity, whether it is still open or repaired, the estimated and actual repair cost, who is… (lettura · — · tutti · API: list_equipment_damages)
lg equipment-damages update — Update an existing damage record: mark it repaired (with repair date, cost and note), dismissed or disputed, change severity/type/area/description, set the estimated cost, or set/clear the responsible driver. (scrittura · conferma · tutti · API: update_equipment_damage)
lg equipment-inspection-links create — Create a one-time link so a driver or agent who is NOT on the platform (port agent, another company's driver) can upload the hand-over photos of one of the company's trailers/vehicles from a phone, without an account. (scrittura · conferma · tutti · API: create_equipment_inspection_link)
lg equipment-inspections create — Record an equipment hand-over inspection of one of the company's own trailers or vehicles on behalf of a driver or the office — "record the pickup inspection of trailer 34ABC12 with these 4 photos, driver Ali".… (scrittura · conferma · tutti · API: create_equipment_inspection) [accetta un file: photos[].attachment_uuid]
lg equipment-inspections delete — Delete an equipment inspection that was recorded by mistake (wrong vehicle, duplicate), together with its photos. (scrittura · conferma + irreversibile · tutti · API: delete_equipment_inspection)
lg equipment-inspections get — Full detail of ONE equipment hand-over inspection: vehicle, event (pickup / dropoff / interim), who did it and where and when, the AI analysis status with its overall condition and summary, the damages that inspection… (lettura · — · tutti · API: get_equipment_inspection)
lg equipment-inspections list — List the equipment hand-over inspections (teslim-tesellüm controls) of this company: which vehicle, the event type (hand-over, take-over, interim), when and where it happened, who performed it (driver or office user, or… (lettura · — · tutti · API: list_equipment_inspections)
lg equipment-inspections run — Run the AI damage analysis again on the photos of one equipment inspection (for example after the analysis failed, or photos were added later). (scrittura · conferma · tutti · API: reanalyze_equipment_inspection)
lg equipment-settings get — Read the company's equipment inspection settings: whether the module is on, at which hand-overs an inspection is required (pickup / dropoff), whether photos are required, the minimum photo count, which angles are… (lettura · — · tutti · API: get_equipment_settings)
lg equipment-settings update — Change the company's equipment inspection settings — e.g. "turn on equipment inspection and require at least 4 photos with front, rear, left and right at pickup". (scrittura · conferma · tutti · API: update_equipment_settings) [chiave manager]
lg equipment-timelines get — Who has one trailer/vehicle right now (custody: in custody of a driver since the last pickup, or released at the last dropoff), the inspections it went through (newest first) and its OPEN damages — in one read. (lettura · — · tutti · API: get_equipment_timeline)
lg export-documents add-item — Append a line item to an export document. (scrittura · — · tutti · API: add_export_document_item)
lg export-documents create — Create a new export document draft. (scrittura · — · tutti · API: create_export_document_draft)
lg export-documents create-set — Create SEVERAL export document drafts (a set, e.g. commercial invoice + packing list) from ONE source in one go: the source is read once by AI and every chosen document is filled from it. (scrittura · — · tutti · API: create_export_document_set) [accetta un file: attachment_uuid]
lg export-documents delete — Delete one export document of this company (draft or generated). (scrittura · conferma + irreversibile · tutti · API: delete_export_document)
lg export-documents duplicate — Copy an existing export document into a NEW draft of the same type (same parties, items and terms; no document number, not generated). (scrittura · — · tutti · API: duplicate_export_document)
lg export-documents extract — Read a pasted order e-mail, offer or confirmation — or an Excel/CSV/TXT item list given as attachment_uuid — and fill an export document from it. (scrittura · — · tutti · API: extract_export_document_from_text) [accetta un file: attachment_uuid]
lg export-documents generate — Produce the final PDF of an export document AND return a short-lived signed download link for it, so the user gets the file straight from the chat. (scrittura · conferma + irreversibile · tutti · API: generate_export_document)
lg export-documents generate-set — Generate several export documents as PDFs in one go and return a short-lived download link for each generated one. (scrittura · conferma + irreversibile · tutti · API: generate_export_document_set)
lg export-documents get — Read one export document in full: every filled field as dot-paths, the line items with their 1-based positions, the server-computed totals and which required fields are still empty. (lettura · — · tutti · API: get_export_document)
lg export-documents list — List the export documents of the current company (proforma invoice, commercial invoice, packing list, shipping instruction, delivery note, certificate/movement applications, exporter declaration, insurance request). (lettura · — · tutti · API: list_export_documents)
lg export-documents options — List the export document types and the ready-made document sets with their credit cost. (lettura · — · tutti · API: get_export_document_options)
lg export-documents preview — Before generating several export documents as PDFs, show what it would cost: which documents would spend a credit, which are free (already generated), the total, the remaining balance and the required fields still empty… (lettura · — · tutti · API: plan_export_document_generation)
lg export-documents remove-item — Delete one line item by its 1-based position. (scrittura · — · tutti · API: remove_export_document_item)
lg export-documents set — Set one or more fields on an export document draft. (scrittura · — · tutti · API: set_export_document_fields)
lg export-documents update-item — Change columns of one existing line item, addressed by its 1-based position from get_export_document. (scrittura · — · tutti · API: update_export_document_item)
lg finance calculate — Build a budget / financial forecast (bütçe tahmini, gelecek yıl bütçesi, nakit/ciro projeksiyonu) from the company's MEASURED history, month by month. (lettura · — · tutti · API: generate_budget_forecast)
lg finance get — One call that returns the measured financial BASE for a period — the numbers a budget, a forecast, a business plan, a cash-flow projection or a board summary is built on, instead of chaining six separate reads. (lettura · — · tutti · API: get_financial_snapshot)
lg fleet-documents list — List fleet documents that expire soon (or already expired): vehicle papers (insurance, inspection, permits) and — for carriers — driver papers (passport, visa, licence, SRC). (lettura · — · committente, autotrasportatore · API: list_expiring_documents)
lg freight-invoices archive — Archive (remove from the active list) a freight invoice YOUR company uploaded — e.g. a duplicate or the wrong file. (scrittura · conferma + irreversibile · tutti · API: archive_freight_invoice)
lg freight-invoices create — Attach 1-20 freight invoices (navlun faturası) to a load. (scrittura · conferma · tutti · API: upload_freight_invoices) [accetta un file: attachment_uuids]
lg freight-invoices list — List the freight invoices (navlun faturaları) of a load that your company is a party to: who uploaded it, amount and currency, invoice date, the AI reading status, and which load parties it is shared with. (lettura · — · tutti · API: list_freight_invoices)
lg freight-invoices set-visibility — Choose which load parties can see a freight invoice YOUR company uploaded — e.g. "share the invoice with the receiver too", "only we should see it". (scrittura · conferma · tutti · API: set_freight_invoice_visibility)
lg freight-reports get — Freight (navlun) cost report over the loads this company can see: agreed freight totals per currency plus the EUR equivalent, freight-invoice totals, how many loads have NO freight recorded (listed by code), a breakdown… (lettura · — · committente, autotrasportatore · API: get_freight_cost_report)
lg fuel-cards create — Register a fuel card (DKV, UTA and the like) in the fleet card book, optionally tied to a driver or a vehicle. (scrittura · conferma · committente, autotrasportatore · API: create_fuel_card)
lg fuel-cards delete — Delete a fuel / toll card (DKV, UTA, Shell…) that was entered BY MISTAKE. (scrittura · conferma + irreversibile · committente, autotrasportatore · API: delete_fuel_card)
lg fuel-cards list — List the company's fuel and toll cards (DKV, UTA, Eurowag, E100, Shell, OMV, Aral, Petrol Ofisi, Opet…) with the last four digits, the driver or vehicle they are tied to, and whether they are active. (lettura · — · committente, autotrasportatore · API: list_fuel_cards)
lg fuel-cards update — Update a fuel card: move it to another driver or vehicle, change its label or note, or DEACTIVATE it (is_active false) when the card is cancelled. (scrittura · conferma · committente, autotrasportatore · API: update_fuel_card)
lg handoff-links generate — Get the logistivo.com link for work that deliberately stays in the browser: package_purchase (buy or upgrade a package; optional package_slug from list_packages and billing_period monthly|yearly pre-select it — the… (lettura · — · tutti · API: get_browser_handoff_link)
lg import-duties get — Read the Turkish import duty table for one GTİP code: customs duty (İthalat Rejimi Kararı) and additional customs duty / İGV, with every country-group column, plus the statutory duty from the nomenclature. (lettura · — · tutti · API: get_import_duty_rates)
lg integration-keys list — List the company's integration (API) keys: name, uuid, which teammate it acts as, scope (read/write) and allowed domains, access level (manager/employee), environment (live/sandbox), status (active/revoked/expired),… (lettura · — · tutti · API: list_integration_keys) [chiave manager]
lg integration-keys revoke — Revoke one of the company's integration (API) keys by its uuid from list_integration_keys: the key stops working immediately and cannot be re-enabled (issue a new key instead). (scrittura · conferma + irreversibile · tutti · API: revoke_integration_key) [chiave manager]
lg invitations create — Invite colleagues to this company by e-mail — one address in email, or up to 20 at once in emails (all-or-nothing: the seat limit and every address's domain are checked before anything is sent). (scrittura · conferma + irreversibile · tutti · API: invite_teammate) [chiave manager]
lg invitations list — List teammate invitations of this company that are not completed yet (pending / e-mail verified / account created), with invitation_code, e-mail, role and expiry. (lettura · — · tutti · API: list_pending_invitations)
lg invitations resend — Re-send a pending teammate invitation e-mail and extend its expiry by 14 days. (scrittura · conferma + irreversibile · tutti · API: resend_invitation) [chiave manager]
lg invitations revoke — Cancel a pending teammate invitation so its link stops working (it can later be re-sent). (scrittura · conferma · tutti · API: revoke_invitation) [chiave manager]
lg invoice-settings get — Read the invoice document settings (fatura ayarları, fatura şablonu ayarları): which invoice templates exist, which template configuration is the company default, which fields of it are filled (logo, seller address,… (lettura · — · tutti · API: get_invoice_settings)
lg invoice-templates create — Create a new invoice template configuration for your company: a base template plus field values (colours, font, header / footer text, IBANs shown, QR code, language; logo and signature from uploaded images). (scrittura · conferma + irreversibile · tutti · API: create_invoice_template) [chiave manager] [accetta un file: logo_attachment_uuid, signature_image_attachment_uuid]
lg invoice-templates delete — Delete one of your invoice template configurations. (scrittura · conferma + irreversibile · tutti · API: delete_invoice_template) [chiave manager]
lg invoice-templates get — Show the fillable fields of an invoice template (logo, colours, font, header / footer text, IBANs shown, QR code, signature, language) with their types, options and defaults — and, for one of your configurations, its… (lettura · — · tutti · API: get_invoice_template)
lg invoice-templates set-default — Make one of your invoice template configurations the company default; the previous default stops being default. (scrittura · conferma · tutti · API: set_default_invoice_template) [chiave manager]
lg invoice-templates update — Edit one of your invoice template configurations: switch its base template, rename it, change field values (merged over the stored ones — only the keys you pass change), replace the logo / signature image, or make it… (scrittura · conferma + irreversibile · tutti · API: update_invoice_template) [chiave manager] [accetta un file: logo_attachment_uuid, signature_image_attachment_uuid]
lg invoices add-line — Add a line item to a DRAFT invoice and recompute totals (tax auto-resolved if tax_rate_id omitted). (scrittura · — · tutti · API: add_invoice_line)
lg invoices add-payment — Record money received (sales invoice) or paid (purchase invoice) against ONE issued invoice: writes the payment, posts the balanced journal entry and reduces the remaining balance. (scrittura · conferma + irreversibile · tutti · API: record_invoice_payment)
lg invoices cancel — Cancel an ISSUED invoice this company issued: posts the reversing journal entry and marks the invoice cancelled. (scrittura · conferma + irreversibile · tutti · API: cancel_invoice)
lg invoices create — Create a DRAFT invoice (reversible) issued by the current company to a recipient business contact. (scrittura · — · tutti · API: create_invoice_draft)
lg invoices delete-draft — Delete a DRAFT invoice of this company together with its lines and taxes. (scrittura · conferma + irreversibile · tutti · API: delete_invoice_draft)
lg invoices download — Get a short-lived download link for the PDF of an invoice visible to this company (and the e-invoice XML when one exists). (lettura · — · tutti · API: download_invoice_pdf)
lg invoices get — Read one invoice in full: parties, load link, dates, every line with tax, tax breakdown, totals, remaining balance and the payments recorded against it. (lettura · — · tutti · API: get_invoice)
lg invoices issue — Issue (finalize) a DRAFT invoice: assigns a number and posts accounting entries. (scrittura · conferma + irreversibile · tutti · API: issue_invoice)
lg invoices list — List invoices visible to this company — the ones it issued and the ones issued to it (as a linked party). (lettura · — · tutti · API: list_invoices)
lg invoices preview — Show the user a full preview of a DRAFT invoice (recipient, line items, tax breakdown, totals) WITHOUT issuing it. (lettura · — · tutti · API: preview_invoice · deprecato: 2026-09-03 · usa get_invoice)
lg invoices remove-line — Remove one line from a DRAFT invoice your company issued; the totals are recalculated. (scrittura · conferma · tutti · API: remove_invoice_line)
lg invoices reverse-payment — Undo ONE payment/collection recorded on an invoice: posts the reversing journal entry, gives the amount back to the invoice's remaining balance and removes the payment row. (scrittura · conferma + irreversibile · tutti · API: reverse_invoice_payment)
lg invoices update — Edit the header of a DRAFT invoice your company issued: recipient contact, currency, issue / due date, the printed note and the invoice template. (scrittura · — · tutti · API: update_invoice_draft)
lg invoices update-line — Edit one line of a DRAFT invoice your company issued (text, quantity, unit, net unit price, discount, tax rate, order). (scrittura · — · tutti · API: update_invoice_line)
lg join-requests approve — Approve a pending join request: the applicant becomes a user of our company with the EMPLOYEE role, takes one team seat and is e-mailed the decision. (scrittura · conferma + irreversibile · tutti · API: approve_join_request) [chiave manager]
lg join-requests list — List PENDING requests from people asking to join our company (they signed up with an e-mail on one of our verified domains and picked our company). (lettura · — · tutti · API: list_join_requests) [chiave manager]
lg join-requests reject — Reject a pending join request: the applicant does not join our company and is e-mailed the decision. (scrittura · conferma + irreversibile · tutti · API: reject_join_request) [chiave manager]
lg journal-entries create — Post a manual double-entry journal entry (yevmiye fişi). (scrittura · conferma + irreversibile · tutti · API: create_journal_entry)
lg journal-entries get — Read one journal entry with its lines (account code/name, debit, credit, counterparty) and totals. (lettura · — · tutti · API: get_journal_entry)
lg journal-entries list — List journal entries (yevmiye fişleri) of the company, newest first, with optional date window. (lettura · — · tutti · API: list_journal_entries)
lg language-settings get — Read the signed-in user's own language settings (dil ayarları). (lettura · — · tutti · API: get_language_settings)
lg language-settings update — Change the signed-in user's OWN language settings — "dilimi İngilizce yap", "e-postalarım Türkçe gelsin", "sohbet mesajlarını Almancaya çevir". (scrittura · — · tutti · API: set_language)
lg load-ai-settings get — Read our company's load AI reminder setting (Settings → Loads): whether the assistant posts reminders into load chats about loads whose status was not updated (ai_warning_enabled) and on which days (warning_frequency:… (lettura · — · tutti · API: get_load_ai_settings)
lg load-ai-settings update — Change our company's load AI reminders (Settings → Loads): ai_warning_enabled turns the reminders the assistant posts into load chats on or off; warning_frequency picks the days (daily, mon_wed_fri, weekly_wed,… (scrittura · conferma · tutti · API: update_load_ai_settings) [chiave manager]
lg load-containers create — Add a sea container number to a load (yüke konteyner ekle) — "add MSC container MSCU1234565 to FKZ8515". (scrittura · conferma · committente, autotrasportatore · API: add_load_container)
lg load-containers delete — Delete a container record from a load (konteyneri sil) — only while its vessel tracking has NOT started (otherwise refused with INVALID_STATUS). (scrittura · conferma + irreversibile · tutti · API: delete_load_container)
lg load-containers get — Show one container of a load and the last known position of the ship carrying it (konteyner konumu): ship name/IMO, latitude/longitude, speed, course, destination, ETA and the position time. (lettura · — · tutti · API: get_load_container)
lg load-containers list — List the sea containers recorded on a load (konteynerler) with their shipping line, whether vessel tracking has started and which ship carries them. (lettura · — · tutti · API: list_load_containers)
lg load-containers set-tracking — Start vessel tracking for a load from its containers (konteyner takibini başlat): the shipping line is queried for each container until the vessel carrying it is found; that ship is then tracked on the load's map and… (scrittura · conferma · tutti · API: start_load_container_tracking)
lg load-documents create — File one or MANY documents the user attached to this conversation onto a load: each file is stored as a company document and posted into the load's chat, where every participant (customer, carrier, customs broker) sees… (scrittura · conferma + irreversibile · tutti · API: attach_chat_file_to_load) [accetta un file: attachment_uuid, attachment_uuids]
lg load-documents list — List the documents (CMR, invoice, packing list, customs papers, photos…) filed on a load — i.e. the files shared in that load's chat. (lettura · — · tutti · API: list_load_documents)
lg load-groups add-loads — Merge EXISTING loads into a groupage trip you own as consignments (they keep their own code, chat, documents and participants; only the trip membership changes — nothing is duplicated and NO credit is used). (scrittura · conferma · committente, autotrasportatore · API: add_loads_to_group)
lg load-groups create — Create a groupage trip (parsiyel/sefer): ONE truck carrying several ISOLATED consignments; each consignment is its own load with its own chat/documents/status and receivers never see each other. (scrittura · conferma + irreversibile · committente, autotrasportatore · API: create_load_group)
lg load-groups download — Download the route report of a groupage trip (sefer / parsiyel, code like LGV00253): route_pdf = detailed route report with map and itinerary, route_xlsx = the same as Excel, driver_sheet_pdf = the simplified driver… (scrittura · — · committente, autotrasportatore · API: download_load_group_report)
lg load-groups get — Detail of one groupage trip: consignments visible to you (load code, status, receiver, route, driver), planned date, optimised master route summary and stop count. (lettura · — · committente, autotrasportatore · API: get_load_group)
lg load-groups list — List groupage trips (parsiyel / sefer: one truck, several isolated consignment loads) this company owns or — for carriers — carries, newest first, with visible consignment count and route optimisation state. (lettura · — · committente, autotrasportatore · API: list_load_groups)
lg load-groups optimize — Re-optimise the master route of a groupage trip you own and RETURN the new itinerary: the ordered stops (pickup → export customs → import customs → dropoff), each stop's address and consignment codes, the total distance… (scrittura · — · committente, autotrasportatore · API: optimize_trip_route)
lg load-groups remove-load — Take one consignment out of a groupage trip you own. (scrittura · conferma · committente, autotrasportatore · API: remove_load_from_group)
lg load-heatmaps generate — Produce the load heatmap report (PDF, with QR code and the list of your active loads: code, departure, arrival, date, weight), save it to the company's reports and return a download link. (scrittura · conferma + irreversibile · tutti · API: generate_load_heatmap_report)
lg load-heatmaps get — Load heatmap data in words: the densest departure and arrival areas of your active loads, ranked by number of loads and by total kilograms. (lettura · — · tutti · API: get_load_heatmap)
lg load-locations create — Report a position for a load on behalf of the carrier (konum bildir) — "FKZ8515 is at Kapıkule now", "the truck is at 41.0, 28.9". (scrittura · conferma + irreversibile · autotrasportatore · API: report_load_location)
lg load-locations list — Show a load's position history (konum geçmişi) and its last known position — "where is FKZ8515 now", "where was it yesterday", "show the truck's track". (lettura · — · tutti · API: list_load_locations)
lg load-locations list-routes — Show the road route segments drawn on a load's tracking map (rota parçaları), each with distance (metres) and duration (seconds): from the pickup address to the first reported position, between reported positions, and… (lettura · — · tutti · API: list_load_route_segments)
lg load-notifications list-recipients — Show which load parties can receive a load notification (departure, arrival, daily location) and how many of their people are subscribed per channel (e-mail, push, SMS). (lettura · — · tutti · API: list_load_notification_recipients)
lg load-notifications send — Send a departure / arrival / daily-location notification about a load to chosen load parties — e.g. "notify the receiver that FRT6470 arrived". (scrittura · conferma + irreversibile · tutti · API: send_load_notification)
lg load-notifications send-email — E-mail a departure / arrival / location update about a load to people you choose from YOUR OWN company directory (business contact persons) — e.g. "e-mail Mehmet at Arkas the location of FKZ8515". (scrittura · conferma + irreversibile · tutti · API: send_load_email_notification)
lg load-participants create — Add a party to a load (yüke taraf ekle) — "FKZ8515'e Arkas'ı alıcı olarak ekle" — or assign a sub-carrier. business_contact_id comes from lookup_business_contact (your own directory). (scrittura · conferma · tutti · API: add_load_participant)
lg load-participants delete — Remove a party or a sub-carrier from a load (yükten taraf çıkar) — "FKZ8515'ten alt taşıyıcı Yılmaz Nakliyat'ı kaldır". participant_id comes from list_load_participants. (scrittura · conferma · tutti · API: remove_load_participant)
lg load-participants list — List a load's parties (yük tarafları): sender, receiver, carrier and sub-carriers, organizer, sender/receiver customs brokers — with participant_id (needed by every other load-participant command), position (0 = primary… (lettura · — · tutti · API: list_load_participants)
lg load-participants set-order — Put the parties of one role in a new order (load owner only); the first id becomes the primary. participant_ids must list ALL current rows of that role (from list_load_participants). (scrittura · conferma · tutti · API: reorder_load_participants)
lg load-participants set-primary — Make a party the primary one in its role (load owner only) — e.g. the main receiver or main customs broker. participant_id from list_load_participants. (scrittura · conferma · tutti · API: set_primary_load_participant)
lg load-participants update — Change one load party's settings (load owner only) — "Arkas FKZ8515'i görmesin": share_with_assigned_company (can the linked company see the load; cannot be turned off for a sub-carrier), conversation_user_ids (only… (scrittura · conferma · tutti · API: update_load_participant)
lg load-party-suggestions approve — Accept a party suggestion: link the suggested business contact to your OWN load as sender or receiver (business_contact_id and party_role from list_load_party_suggestions). (scrittura · conferma · tutti · API: confirm_load_party_suggestion)
lg load-party-suggestions list — Show sender/receiver suggestions for one of your OWN loads: parties named in the load's documents that match a contact in your directory but are not linked to the load yet. (lettura · — · tutti · API: list_load_party_suggestions)
lg load-party-suggestions reject — Close wrong party suggestions on your OWN load so they are not suggested again — "bu önerileri bir daha gösterme". (scrittura · — · tutti · API: dismiss_load_party_suggestions)
lg load-reports get — Build a report of your ACTIVE loads, optionally filtered by sender, receiver, transport mode, departure country or arrival country. format=summary (default) answers in chat: the number of loads and how many are in each… (lettura · — · tutti · API: get_load_report)
lg load-reports options — List the companies you can filter the load report by — the senders, receivers, carriers and other parties that appear on your active loads — with their company id and role. (lettura · — · tutti · API: get_load_report_options)
lg load-types search — Resolve a load/transport type (e.g. (lettura · — · tutti · API: lookup_load_type)
lg load-vehicles delete — Detach the fleet equipment from a load: both slots by default, or only the tractor unit / only the trailer. (scrittura · conferma · tutti · API: clear_load_equipment)
lg load-vehicles get — Show which tractor unit (or truck/van) and which trailer are attached to a load, whether they belong to your own fleet, and whether the load can still be changed. (lettura · — · tutti · API: get_load_equipment)
lg load-vehicles set — Attach one of your own fleet vehicles to a load: the tractor unit / truck slot (plate) and/or the trailer slot (trailer_plate). (scrittura · conferma · tutti · API: assign_vehicle_to_load)
lg loads add-order-reference — Attach an order reference to a load (sipariş referansı ekle) — "FKZ8515'e satın alma siparişi PO-4471 ekle". order_type is the kind of order (e.g. purchase, sales), order_no the number. (scrittura · conferma + irreversibile · tutti · API: add_load_order_reference)
lg loads analyze-documents — Re-run the background AI consistency analysis of a load's documents (does the invoice contradict the CMR, the packing list, the declared weight…) and refresh the load's problem flag with the outcome. (scrittura · — · tutti · API: reanalyze_load_documents)
lg loads archive — Archive one of the company's OWN loads (yükü arşivle) — "FKZ8515'i arşive al". (scrittura · conferma + irreversibile · tutti · API: archive_load)
lg loads assign-driver — Assign one of this company's drivers to a load so the driver sees it in the mobile app and starts reporting position. (scrittura · conferma · autotrasportatore · API: assign_driver_to_load)
lg loads audit-documents — Cross-check the documents already attached to loads and report, PER LOAD, whether their package counts and gross weights agree. (lettura · — · tutti · API: audit_load_documents)
lg loads close-problem — Close the open document-consistency flag of ONE load, from the chat. action=resolved means the contradiction was actually fixed (a corrected document was uploaded); action=dismissed means it was a false alarm and should… (scrittura · conferma · tutti · API: resolve_load_problem_flag)
lg loads create — Open a freight load (yük). (scrittura · conferma + irreversibile · tutti · API: create_load)
lg loads download — Generate a load's CMR consignment note as a PDF and return a short-lived download link — "FKZ8515'in CMR'ını ver". (lettura · — · tutti · API: download_load_cmr)
lg loads extract — Read a booking/order text (an e-mail body, a note, an ERP export line) and return the load fields it contains, in the quick-load form's shape: transport mode, countries, dates, load type, vehicle type, weight, goods… (lettura · — · committente · API: extract_load_from_text)
lg loads get — Read one load in full by its code: route, dates, weight, current status, parties (sender/receiver/carrier), agreed freight (freight_amount + freight_currency) with its freight invoices (number, date, total), latest… (lettura · — · tutti · API: get_load)
lg loads list — List the freight loads (yük) this company can see, newest first. (lettura · — · tutti · API: list_loads)
lg loads list-associated — List the loads of the same multi-vehicle order as a given load (aynı siparişin diğer araçları) — every active load that shares its vehicle group code (LG…) and that your company can see, with status, date and carrier. (lettura · — · tutti · API: list_associated_loads)
lg loads list-billing-targets — Show who you can invoice for a load: its commercial parties (sender, receiver, carrier) you are allowed to bill, each with recipient_contact_id to pass to create_invoice_draft and in_my_directory (true = already in your… (lettura · — · tutti · API: list_load_billing_targets)
lg loads list-problems — List loads whose uploaded documents the AI consistency check found to CONTRADICT each other (e.g. invoice weight vs CMR weight). (lettura · — · tutti · API: list_load_problem_flags)
lg loads list-status-history — Show a load's status history (durum geçmişi) in order — when it went pending, in transport, transit, delivered (done). (lettura · — · tutti · API: list_load_status_history)
lg loads list-stops — List the stops of a multi-stop load (çok duraklı yük — several pickups/drop-offs on one load) in route order, with type (pickup, dropoff, customs_exit, customs_entry), company, address, leg distance/duration and whether… (lettura · — · tutti · API: list_load_stops)
lg loads optimize — Re-order the stops of a multi-stop load for the shortest driving route (pickups first, then drop-offs) and store the new order with leg distances — "optimise FKZ8515's stops". (scrittura · — · tutti · API: optimize_load_stops)
lg loads options — Read a load's editable fields, their current values and the allowed options (load types, vehicle types, goods classes, stackability, incoterms, movement types) — "FKZ8515'te neyi değiştirebilirim?". (lettura · — · tutti · API: get_load_edit_form)
lg loads preview-copy — Prepare a copy draft of one of your company's OWN loads (yükü kopyala) — "FKZ8515'in aynısından bir tane daha açalım": transport mode, countries, addresses, load type, vehicle type, weight, goods class, incoterms, ports… (lettura · — · tutti · API: get_load_copy_template)
lg loads remove-driver — Remove the driver from a load (the opposite of assign_driver_to_load): the load disappears from the driver's app and GPS tracking of the load stops. (scrittura · conferma · autotrasportatore · API: unassign_driver_from_load)
lg loads search — Full-text search across your loads (yük ara) — company names, pickup/delivery address, order references, load code, text written in the load chat and text read from documents shared in the chat: "içinde PO-4471 geçen… (lettura · — · tutti · API: search_loads)
lg loads set-status — Move a load to a new transport status and append it to the load's status history (this is what the customer sees on the tracking screen). (scrittura · conferma + irreversibile · autotrasportatore · API: update_load_status)
lg loads set-stop-status — Mark one stop of a multi-stop load as completed, or undo it (completed=false) — "FKZ8515's second drop-off is done". (scrittura · conferma · autotrasportatore · API: mark_load_stop_completed)
lg loads set-tracking — Turn a load's GPS location tracking on or off (konum takibi) — "stop location tracking for FKZ8515", "resume tracking". (scrittura · conferma · autotrasportatore · API: set_load_location_tracking)
lg loads update — Edit an existing load (yükü düzenle): loading date, weight, load type, vehicle types, goods class, stackability, pickup/delivery address, incoterms, movement type, loading/destination port. (scrittura · conferma + irreversibile · tutti · API: update_load)
lg maturity-options list — The selectable payment terms (vade): maturity_option_id and the number of days (0 = cash / peşin). maturity_option_id is what update_company_profile takes. (lettura · — · tutti · API: list_maturity_options)
lg notification-settings get — Read our company's notification switches (Settings → Notifications): which e-mail notifications (type "notification") and push notifications (type "web-push") are on for the whole company — e.g. message, load, demand… (lettura · — · committente · API: get_notification_settings) [chiave manager]
lg notification-settings update — Turn our company's notification switches on or off (Settings → Notifications) — e.g. stop load chat push notifications or message e-mails for the whole company. settings is a list of {slug, enabled}; slugs come from… (scrittura · conferma · committente · API: update_notification_settings) [chiave manager]
lg notifications list — Read the signed-in user's own notification inbox (the bell icon): what happened, which kind of event it was, when, whether it is still unread, and the panel address the notification points at. (lettura · — · tutti · API: list_notifications)
lg notifications mark-read — Mark ALL of the signed-in user's unread notifications as read (empty the bell). (scrittura · — · tutti · API: mark_notifications_read)
lg packages get — Read this company's package and CREDIT balance: how many credits are left, how many the package grants per year, how many were used, the renewal date, and the assistant token usage of the current period (1,000,000… (lettura · — · tutti · API: get_credit_balance)
lg packages list — List the Logistivo packages this company can buy: slug, name, monthly price and yearly upfront total in the company's BILLING currency (TRY for Türkiye-billed companies, EUR otherwise — never converted with an exchange… (lettura · — · tutti · API: list_packages)
lg pallets add-measurement — Record a NEW measurement for an existing pallet (dimensions in centimetres and/or gross weight in kilograms). (scrittura · conferma · tutti · API: add_pallet_measurement)
lg pallets add-proof — Attach a proof photo to one of this company's pallets (e.g. the wrapped pallet, its label, damage on arrival). (scrittura · — · tutti · API: add_pallet_proof) [accetta un file: attachment_uuid]
lg pallets calculate — Suggest the missing base side of a pallet from a standard footprint (EUR 120×80, industrial 120×100, half 80×60; ±5 cm) when only one base side is known, and compute the volume when length, width and height are all… (lettura · — · tutti · API: complete_pallet_dimensions)
lg pallets create — Register a NEW pallet in a warehouse, optionally with its first measurement. warehouse_id is required — resolve the warehouse name with lookup_warehouse first. (scrittura · conferma · tutti · API: create_pallet)
lg pallets delete — Delete one of this company's pallet records. (scrittura · conferma + irreversibile · tutti · API: delete_pallet)
lg pallets delete-proof — Remove one proof photo from one of this company's pallets. (scrittura · conferma + irreversibile · tutti · API: delete_pallet_proof)
lg pallets extract — Estimate a pallet's content label, dimensions (cm) and gross weight (kg) from photo(s) the user attached to THIS conversation. (scrittura · — · tutti · API: extract_pallet_from_photos) [accetta un file: attachment_uuids]
lg pallets get — Read one pallet in full: its identity (code, label, SKU, barcode), status, warehouse and area, the FULL measurement history (each row with its id, source — manual, lidar, arcore or ai_photo — and confidence), its proof… (lettura · — · tutti · API: get_pallet)
lg pallets list — List the pallets of this company: code, label, SKU/barcode, status, which warehouse and area it sits in, its latest measured dimensions (cm) and gross weight, and how many proof photos it has. (lettura · — · tutti · API: list_pallets)
lg pallets update — Update an existing pallet: its status (in_stock, in_transit, reserved, shipped, disposed), its label/SKU/barcode/note, or MOVE it to another warehouse or area. (scrittura · conferma · tutti · API: update_pallet)
lg parasut-contacts create — Create a new customer or supplier contact IN PARAŞÜT and keep its local copy. (scrittura · conferma + irreversibile · tutti · API: create_parasut_contact)
lg parasut-contacts list — List the customer / supplier contacts held in Paraşüt (the local copy synchronised from Paraşüt): parasut_contact_id (the Paraşüt id used by create_parasut_sales_invoice — NOT a business contact id), name, short name,… (lettura · — · tutti · API: list_parasut_contacts)
lg parasut-invoices create — Issue a SALES invoice in Paraşüt for one of this company's Paraşüt contacts, as an e-invoice (scenario commercial or basic — the recipient must be an e-invoice user) or an e-archive invoice (scenario e_archive); check… (scrittura · conferma + irreversibile · tutti · API: create_parasut_sales_invoice)
lg parasut-invoices list — List invoices held in Paraşüt (local copy): sales invoices (default) or purchase bills, newest issue date first — invoice id and number, item type, description, issue / due date, net / gross / VAT totals, currency,… (lettura · — · tutti · API: list_parasut_invoices)
lg parasut-invoices options — Return the options of the Paraşüt invoice form: income/expense categories (category_id), the Paraşüt bank and cash accounts, and — with tax_number — whether that VKN is a registered e-invoice user (then use scenario… (lettura · — · tutti · API: get_parasut_invoice_options)
lg parasut-settings delete — Disconnect Paraşüt from this company: the saved credentials are removed, the accounting provider switches back to local when it was Paraşüt, and the LOCAL copies pulled from Paraşüt (contacts, invoices, bank accounts,… (scrittura · conferma + irreversibile · tutti · API: disconnect_parasut) [chiave manager]
lg parasut-settings get — Show the Paraşüt integration status of this company: whether it is connected, the Paraşüt firm number, the user name, the client id/secret MASKED (last 4 characters only), when it was connected, the token status and the… (lettura · — · tutti · API: get_parasut_settings) [chiave manager]
lg parasut-settings update — Connect this company's Paraşüt account or renew its credentials (replaces an existing connection). (scrittura · conferma · tutti · API: connect_parasut) [chiave manager] [solo CLI]
lg payables list — Payables ("whom do we owe how much"): per-supplier totals of recorded purchase invoices — invoiced, paid, remaining, earliest due date — with a per-currency breakdown and an overall summary. (lettura · — · tutti · API: list_payables)
lg payment-cards delete — Remove a saved payment card (card_id from list_payment_cards). (scrittura · conferma + irreversibile · tutti · API: delete_payment_card) [chiave manager]
lg payment-cards list — List the company's saved payment cards, MASKED (last four digits only), with the card holder name, expiry and which one is the default card the monthly subscription is charged to. (lettura · — · tutti · API: list_payment_cards)
lg payment-cards set-default — Make one of the saved cards (card_id from list_payment_cards) the DEFAULT card: the monthly package payment is charged to it from now on, and every other card loses the default flag. (scrittura · conferma + irreversibile · tutti · API: set_default_payment_card) [chiave manager]
lg payment-instructions cancel — CANCEL a pending bank payment instruction: the reservation on its invoices is released so they can be paid another way, and the instruction becomes "cancelled". (scrittura · conferma + irreversibile · tutti · API: cancel_settlement_instruction)
lg payment-instructions download — Get the bank payment instruction document (PDF) with a short-lived download link. (lettura · — · tutti · API: download_settlement_instruction)
lg payment-instructions get — Read one bank payment instruction: its code, template, effective date, status with timestamps and cancel reason, its note, and — when the PDF has already been rendered — a short-lived signed link to it so the user gets… (lettura · — · tutti · API: get_settlement_instruction)
lg payment-instructions list — List the bank payment instructions of this company: instruction code, which template (bank format) it uses, its effective date, status (pending, executed, cancelled) and when it was executed or cancelled. (lettura · — · tutti · API: list_settlement_instructions)
lg payment-instructions run — EXECUTE a pending bank payment instruction (banka talimatını yürüt / uygula): the reserved invoices are paid, the payments and journal entries are written with the instruction's effective date, and the instruction… (scrittura · conferma + irreversibile · tutti · API: execute_settlement_instruction)
lg planning-boards get — The planning calendar: for every driver, the stretches of days with planned work inside the Schengen area (planned_in), days assumed inside (drive back, assumed_in), planned work outside (planned_out), leave / rest… (lettura · — · autotrasportatore · API: get_planning_board)
lg plans archive — Close a plan because the user says the work is finished or abandoned. (scrittura · — · tutti · API: archive_plan)
lg plans create — Write down a multi-step job so it survives between conversations ("link these 5 loads to a trip, then invoice them"). (scrittura · conferma · tutti · API: create_plan)
lg plans get — Read one plan: the steps that were agreed AND the commands that actually ran while it was active. (lettura · — · tutti · API: get_plan)
lg plans list — List this company's plans, newest first. (lettura · — · tutti · API: list_plans)
lg ports search — Find a seaport by name or UN/LOCODE (liman ara) — "Mersin", "TRMER", "Trieste". (lettura · — · tutti · API: lookup_port)
lg preferences create — Remember a lasting preference of THIS user, so it applies to every future conversation too ("always show amounts in EUR", "write driver names surname first", "I want the weekly summary on Mondays"). (scrittura · — · tutti · API: remember_preference)
lg preferences delete — Forget one stored preference of this user. (scrittura · — · tutti · API: forget_preference)
lg preferences list — List what you have been asked to remember about THIS user, with the labels. (lettura · — · tutti · API: list_preferences)
lg product-brands create — Create a new product brand for this company (the panel's "new brand"). (scrittura · conferma · committente · API: create_product_brand)
lg product-brands list — List this company's product brands (id, name, code, active flag, number of products). (lettura · — · committente · API: list_product_brands)
lg product-categories create — Create a new product category for this company (the panel's "new category"). (scrittura · conferma · committente · API: create_product_category)
lg product-categories list — List this company's product categories (id, name, code, active flag, number of products). (lettura · — · committente · API: list_product_categories)
lg products add-image — Add a photo to a product's gallery. (scrittura · — · committente · API: add_product_image) [accetta un file: attachment_uuid]
lg products create — Define a new product in this company's catalogue so stock can be recorded against it: name plus optionally its unit of measure, SKU, barcode, category, brand, minimum stock level, reorder quantity and lot tracking. (scrittura · conferma · committente · API: create_product)
lg products delete — Delete a product from this company's catalogue. (scrittura · conferma + irreversibile · committente · API: delete_product)
lg products delete-image — Remove one photo from a product's gallery (image_id from get_product). (scrittura · conferma + irreversibile · committente · API: delete_product_image)
lg products extract — Read product details (name, description, SKU, barcode, unit, category, brand) from 1-5 photos of the product or its label — the panel's "fill from photo" button. (scrittura · — · committente · API: extract_product_from_photos) [accetta un file: attachment_uuids]
lg products get — Show one product of this company in full: code, SKU, barcode, unit, category and brand, low-stock threshold and reorder quantity, lot tracking, its photos (with image_id for delete_product_image /… (lettura · — · committente · API: get_product)
lg products list — List the products of this company: code, name, SKU/barcode, unit, category and brand, whether it is active, and its low-stock threshold. (lettura · — · committente · API: list_products)
lg products list-low-stock — List the products whose quantity on hand is BELOW their low-stock threshold (strictly below — a product exactly at the threshold is not listed), with the quantity on hand and the threshold itself. (lettura · — · committente · API: list_low_stock_products)
lg products options — List the units of measure a product can be held in (slug for create_product / update_product unit, with Turkish and English names). (lettura · — · committente · API: get_product_options)
lg products search — Resolve a product to its product_id + on-hand quantity. (lettura · — · committente · API: lookup_product)
lg products set-primary-image — Make one of a product's photos its cover image (image_id from get_product). (scrittura · — · committente · API: set_product_primary_image)
lg products update — Correct an existing product: its name, unit, SKU, barcode, category, brand, minimum stock level, reorder quantity, lot tracking, note, or whether it is active. (scrittura · conferma · committente · API: update_product)
lg receivables get — Account statement of one contact: every sales invoice issued to them and every collection, in date order with a running balance, plus totals (invoiced, paid, open balance, open invoice count). (lettura · — · tutti · API: get_receivable_statement)
lg receivables list — Receivables ("who owes us how much"): per-contact totals of issued sales invoices — invoiced, paid, remaining — with a per-currency breakdown and an overall summary. (lettura · — · tutti · API: list_receivables)
lg report-files create — Turn a table you compiled from tool results into a downloadable Excel (default), PDF or CSV file — any custom table, list, comparison or export, with optional charts. (lettura · — · tutti · API: create_report_file)
lg reports get — Financial reports from posted journal entries: trial_balance (per-account debit/credit/balance as of a date), balance_sheet (as of a date) or income_statement (revenues/expenses/net income for a date range; defaults to… (lettura · — · tutti · API: get_accounting_report)
lg reservations approve — As the warehouse owner, approve a pending reservation received at your warehouse (the booker is notified). (scrittura · conferma · committente · API: approve_reservation)
lg reservations cancel — Cancel (withdraw) a warehouse reservation you booked, or — as the warehouse owner (customer) — cancel a reservation received at your warehouse. (scrittura · conferma + irreversibile · tutti · API: cancel_reservation)
lg reservations complete — As the warehouse owner, mark an APPROVED reservation at one of your warehouses as completed (the vehicle came and the work is done). (scrittura · conferma + irreversibile · committente · API: complete_reservation)
lg reservations create — Book a warehouse dock time slot. (scrittura · conferma · tutti · API: create_reservation)
lg reservations get — Detail of one warehouse reservation you booked or (customer) one received at your warehouse: warehouse, area, time window, status, contact, notes, rejection reason. (lettura · — · tutti · API: get_reservation)
lg reservations list — List warehouse dock reservations. side=booked_by_me (default): reservations this user/company booked at other companies' warehouses. side=received (customer role only): reservations other companies made at ONE of your… (lettura · — · tutti · API: list_reservations)
lg reservations list-slots — Available dock time slots of one day with remaining capacity. (lettura · — · tutti · API: list_reservation_slots)
lg reservations reject — As the warehouse owner, reject a pending reservation received at your warehouse, with an optional reason shown to the booker. (scrittura · conferma + irreversibile · committente · API: reject_reservation)
lg reservations reschedule — As the warehouse owner, move a PENDING or APPROVED reservation at one of your warehouses to a new time. (scrittura · conferma · committente · API: reschedule_reservation)
lg roro-routes list — For a load you are carrying, list the Ro-Ro (ferry) lines closest to its PICKUP address, nearest first: the line name, its departure and arrival ports and how many kilometres the pickup point is from the departure port. (lettura · — · autotrasportatore · API: list_nearby_roro_routes)
lg roro-routes select — Select the Ro-Ro (ferry) line a load you are carrying will use. (scrittura · conferma · autotrasportatore · API: select_roro_route)
lg roro-routes set-required — Mark whether a load you are carrying will travel by Ro-Ro (ferry) or not. (scrittura · conferma · autotrasportatore · API: set_load_roro_required)
lg route-plans assign-driver — Assign a driver (and, on a double-crew plan, a co-driver; optionally the vehicle/trailer) to a saved route plan (route_plan_id or route_plan_code). (scrittura · conferma · autotrasportatore · API: assign_driver_to_route_plan)
lg route-plans calculate — Calculate a multi-stop truck journey WITHOUT saving it: truck driving time (car time × hgv_factor, capped speed), the EU 561/2006 / AETR breaks, daily and weekly rests, weekend/holiday driving bans and border waits, and… (scrittura · conferma · autotrasportatore · API: calculate_route_plan)
lg route-plans create — Save a route plan as a DRAFT (same arguments as calculate_route_plan, plus name, vehicle_id, trailer_id, start_flex_days). (scrittura · conferma · autotrasportatore · API: create_route_plan)
lg route-plans delete — Cancel and delete a route plan (route_plan_id or route_plan_code). (scrittura · conferma + irreversibile · autotrasportatore · API: delete_route_plan)
lg route-plans get — One saved route plan: stops with arrival/departure ranges, the summary (distance, truck driving time, arrival optimistic / expected / conservative, breaks, daily/weekly rests, reduced rests, border waits), Schengen days… (lettura · — · autotrasportatore · API: get_route_plan)
lg route-plans list — List the company's saved route plans, newest first: code, name, status (draft | assigned | converted | cancelled), departure, crew, driver, vehicle, linked load/trip, stops, arrival range and Schengen day count. (lettura · — · autotrasportatore · API: list_route_plans)
lg route-plans preview — Compare 1-6 variants of the same journey side by side — different drivers, departure days or a double crew: arrival range, driving and rest counts, Schengen days left at the end for every crew member, availability /… (scrittura · conferma · autotrasportatore · API: compare_route_plan_scenarios)
lg route-plans remove-driver — Take the driver (and co-driver) off an assigned route plan (route_plan_id or route_plan_code); the plan goes back to draft and stops counting as planned Schengen days for them. (scrittura · conferma · autotrasportatore · API: unassign_driver_from_route_plan)
lg route-plans select — Link a saved route plan (route_plan_id or route_plan_code) to the load or trip it was planned for — give load_code OR trip_code; give neither to remove the link. (scrittura · conferma · autotrasportatore · API: link_route_plan)
lg route-plans update — Change a saved route plan (route_plan_id or route_plan_code): any create_route_plan field — name, departure, stops, crew, options, vehicle. (scrittura · conferma · autotrasportatore · API: update_route_plan)
lg schengen-stays calculate — Project ONE driver's Schengen 90/180 days into the future: days used today, then how the remaining days move with the loads, trips and route plans already assigned to him (plus the drive back out) and his leave /… (lettura · — · autotrasportatore · API: get_driver_schengen_projection)
lg schengen-stays create-set — Import drivers' past Schengen entry/exit periods (passport stamps) from an Excel/CSV file — one row per stay: driver code or name, entry date, exit date (empty = still inside). (scrittura · conferma · autotrasportatore · API: import_driver_schengen_periods) [accetta un file: attachment_uuid]
lg schengen-stays download — Give a short-lived download link to the Schengen history import template, pre-filled with the company's active drivers (user code + name; entry/exit date cells empty). (lettura · — · autotrasportatore · API: download_schengen_import_template)
lg schengen-stays get — One driver's full Schengen 90/180 picture: days used (confirmed / declared / inferred), days left (signed; negative = overstay), latest exit date, breach date, when days come back (regain schedule), per-country day… (lettura · — · autotrasportatore · API: get_driver_schengen_detail)
lg schengen-stays list — Fleet-wide Schengen 90/180 compliance: which drivers breached the 90-days-in-180 rule or are close to it, how many days each has left (days_remaining is SIGNED — negative means overstay), the latest exit date… (lettura · — · autotrasportatore · API: list_schengen_compliance)
lg schengen-stays list-periods — List the Schengen stay periods DECLARED for a driver (passport stamps / starting balance) with their period_id, entry and exit dates and day count. (lettura · — · autotrasportatore · API: list_driver_schengen_periods)
lg schengen-stays remove-period — Delete ONE wrongly entered declared Schengen period of a driver (period_id from list_driver_schengen_periods). (scrittura · conferma + irreversibile · autotrasportatore · API: delete_driver_schengen_period)
lg schengen-stays set-baseline — Set a driver's Schengen starting balance — what happened BEFORE GPS tracking: either the exact periods inside the zone from passport stamps (baseline_mode=periods) or just "X days used in the last 180"… (scrittura · conferma · autotrasportatore · API: set_driver_schengen_baseline)
lg schengen-stays set-exemption — Exempt a driver from Schengen 90/180 tracking (EU/EFTA passport, residence permit, national long-stay visa) or switch the rule back on. (scrittura · conferma · autotrasportatore · API: set_driver_schengen_exemption)
lg settlements cancel — CANCEL a bulk collection / payment (settlement batch). (scrittura · conferma + irreversibile · tutti · API: cancel_settlement_batch) [chiave manager]
lg settlements create — Close several open invoices of ONE contact in ONE currency in a single bulk collection (direction in) or bulk payment (direction out). instrument transfer = money already moved by bank transfer (payments + journal… (scrittura · conferma + irreversibile · tutti · API: create_settlement_batch)
lg settlements get — Read one bulk collection / payment (settlement batch) in full: code, direction (in = collection, out = payment), instrument (transfer, bank instruction or cheque), status, counterparty, currency and total, value date,… (lettura · — · tutti · API: get_settlement_batch)
lg settlements list — List bulk collection/payment batches (code, direction, instrument, contact, currency, total, value date, status), newest first. (lettura · — · tutti · API: list_settlement_batches)
lg settlements list-counterparties — List the business contacts that have OPEN local invoices in one money direction — in = customers owing us (sales invoices), out = suppliers we owe (purchase invoices) — each with its default open-invoice currency and… (lettura · — · tutti · API: list_settlement_counterparties)
lg settlements list-invoices — Open LOCAL invoices of one contact in one currency that can be allocated in a bulk collection (direction in = sales invoices) or bulk payment (direction out = purchase invoices), each with payable_remaining (remaining… (lettura · — · tutti · API: list_settlement_invoices)
lg settlements options — Return the options of the bulk collection / payment form: allowed currencies, this company's OWN bank accounts (bank_account_id for create_settlement_batch / attach_check_to_invoices), bank instruction templates, batch… (lettura · — · tutti · API: get_settlement_options)
lg ship-trackings create — Attach a ship to a load and track it on the load's map (yüke gemi bağla), or swap the ship (replace_ship_id = the ship being replaced) — "FKZ8515 sails on MSC Gülsün, track it". (scrittura · conferma · committente, autotrasportatore · API: track_ship_for_load)
lg ship-trackings delete — Stop tracking a ship on a load (gemi takibini durdur). (scrittura · conferma · committente, autotrasportatore · API: stop_ship_tracking)
lg ship-trackings get — Show the ship(s) tracked on a load and their position history since the load was created (yükün gemi takibi) — "where is FKZ8515's ship now". (lettura · — · tutti · API: get_load_ship_tracking)
lg ships search — Search the ship registry (gemi sicili) by name, IMO or MMSI — "what is MSC Gülsün's IMO", "find the vessel 9839430". (lettura · — · tutti · API: lookup_ship)
lg stock adjust — Record a stock count correction (sayım düzeltme) or write-off (fire). mode=set sets the absolute on-hand at the slot; mode=delta applies a signed change (negative reduces). reason is required. (scrittura · conferma + irreversibile · committente · API: create_stock_adjustment)
lg stock list — Read current on-hand stock levels. (lettura · — · committente · API: check_stock_level)
lg stock list-movements — List the stock movements of this company, newest first: which product moved, in or out (or a transfer or a count adjustment), how much, in which warehouse and area, on which pallet, who performed it and when. (lettura · — · committente · API: list_stock_movements)
lg stock move — Record a stock movement: inbound (giriş), outbound (çıkış), or transfer between locations. (scrittura · conferma + irreversibile · committente · API: create_stock_movement)
lg stock options — List the stock movement types (receipt, issue, transfer, count adjustment …) with their slug and Turkish/English names — the values create_stock_movement and list_stock_movements use. (lettura · — · committente · API: get_stock_options)
lg sub-companies create — Add a group / sub company (alt firma) to this customer company: legal_name (ticaret unvanı), tax_office (vergi dairesi), tax_number and the full address — all four required. (scrittura · conferma · committente · API: create_sub_company) [chiave manager]
lg sub-companies delete — Delete one of this customer company's group / sub companies (alt firma) by sub_company_id from list_sub_companies. (scrittura · conferma + irreversibile · committente · API: delete_sub_company) [chiave manager]
lg sub-companies list — This customer company's group / sub companies (alt firmalar, grup şirketleri — Settings › Sub Companies): sub_company_id, legal name, tax office, tax number and address. (lettura · — · committente · API: list_sub_companies)
lg tariff-chapters get — Answer "which chapter is this GTİP in / what does chapter 76 cover / what do the chapter notes say?". (lettura · — · tutti · API: get_tariff_chapter)
lg tariff-matrices get — FREE. (lettura · — · tutti · API: get_tariff_matrix)
lg tariff-matrices list — FREE. (lettura · — · tutti · API: list_tariff_matrix_runs)
lg tariff-matrices preview — FREE. (lettura · — · tutti · API: plan_tariff_matrix)
lg tariff-matrices run — Run an official duty + anti-dumping inquiry for ONE tariff code across MANY origin and destination countries at once, and record it. (scrittura · conferma + irreversibile · tutti · API: run_tariff_matrix)
lg tariffs coverage — FREE. (lettura · — · tutti · API: get_tariff_coverage)
lg tariffs extract — Read an invoice or proforma the user attached to THIS conversation and pull out its product lines with candidate GTİP/HS codes, plus the origin and destination it names. (scrittura · — · tutti · API: extract_tariff_codes_from_invoice) [accetta un file: attachment_uuid]
lg tariffs get — Read the result of a tariff inquiry that was already run: duty rate, the column it came from, the statutory rate, anti-dumping measures and the data notes. (lettura · — · tutti · API: get_tariff_inquiry)
lg tariffs inquiry — Start an official duty / anti-dumping inquiry for one GTİP/HS code and a COUNTRY PAIR (origin → destination). (scrittura · conferma + irreversibile · tutti · API: run_tariff_inquiry)
lg tariffs list — List this company's recent tariff inquiries (code, direction, counterpart country, status, date) so the user can find an earlier one by code or country instead of running a new inquiry. (lettura · — · tutti · API: list_tariff_inquiries)
lg tariffs search — Search the Turkish customs nomenclature (GTİP / HS) by goods description or by a partial code, and return matching codes with their official descriptions. (lettura · — · tutti · API: lookup_tariff_code)
lg teammates delete — Remove a person from the company team. (scrittura · conferma + irreversibile · tutti · API: remove_teammate) [chiave manager]
lg teammates list — List the other users of this company (drivers excluded) with e-mail, active state and RBAC role (manager | employee | fleet-manager), plus seat_usage (team seats used / limit / remaining under the package). role narrows… (lettura · — · tutti · API: list_teammates)
lg teammates set-role — Change a team member's role (for example make them a manager, or move them back to employee). (scrittura · conferma · tutti · API: update_teammate_role) [chiave manager]
lg teammates set-status — Activate or deactivate a team member. (scrittura · conferma · tutti · API: set_teammate_status) [chiave manager]
lg tender-bids create — Submit YOUR bid for a tender using a file the user attached to THIS conversation (the filled specification spreadsheet, a PDF offer, or a zip). (scrittura · conferma + irreversibile · autotrasportatore · API: submit_tender_bid) [accetta un file: attachment_uuid]
lg tender-bids get — Read YOUR OWN bid on a tender: its status (submitted, revision requested, accepted, rejected), when it was submitted and which files it carries. (lettura · — · autotrasportatore · API: get_my_tender_bid)
lg tender-bids set-status — As the tender owner, ACCEPT a carrier's bid, REJECT it, or ask for a REVISION. (scrittura · conferma + irreversibile · committente · API: decide_tender_bid)
lg tenders add-document — Attach a file to one of YOUR tenders as an additional specification document (accepted: pdf, xlsx, xls, doc, docx; at most 10 MB). (scrittura · conferma · committente · API: add_tender_document) [accetta un file: attachment_uuid]
lg tenders create — Open a NEW document-based freight tender and generate its specification Excel from the lanes the user gives (origin → destination, vehicle/load type, monthly volume). (scrittura · conferma · committente · API: create_tender) [accetta un file: attachment_uuid]
lg tenders delete-document — Remove a specification file from one of YOUR tenders (document_id from get_tender → documents[]). (scrittura · conferma + irreversibile · committente · API: delete_tender_document)
lg tenders extract — Draft the specification (terms) text of a tender from a tender document the user supplies (accepted: pdf, xlsx, xls; at most 10 MB). (lettura · — · committente · API: extract_tender_specification) [accetta un file: attachment_uuid]
lg tenders generate — Generate a specification Excel for an EXISTING tender from the lanes/items the user gives and attach it to the tender as a document; returns a short-lived download link. (scrittura · conferma · committente · API: generate_tender_excel)
lg tenders get — Read one tender in full: specification text, dates, attached specification files (with short-lived download links) and — for the tender owner — every carrier bid with its status; a carrier sees only its own bid. (lettura · — · committente, autotrasportatore · API: get_tender)
lg tenders list — List document-based freight tenders. (lettura · — · committente, autotrasportatore · API: list_tenders)
lg tenders update — Edit one of YOUR tenders: title, description, specification text, the bidding window (start_date / end_date), the price-validity window, whether it still accepts bids (is_active), its status, and who it is shared with. (scrittura · conferma · committente · API: update_tender)
lg trade-measures get — Answer "is there an anti-dumping / countervailing / safeguard measure on this GTİP code when importing INTO TURKEY?" straight from the Ministry of Trade's measures-in-force list, which we sync every day. (lettura · — · tutti · API: get_trade_measures)
lg trade-measures list — Browse Türkiye's trade-defence measures WITHOUT a GTİP code: by origin country ("which measures apply to goods from China"), by product ("which countries have a measure on aluminium foil"), by measure type, or by end… (lettura · — · tutti · API: list_trade_measures)
lg user-accounts preview — Show what closing MY OWN account would do, without closing it: whether I am a manager, whether I am the only user (then the company is deactivated too), whether I must first hand the manager role to a teammate… (lettura · — · tutti · API: preview_account_closure)
lg users get — Who am I? (lettura · — · tutti · API: get_current_user)
lg vehicle-assignments create — Hand a fleet vehicle over to a driver (open an assignment), so their expense receipts and trips are attached to the right tractor unit or trailer. (scrittura · conferma · committente, autotrasportatore · API: assign_vehicle_to_driver)
lg vehicle-assignments list — List which driver currently holds which vehicle (tractor unit / trailer). (lettura · — · committente, autotrasportatore · API: list_vehicle_assignments)
lg vehicle-assignments revoke — Close an open vehicle assignment: the driver hands the vehicle back. (scrittura · conferma · committente, autotrasportatore · API: end_vehicle_assignment)
lg vehicle-expenses create — Record a cost against one of the company's own vehicles without an invoice file — category, amount and currency are required, the rest is optional. (scrittura · conferma · committente, autotrasportatore · API: create_vehicle_expense) [accetta un file: attachment_uuid]
lg vehicle-expenses delete — Delete a vehicle cost entered by mistake (duplicate, wrong plate, test entry). (scrittura · conferma + irreversibile · committente, autotrasportatore · API: delete_vehicle_expense)
lg vehicle-expenses list — List the cost records of the company's own vehicles (maintenance, tyres, repair, roadworthiness test, insurance, fuel, tolls, parts) with a EUR total and a breakdown per category and per currency. (lettura · — · committente, autotrasportatore · API: list_vehicle_expenses)
lg vehicle-expenses update — Correct a recorded vehicle cost: category, amount, currency, vendor, invoice number, invoice date or description — "the tyre invoice was 580 not 850". (scrittura · conferma · committente, autotrasportatore · API: update_vehicle_expense)
lg vehicles add-document — File a paper of one of the company's own vehicles — registration (ruhsat), traffic or kasko insurance, roadworthiness inspection, tachograph calibration, CMR insurance, green card, ADR certificate — from an uploaded… (scrittura · conferma · committente, autotrasportatore · API: add_vehicle_document) [accetta un file: attachment_uuid]
lg vehicles archive — Take a vehicle out of service (archive it) or put an archived one back into service. (scrittura · conferma · committente, autotrasportatore · API: archive_vehicle)
lg vehicles create — Add a vehicle to this company's fleet: plate plus its kind (truck, tractor unit, trailer, van, pickup, car), optionally brand, model, model year, VIN and a note. (scrittura · conferma · committente, autotrasportatore · API: create_vehicle) [accetta un file: attachment_uuid]
lg vehicles delete — Delete a vehicle record that was created BY MISTAKE (wrong plate, duplicate). (scrittura · conferma + irreversibile · committente, autotrasportatore · API: delete_vehicle)
lg vehicles delete-document — Remove a paper from a vehicle's file (a duplicate row, a paper filed on the wrong vehicle, an old registration). (scrittura · conferma + irreversibile · committente, autotrasportatore · API: delete_vehicle_document)
lg vehicles get — Full detail of ONE fleet vehicle: identity (plate, kind, brand, model, model year, VIN), whether it is active or archived, ALL of its papers with their expiry date and days_to_expiry, how many papers expire soon or… (lettura · — · committente, autotrasportatore · API: get_vehicle)
lg vehicles list — List this company's fleet vehicles with plate, kind (truck / tractor unit / trailer / van / pickup / car), brand, model, model year, VIN and how many of their papers (insurance, inspection, permits) expire soon or have… (lettura · — · committente, autotrasportatore · API: list_vehicles)
lg vehicles search — Resolve one of this company's fleet vehicles (truck, tractor unit, trailer, van, pickup, car) to its vehicle_id by plate, brand, model or VIN. (lettura · — · committente, autotrasportatore · API: lookup_vehicle)
lg vehicles update — Correct a fleet vehicle's fields: plate, kind, brand, model, model year, VIN or note. (scrittura · conferma · committente, autotrasportatore · API: update_vehicle)
lg vehicles update-document — Correct a vehicle paper already on file — most often its expiry date (valid_until) after a renewal or a wrong AI reading, but also its type, number, issue date, issuer, the plate printed on it, issuing country, title or… (scrittura · conferma · committente, autotrasportatore · API: update_vehicle_document)
lg wallets get — Read this company's Logistivo WALLET balance — the prepaid MONEY balance (amount + currency). (lettura · — · tutti · API: get_wallet_balance)
lg wallets list-transactions — List this company's Logistivo WALLET movements, newest first: top-ups and money spent on packages or paid features, with the amount, the balance before/after, who did it and when. (lettura · — · tutti · API: list_wallet_transactions)
lg warehouse-areas create — Add a new area to one of this company's warehouses — an open area, a closed area or a loading ramp — with how many vehicles it can take at the same time (its booking slot capacity). (scrittura · conferma · committente · API: create_warehouse_area)
lg warehouse-areas delete — Delete one area/ramp of a warehouse. (scrittura · conferma + irreversibile · committente · API: delete_warehouse_area)
lg warehouse-areas update — Change a warehouse area's name, type (open_area, closed_area, ramp), vehicle capacity, display order or active flag. (scrittura · conferma · committente · API: update_warehouse_area)
lg warehouse-links create — Create a public booking link for one of this company's warehouses, to share with a carrier, supplier or customer: anyone holding the URL can book a slot (the booking still waits for your approval). (scrittura · conferma · committente · API: create_warehouse_link)
lg warehouse-links list — List the public booking links shared for one of this company's warehouses: the full URL (anyone holding it can book a slot), the area it is limited to (if any), the expiry, and whether it is active. (lettura · — · committente · API: list_warehouse_links)
lg warehouse-links revoke — Permanently revoke a warehouse booking link: the URL stops working for everyone and cannot be brought back (create a new link if needed). (scrittura · conferma + irreversibile · committente · API: revoke_warehouse_link)
lg warehouse-links set-status — Turn a warehouse booking link off (nobody can book through it) or back on. (scrittura · conferma · committente · API: set_warehouse_link_status)
lg warehouses create — Define a new warehouse for this company so stock can be held and dock slots booked there: a name and its street address are enough. (scrittura · conferma · committente · API: create_warehouse)
lg warehouses delete — Delete one of this company's warehouses. (scrittura · conferma + irreversibile · committente · API: delete_warehouse)
lg warehouses get — Read one warehouse in full: its identity and address, working days and hours, holiday opening, capacity, reservation slot rules (slot length, minimum and maximum duration), its safety and driver rules, the… (lettura · — · committente · API: get_warehouse)
lg warehouses list — List the warehouses of this company: name, address, whether it is active, its working days and hours, open/closed area capacity, the dock slot length and how many areas (racks/bays) it has. (lettura · — · committente · API: list_warehouses)
lg warehouses search — Resolve a warehouse by name to its warehouse_id, with its areas. (lettura · — · committente · API: lookup_warehouse)
lg warehouses set-equipment — Set a warehouse's equipment list IN FULL (forklift, transpallet = pallet truck, other; with quantity and an optional name/specification). (scrittura · conferma · committente · API: set_warehouse_equipment)
lg warehouses update — Update a warehouse: its name or address, working days and hours, holiday opening, capacity, dock slot rules, the driver/safety flags or the active flag. (scrittura · conferma · committente · API: update_warehouse)
Integrazione ERP e CRM — Identità: nessun account di servizio, ma un utente reale
Un ERP o un CRM si collega a Logistivo come un vero utente aziendale che possiede un token di accesso personale generato dal pannello. Un account di servizio sintetico — senza azienda, esente dai limiti di ambito, senza nessun responsabile — non viene mai creato.
È una questione di architettura, non di preferenza. L'isolamento multi-tenant si basa interamente sull'azienda dell'utente; per un'identità senza azienda l'ambito di isolamento diventa inerte, e una sola query sbagliata con quel token legge dati che non le appartengono. Il secondo motivo è l'audit: la colonna utente nel registro collega “chi l'ha eseguito” a una persona; un account di servizio rende quella colonna priva di significato e lascia senza proprietario un'integrazione che emette fatture. Il terzo è la revoca: se un token appartiene a una persona, l'integrazione si zittisce quando quella persona se ne va. Un bridge senza proprietario è il bridge che continua a scrivere in silenzio per anni.
In pratica: l'azienda crea un normale utente nel pannello (per esempio “ERP Bridge”, di proprietà di un dipendente con nome e cognome), gli assegna un ruolo ristretto, genera un token dalla sessione di quell'utente e lo inserisce nell'ERP.
Quell'utente è visibile nel sistema dei permessi, i suoi diritti possono essere ridotti e il suo token può essere revocato in modo indipendente. Ciò che è vietato non è creare un account — è creare un account che non sia legato a un tenant.
Un'integrazione per token. Se due sistemi condividono un token, la granularità della revoca sparisce: tagliare fuori il CRM significa tagliare fuori anche l'ERP.
Integrazione ERP e CRM — Versioning e deprecazione
La risposta del catalogo riporta un intero contract_version; le righe dei comandi riportano since, deprecated_at e replaced_by. La versione del contratto aumenta solo con le modifiche incompatibili (breaking change).
La versione NON aumenta per: un nuovo comando, un nuovo parametro facoltativo, un nuovo campo in una risposta. Un consumatore deve ignorare i campi che non conosce; un client che va in errore su un campo sconosciuto non è conforme.
La versione AUMENTA per: rimuovere o rinominare un comando, rimuovere un campo di risposta, rendere obbligatorio un parametro facoltativo, restringere un enum. La vecchia forma resta attiva per almeno due trimestri di calendario (6 mesi) con deprecated_at e replaced_by.
La deprecazione viene annunciata nel catalogo, non solo in un changelog. Poiché il client si costruisce dal catalogo, un comando con deprecated_at impostato stampa un avviso senza alcuna release del client, e l'integratore lo vede nei propri log.
Il nome API è congelato per sempre. L'identità CLI (dominio/verbo) poteva essere ridefinita liberamente prima dell'annuncio; dopo l'annuncio cambia solo con un incremento di versione e una finestra di migrazione, durante la quale la vecchia coppia viene servita come alias.
In pratica: la risposta del catalogo e l'header X-Contract-Version riportano la versione; ogni riga di comando riporta since, deprecated_at, replaced_by e aliases (vecchie coppie dominio/verbo). Chiamare un comando deprecato funziona ancora e risponde con un header X-Deprecated: name; deprecated_at=…; replaced_by=… più un oggetto deprecated nel corpo. ?domain= sul catalogo risolve un vecchio dominio alias nel comando attuale.
Un client che comprende la versione 1 e incontra un numero più alto dovrebbe registrare un avviso e proseguire; lg fa esattamente così. I ritiri in vigore sono elencati nella promessa di stabilità qui sopra.
Integrazione ERP e CRM — Identificativi stabili: non dare mai al tuo ERP un id auto-incrementale come chiave
Gli id interni auto-incrementali sono opachi e limitati al tenant: l'id valido di un'altra azienda per te restituisce “non trovato”, non dati. Ma essere opachi non li rende chiavi di business. Ciò che un ERP memorizza nel proprio record deve essere una chiave di business.
Carico: code (il codice cliente, ad es. FSK2158). loads get funziona già tramite code.
Paese: ISO 3166-1 alpha-2. countries search restituisce il codice.
HS / tariffa: il codice stesso — la nomenclatura è già universale.
Fattura: il numero di fattura, una volta emessa. Una bozza ha solo un id di superficie, e l'id di una bozza NON è una chiave di business — l'ERP dovrebbe portare il proprio riferimento e non salvare mai l'id di una bozza.
Prodotto, magazzino, contatto: oggi solo un id di superficie. La regola per i nuovi comandi è esplicita: ogni comando che restituisce un id di superficie restituisce anche la chiave di business del tenant (SKU, codice, partita IVA), così l'ERP può fare la corrispondenza dalla sua parte.
Integrazione ERP e CRM — Paginazione, filtri e sync incrementale
I comandi di elenco accettano limit e restituiscono count. Per una sync notturna il contratto si impegna su quanto segue; un comando di elenco che lo ha adottato dichiara cursor e updated_since nel suo JSON Schema, e finché non lo fa trattalo come una finestra piccola (massimo 20 righe, nessun cursore).
Richiesta: limit (da 1 al limite massimo del comando) più cursor (opaco, solo in avanti, firmato dal server). offset NON viene usato — in una tabella live un offset si sposta; un record inserito tra due pagine fa saltare una riga all'ERP o gliela fa contare due volte, e succede in silenzio.
Risposta: { count, total?, next_cursor|null }. count è il numero di righe in questa risposta; quando next_cursor è null l'elenco è completo. Restituisci next_cursor invariato — non è un numero di pagina e non spetta a te costruirlo.
Un cursore manomesso o estraneo viene rifiutato con 422 invalid_request; un cursore è legato all'azienda che lo ha ricevuto e non può paginare i dati di un altro tenant.
Filtri: i parametri con nome dello JSON Schema, combinati in AND. Non esiste un linguaggio di query libero — un DSL sarebbe una seconda superficie di query da difendere.
Sync incrementale: updated_since (ISO-8601, UTC) più il cursore. Memorizza l'updated_at più recente che hai visto e ripassalo all'esecuzione successiva; senza di esso ogni ERP riscarica tutto ogni ora.
Riferimento esterno: i comandi di scrittura accettano external_ref (la chiave del tuo documento), unica per azienda; una seconda creazione con lo stesso external_ref viene rifiutata anziché duplicata, e list/get lo restituiscono così puoi abbinare i record dalla tua parte.
Integrazione ERP e CRM — Rate limit
La chiave del limite è il token, non l'IP: un ERP arriva da dietro un unico NAT, e un limite basato sull'IP conterebbe un'intera azienda come un solo utente. Due integrazioni con due chiavi non si consumano mai la quota a vicenda — il secondo motivo di “un'integrazione per chiave”.
Discovery senza autenticazione (public/cli/catalog): 30 al minuto. È un dizionario, non una fonte di dati; leggilo una volta mentre scrivi il tuo bridge, mai in un ciclo di produzione.
Endpoint del catalogo (GET common/commands, GET common/commands/{name}): 120 al minuto per token. Il catalogo cambia di rado e risponde 304 a If-None-Match; non riscaricarlo prima di ogni comando — lg lo tiene in cache per un'ora.
Comandi di lettura (POST common/commands/{name} con read_only: true): 120 al minuto per token.
Comandi di scrittura (POST common/commands/{name} con read_only: false; anche un nome sconosciuto conta qui): 30 al minuto per token. Le scritture hanno effetti collaterali; un ciclo fuori controllo viene addebitato.
Comandi che spendono crediti (credit_cost nella riga del catalogo non è zero — per esempio tariffs inquiry ed export-documents generate): il limite reale sono i CREDITI, non il numero di richieste. Una risposta 200 può aver speso un credito.
Limiti giornalieri per azienda, condivisi con il pannello: i comandi che inviano email o notifiche push a persone esterne alla tua azienda attingono a 300 notifiche in uscita al giorno, e l'avvio del tracciamento a pagamento di container o navi a 100 al giorno. Oltre il limite un comando risponde DAILY_LIMIT_REACHED con retry_after; gli upload di file hanno limiti propri (vedi Comandi che accettano file).
429 riporta sempre Retry-After e un corpo { error_code: "rate_limited", retry_after, limit, bucket }; rispettalo invece di inventare un ritardo fisso. Il catalogo pubblica i valori attuali sotto rate_limits.
Integrazione ERP e CRM — Cose che non faremo
Spesso è la parte più utile di un contratto: sapere cosa non arriverà mai ti permette di progettare di conseguenza.
Nessun account di servizio e nessuna identità che non sia legata a un tenant.
Nessun pagamento, numero di carta o consenso legale tramite l'API o una chat. Questi passaggi restano nel browser della persona; un comando ti fornisce il link.
Nessuna seconda strada: non esiste accesso diretto al database, accesso shell né un endpoint massivo che aggiri l'unico punto di applicazione. Il controllo del ruolo, il controllo di conferma, l'idempotenza e il registro di audit sono applicati solo lì.
Decidere in base al testo del messaggio di errore non è supportato; il testo è localizzato e cambia senza preavviso.
Nessuna paginazione con offset.
Usare un id di superficie come chiave di business nel tuo ERP non è supportato.
I webhook in uscita non vengono infilati in questo contratto — ma ora ESISTONO e sono documentati in questa pagina (la sezione webhook qui sopra). Il catalogo è una superficie PULL e il flusso di eventi è un contratto SEPARATO: i nomi degli eventi e lo schema del payload sono versionati con regole proprie e non sono legati alla versione del contratto del catalogo dei comandi.
Il catalogo leggibile dalle macchine
Questa pagina è stata scritta per le persone. Per un assistente IA o un client automatico, le stesse informazioni esistono come copia strutturata e senza autenticazione.
GET /api/public/cli/catalog non richiede autenticazione e restituisce l'identità pubblica dei comandi: il nome API congelato, l'identità CLI dominio/verbo, la descrizione, i parametri JSON Schema, i flag read_only, confirmation_needed e irreversible, il credit_cost e i campi di accesso key_level, permission, file_params, secret_parameters e cli_only. Non restituisce dati personali, dati di tenant né record di esempio — solo com'è fatta la superficie.
Il modo giusto in cui un agente esterno può usarlo: leggere il catalogo, spiegare con PAROLE PROPRIE quali lavori sono possibili e, quando serve un'esecuzione, indirizzare l'utente a eseguirla nel proprio ambiente con il proprio token. L'agente non chiede, non genera e non inoltra mai il token di un utente.
Collegare Logistivo a un assistente IA per la registrazione e le richieste di trasporto è un canale separato, con una pagina dedicata:
Il catalogo è senza autenticazione; l'esecuzione no. Non c'è modo di eseguire un comando per conto di un agente — ciò che viene eseguito è sempre l'identità dell'utente stesso.
Una password Logistivo, un codice di verifica o un token di accesso non passano mai attraverso una chat. Non costruire un flusso che ne chieda, ne generi o ne inoltri uno.
Se un comando è irreversibile è scritto nel catalogo. Non suggerire mai “proviamo” su un comando con irreversible: true.
I comandi con un credit_cost diverso da zero (per esempio tariffs inquiry ed export-documents generate) hanno un esito monetario; non chiamarli in un ciclo automatico.
Pagamenti, numeri di carta e consensi legali non passano mai da una chat o da un agente. Offri invece il link di handoff-links generate; la persona completa il passaggio nel proprio browser.
Un agente che agisce con la chiave di un utente dovrebbe chiamare prima users get: restituisce il ruolo, il livello di accesso della chiave, i permessi effettivi e se un consenso in sospeso o una verifica del telefono stanno bloccando le scritture — prevedi i rifiuti invece di collezionarli.
Un gemello in testo semplice di questa pagina si trova su /cli.md; usalo se analizzi il markdown in modo più affidabile dell'HTML.
La definizione leggibile dalle macchine: OpenAPI 3.1 e Postman
Il catalogo qui sopra è il formato proprio di Logistivo. Le stesse informazioni sono pubblicate anche in due formati standard del settore che i tuoi strumenti comprendono già: una definizione OpenAPI 3.1 e una collection Postman. Nessuna delle due è scritta a mano — entrambe vengono generate dal registro live dei comandi a ogni richiesta, quindi non possono diventare obsolete.
La definizione È il catalogo, non una seconda realtà. Ogni comando compare come operazione POST /api/common/commands/; lo schema del corpo è lo JSON Schema del comando stesso (byte per byte ciò che vede l'assistente), lo schema della risposta è l'envelope comune, i flag di controllo (read_only, confirmation_needed, irreversible e il badge dei crediti) stanno nell'estensione x-logistivo, e le chiavi di errore di business stanno sotto x-error-keys. Un comando ritirato è contrassegnato con deprecated: true e resta richiamabile per tutta la sua finestra di sei mesi.
Accanto alla superficie dei comandi, nella definizione ci sono anche gli endpoint REST che portano il contratto di integrazione: 10 endpoint di elenco con sync incrementale (updated_since + cursor + limit) e 7 endpoint di scrittura che accettano la tua chiave (external_ref). La superficie REST di Logistivo è molto più ampia; il resto è escluso DI PROPOSITO. Quei payload sono il contratto proprio del prodotto, e uno schema scritto per supposizione romperebbe il tuo client generato alla prima chiamata — e tu cercheresti il bug nel tuo codice, non nel nostro.
La definizione viene generata per il RUOLO di chi la richiede: il comando di un altro ruolo non entra mai nel documento, perché una definizione è un contratto, non un dizionario, e tutto ciò che contiene deve essere richiamabile con quel token. La versione senza autenticazione è l'unione dei tre ruoli, e lì ogni operazione indica sotto x-logistivo.roles quali ruoli la vedono.
Non fidarti della nostra parola — verifica: npx @redocly/cli lint logistivo-openapi.json passa senza alcun avviso.
GET /api/common/spec/openapi.json — La definizione OpenAPI 3.1 per il ruolo del tuo token. Riporta un ETag; If-None-Match ti restituisce un 304, così non la riscarichi a ogni build.
GET /api/common/spec/postman.json — Lo stesso perimetro come collection Postman v2.1, con le variabili base_url e token e le cartelle già raggruppate per dominio dei comandi.
GET /api/public/cli/openapi.json — La versione senza autenticazione — l'unione dei tre ruoli. Per progettare e stimare i costi del bridge prima di avere un token.
GET /api/public/cli/postman.json — La collection Postman senza autenticazione: un unico file da consegnare al tuo team.
559 operazioni — 519 comandi + 36 operazioni REST e del control plane + 4 endpoint di catalogo e identità. I numeri in questa pagina non sono digitati a mano; vengono contati dal documento live a ogni richiesta, quindi il giorno in cui un comando viene rilasciato aumentano anche qui — e i conti tornano.
Lo schema di sicurezza — bearerAuth: un token Passport emesso per un utente reale. Una chiave con ambito di lettura può chiamare solo le operazioni contrassegnate con x-logistivo.read_only: true; un tentativo di scrittura restituisce 403 PRIMA del controllo di conferma, quindi una chiave di sola lettura non vede mai un 409.
Ogni ramo di errore è descritto — Ogni operazione descrive separatamente 401/403/404/409/422/429/500. I due significati di 409 (conferma richiesta / conflitto di idempotenza) e i due significati di 422 (errore di schema / rifiuto di business) sono distinti nel documento, così il tuo generatore non li fonde in un unico ramo.
Nessun timestamp — Il documento non riporta alcun orario di generazione. Lo stesso catalogo produce gli stessi byte, ed è per questo che l'ETag funziona davvero e una definizione che salvi nel controllo di versione non risulta “modificata” a ogni download.
Non abbiamo inventato i payload del prodotto — Negli endpoint REST di scrittura è descritto solo il campo del contratto (external_ref); il resto del corpo resta aperto come additionalProperties: true e il lettore viene rimandato alla documentazione del prodotto. Una definizione incompleta ma vera è meglio di una completa ma inventata.
L'elenco delle chiavi di errore per operazione NON è esaustivo — x-error-keys elenca solo le chiavi che derivano con certezza dal record del comando stesso, e lo dichiara con x-error-keys-exhaustive: false. Il dizionario completo si trova alla radice del documento; tratta qualsiasi chiave che non riconosci come un fallimento generico. Un “elenco completo” fabbricato ti avrebbe spinto a non scrivere mai il ramo predefinito.
Gli strumenti di discovery non sono nella definizione — search_commands, run_command e list_capabilities esistono solo all'interno del ciclo della chat e non possono essere chiamati via HTTP. Se fossero stati inclusi, il tuo generatore avrebbe scritto tre metodi che non avrebbero mai potuto funzionare.
Generazione di codice: un client tipizzato dalla definizione
Hai la definizione; ora genera da essa codice funzionante. `lg codegen` legge il documento OpenAPI e scrive un client in un unico file, senza dipendenze — TypeScript (dichiarazioni di tipo più un sottile wrapper per le chiamate) oppure PHP (una classe client con array shape PHPDoc). Niente `npm install`, niente composer: `fetch` lato TypeScript, `ext-curl` lato PHP.
La generazione avviene sulla TUA macchina, non sul nostro server. Non è una preferenza: fissa una volta la definizione nel tuo repository (`lg spec --out=...`) e lo stesso comando gira a ogni build senza rete e senza token, così la tua CI non dipende mai dalla nostra disponibilità. E poiché il codice generato è codice che GIRA nel tuo ERP, tenerlo nel tuo repository invece di scaricarlo da un'API significa che ogni modifica compare in `git diff`.
Il client generato gestisce correttamente tutti e tre i canali di Logistivo, e capisce quale è quale dal documento invece di indovinarlo: ogni operazione dichiara il proprio canale in `x-logistivo.surface`. Il canale dei comandi estrae il contenuto dall'envelope `{success, data:{…}}`; un elenco di sync REST NON è avvolto in un envelope e viene restituito così com'è (estrarlo farebbe perdere `next_cursor`); una scrittura REST restituisce il corpo di prodotto proprio dell'endpoint. Un generatore generico non conosce questa distinzione — il nostro sì.
I tipi non sono congetture: l'interfaccia degli argomenti di ogni comando viene generata proprio dallo JSON Schema che vede l'assistente. Ciò che è obbligatorio resta obbligatorio, gli enum diventano union type, gli oggetti annidati diventano tipi annidati. In pratica: se il server richiede un campo, la chiamata che lo dimentica non fallisce con un 422 in produzione — fallisce in fase di compilazione.
Nel file non viene scritto alcun timestamp di generazione: la stessa definizione con gli stessi flag produce gli stessi byte. Rigenerare quindi non fa rumore in `git diff`, e l'unica cosa davvero cambiata — il contratto — resta visibile.
1. Fissa la definizione — La definizione viene generata per il tuo ruolo; ogni operazione che contiene è richiamabile con quel token. Fai il commit del file. lg login --api-key= lg spec --out=logistivo-openapi.json
2. Genera il client — Ne esce un unico file che contiene come metodo OGNI operazione della definizione che hai fissato: i comandi che il tuo ruolo può chiamare, gli endpoint REST che portano il contratto di integrazione e gli endpoint di discovery. Il conteggio è quello del TUO ruolo, non il totale della piattaforma — oggi una chiave da committente produce 448 metodi di comando, una da autotrasportatore 452, una da doganalista 312. Generando dalla definizione pubblica senza autenticazione il tetto è di 559 operazioni. lg codegen ts --from=logistivo-openapi.json --out=logistivo-client.ts lg codegen php --from=logistivo-openapi.json --out=LogistivoClient.php --namespace="Acme\\Logistivo" # or straight from the server, without downloading first: lg codegen ts --out=logistivo-client.ts
3. Verifica, poi usa — Se il codice generato non compila, la colpa è nostra, non tua: l'integrità della definizione è protetta da un controllo eseguibile sul server. npx tsc --noEmit --strict --target ES2022 --module ESNext --moduleResolution bundler logistivo-client.ts php -l LogistivoClient.php
Un metodo per operazione — Ogni comando del documento, ogni endpoint REST che porta il contratto di integrazione e gli endpoint di discovery. Genera dalla definizione del tuo ruolo e ottieni solo ciò che puoi chiamare (448 comandi per un committente); genera dalla definizione pubblica e ottieni tutte le 559 operazioni. Il giorno in cui un comando viene aggiunto sul server, rigenerare lo include; non c'è alcuna release del client da aspettare.
Tipi degli argomenti — Lo schema `args` di ogni comando diventa un'interfaccia (un array shape in PHP). I campi obbligatori restano obbligatori, gli enum diventano union. In TypeScript dimenticare un campo obbligatorio è un errore di compilazione; in PHP il tuo IDE e PHPStan vedono la stessa forma.
Classi di errore — La tassonomia di trasporto (`error_code`) e quella di business (`error_key`) sono campi separati; il controllo di conferma e il rate limit sono tipi di errore separati. La union delle chiavi di errore resta aperta a valori sconosciuti — quando il server dichiara una nuova chiave il tuo codice non smette di compilare, ricade nel ramo `default`.
Una politica di retry corretta — I retry automatici si applicano solo alle chiamate sicure: le letture e le scritture che portano una chiave di idempotenza. Una scrittura senza chiave che va in timeout non significa “non è stato scritto nulla”, quindi il client non la ripete mai alla cieca. Su un 429 attende il `Retry-After` del server invece di inventare un ritardo.
I corpi dei risultati non sono tipizzati — I risultati dei comandi tornano come `unknown` (`mixed` in PHP), per lo stesso motivo della definizione stessa: la forma dei risultati è l'output di business del comando, non fa parte del contratto. Un tipo di risultato indovinato inizierebbe a mentire la prima volta che un campo si sposta.
Il file generato non si modifica a mano — È un output, non un sorgente. Se ti serve un comportamento in più, avvolgi la classe generata; tutto ciò che scrivi al suo interno va perso alla generazione successiva.
Gli strumenti di discovery non vengono generati — `search_commands`, `run_command` e `list_capabilities` vivono solo all'interno del ciclo della chat e non possono essere chiamati via HTTP; sono assenti dalla definizione e quindi dal client. Includerli avrebbe significato scrivere tre metodi che non funzionano mai.
Perimetro onesto
Preferiamo far crescere questa sezione piuttosto che ridurla. Il valore di un contratto di integrazione sta meno in ciò che promette e più nella chiarezza con cui dice ciò che non fa.
La CLI gira nel contesto di un utente del tenant — Ogni comando viene eseguito con l'azienda e il ruolo dell'utente il cui token viene presentato. Una modalità da operatore di piattaforma — una modalità amministrativa che legge trasversalmente tra aziende — è fuori da questa superficie e non verrà aperta da qui.
Il tuo elenco di comandi dipende dal tuo ruolo — Un account committente vede 448 comandi, un autotrasportatore 452, un doganalista 312, un affiliato 55. Se un comando manca dal tuo catalogo, controlla prima il ruolo; se è elencato ma viene rifiutato, controlla l'ambito e il livello di accesso della chiave. Gli account autista non hanno alcun accesso a questa superficie.
Alcuni comandi spendono crediti — Le interrogazioni tariffarie, la generazione di documenti e alcuni altri comandi basati sull'IA attingono al saldo crediti del tuo piano. Ogni riga del catalogo riporta credit_cost {mode, credits}: fixed è l'addebito esatto per chiamata, read_only non addebita mai, e computed significa che l'addebito dipende dalla chiamata — credits è allora null e la cifra reale compare sulla scheda di conferma. Un preflight (dry_run) ti dice quanto addebiterebbe una chiamata e se il tuo saldo la copre.
Le chiavi di integrazione non possono guidare la chat della dashboard — L'assistente IA all'interno della dashboard è pensato per le persone. Avviare o proseguire un'esecuzione dell'assistente con una chiave di integrazione viene rifiutato con 403; gli agenti usano gli endpoint dei comandi, lg o il canale MCP, dove ogni comando viene eseguito al livello di accesso della chiave e le sue scritture vengono registrate come scritture di integrazione.
Il catalogo non sostituisce la REST API esistente — La superficie REST che alimenta le app web e mobile di Logistivo resta dov'è e rimane soggetta alla regola di retrocompatibilità. Il catalogo dei comandi non sostituisce il CRUD delle risorse; è il livello dei VERBI — l'unico modo, sottoposto ad audit, di fare una cosa.
Oggi i comandi di elenco restituiscono finestre piccole — Finché un comando di elenco non dichiara cursor e updated_since nel suo schema, il suo limite è di 20 righe senza cursore. Non è pensato per estrarre una copia completa dei tuoi dati; la sync incrementale viene estesa comando per comando.
Domande frequenti
A cosa serve la Logistivo CLI?
Svolge il lavoro del tuo account Logistivo da un terminale, da uno script o dal tuo agente IA: carichi e viaggi, richieste di trasporto, offerte e gare, flotta, autisti e le loro spese, documenti, contatti e partitari clienti e fornitori, fatture e contabilità, magazzino e scorte, membri del team, tariffe HS e dazi antidumping. Ogni azione di scrittura del pannello ha un comando; pagamenti, consensi legali e chiusura dell'account restano deliberatamente nel browser. Gli stessi comandi sono richiamabili via HTTP per le integrazioni ERP/CRM e tramite il canale MCP.
Come sono nominati i comandi nella Logistivo CLI?
La forma è lg --parameter=value. Il dominio è un'entità al plurale (loads, demands, invoices, export-documents) e il verbo proviene da un vocabolario chiuso che cresce solo per decisione esplicita (list, get, create, update, search, set-status, generate e così via). Tutti i verbi di un'entità vivono in un solo dominio, e la coppia (dominio, verbo) è unica in tutto il catalogo.
Come mi autentico nella CLI?
In modo interattivo, lg login mostra un codice di approvazione che confermi nel browser dopo aver effettuato l'accesso a Logistivo — nel terminale non si digita né una password né una chiave, e la sessione resta attiva e si rinnova da sola finché non esegui lg logout. lg login --password (email e password) resta disponibile come alternativa di riserva. Sui server e in CI, usa una chiave di integrazione emessa nel pannello o con lg keys create: lg login --api-key la salva in un profilo locale, oppure mettila nella variabile d'ambiente LOGISTIVO_TOKEN. Via HTTP il token viaggia nell'header Authorization: Bearer.
Posso creare un account di servizio per la mia integrazione ERP?
No. Un'integrazione si collega con il token di un vero utente aziendale creato nel pannello. Un'identità sintetica senza azienda rende inerte l'isolamento multi-tenant, rende priva di significato la colonna “chi l'ha eseguito” nel registro di audit e lascia un bridge che non si zittisce quando il suo proprietario se ne va. Lo schema corretto è un utente dedicato con un ruolo ristretto e un proprietario con nome e cognome.
Logistivo ha un ambiente di test (sandbox)?
Sì, ed è self-service: per la tua azienda viene aperto un tenant sandbox separato — stesso codice, stesso catalogo di comandi, un proprio registro dei crediti. L'ambiente è derivato dall'azienda della chiave e non può essere indicato nella richiesta; una chiamata fatta con il profilo sbagliato si ferma lato server con 403 ENVIRONMENT_MISMATCH. Una richiesta di trasporto aperta nella sandbox non raggiunge mai autotrasportatori reali, un evento della sandbox non viene mai consegnato alla tua sottoscrizione webhook live e il tuo saldo live non si muove. Endpoint: POST /api/common/integration-sandbox (apertura), POST /api/common/integration-sandbox/keys (chiave), GET /api/common/integration-sandbox/go-live (checklist di go-live). Dal lato di lg, lg --sandbox e lg --live sono selettori di profilo validi per una singola esecuzione.
Come leggo l'output di lg --json in uno script?
L'output è l'intero envelope HTTP: { "success": bool, "data": { "contract_version", "command", "status", "result" }, "code", "message" }. Il payload di business sta sotto .data.result; nei comandi di elenco le righe sono .data.result., il conteggio è .data.result.count e la pagina successiva è .data.result.next_cursor. Quindi il percorso jq corretto è simile a lg loads list --json | jq -r '.data.result.loads[].load_code'. Un percorso che salta l'envelope non dà errore, restituisce null in silenzio — in uno script di monitoraggio diventa un allarme che non smette mai di suonare. L'unica eccezione è /api/public/status, il cui corpo è deliberatamente privo di envelope.
Se invio due volte la stessa richiesta, ottengo record duplicati?
No, se hai inviato un idempotency_key. Una seconda chiamata con la stessa chiave non riesegue il comando; restituisce il primo risultato con stato replayed. La chiave dovrebbe essere un UUID e deve restare la STESSA tra un retry e l'altro — generare una chiave nuova per ogni tentativo equivale a non usare l'idempotenza.
Cosa fa --yes?
Supera il controllo di conferma. Quando un comando soggetto a conferma viene chiamato senza --yes non cambia nulla: il server riassume in una frase cosa sta per fare, dice se è irreversibile e si ferma (HTTP 409, exit code della CLI 4). Ripetere il comando con --yes esegue il lavoro.
Come rilevo un comando fallito in uno script?
Leggi l'exit code, mai il testo del messaggio: 0 successo, 1 rifiuto per regola di business, 2 errore di comando o di argomento, 3 errore di autenticazione o di ruolo, 4 conferma richiesta. Via HTTP gli equivalenti sono 200, 422, 404, 403 e 409, e il campo error_code nel corpo è stabile. Il MESSAGGIO di errore è localizzato e cambia senza preavviso.
Come scopro i comandi disponibili in modo programmatico?
GET /api/public/cli/catalog per la discovery senza autenticazione, e GET /api/common/commands per l'elenco che il tuo account può effettivamente vedere. Entrambi restituiscono i parametri JSON Schema di ogni comando; costruisci il tuo client a partire da questi invece di scrivere nel codice un elenco fisso di comandi.
Devo aggiornare il mio client quando viene aggiunto un nuovo comando?
No. Il client scarica il suo elenco di comandi dal catalogo, quindi un comando aggiunto sul server compare senza una nuova release del client. Un aggiornamento serve solo per una modifica incompatibile che incrementa la versione del contratto, e in quel caso la vecchia forma resta attiva per almeno sei mesi.
La CLI sostituisce la REST API esistente?
No. La superficie REST che alimenta le app web e mobile resta al suo posto. Il catalogo dei comandi non sostituisce il CRUD delle risorse; è il livello dei verbi — l'unico modo, protetto dal controllo del ruolo, dal controllo di conferma e sottoposto ad audit, di eseguire un'azione.
Come ottengo una chiave API Logistivo e cosa può fare?
La emette un responsabile con il permesso di gestione del team, nel pannello in Settings › Integration keys oppure da un terminale con lg keys create. La chiave agisce per conto di un vero membro del team e ha tre impostazioni indipendenti: l'ambito (read apre il catalogo e i comandi che non scrivono, write apre tutti i comandi — il controllo di conferma resta com'è), autorizzazioni facoltative per dominio e un livello di accesso — employee, il predefinito, per l'operatività quotidiana, oppure manager per team, impostazioni, chiavi e denaro. Viene mostrata una sola volta e non viene memorizzata sul server; può essere ruotata, trasferita e revocata. Quando il membro per conto del quale agisce se ne va, anche la chiave si chiude. Non esiste un account di servizio.
Cosa succede se riutilizzo una chiave di idempotenza per un comando diverso?
Il server risponde 409 idempotency_conflict e indica il comando per cui la chiave è stata usata la prima volta; non viene eseguito né riprodotto nulla. Le chiavi sono limitate alla tua azienda, legate a un solo comando e bloccate per 24 ore — dopo di che la stessa chiave avvia una nuova esecuzione.
Come vengono applicati i rate limit alla mia integrazione?
Per token, al minuto, in tre bucket: letture del catalogo 120, comandi di lettura 120, comandi di scrittura 30. Un 429 riporta sempre Retry-After e un corpo con retry_after, limit e bucket; attendi quel tempo e riprova. Il catalogo pubblica i valori attuali sotto rate_limits.
Come distinguo un rifiuto di business da un errore di trasporto?
Basa la logica prima su error_code: failed (422) è un rifiuto di business e riporta un error_key stabile come INSUFFICIENT_CREDITS o NOT_FOUND; server_error (5xx) e gli errori di rete si ritentano con la stessa chiave di idempotenza; per rate_limited (429) si attende. Non decidere mai in base al testo dell'errore.
Logistivo invia webhook? Per quali eventi?
Sì. Registri un indirizzo https e scegli gli eventi che ti interessano; quando accadono arriva una POST firmata. Oggi sono sottoscrivibili 13 eventi: carico creato/cambio di stato/autista assegnato, richiesta di trasporto creata e cambio di stato, offerta presentata/rivista/accettata, fattura in bozza/emessa/annullata, e prenotazione di magazzino creata/cambio di stato. Ogni nome è coperto da una classe di evento effettivamente emessa — nulla viene annunciato per poi non essere mai emesso, perché un evento del genere è un fallimento silenzioso che l'integratore aspetta per sempre. Le sottoscrizioni si creano in Settings › Integration › Webhooks, oppure da un terminale con lg webhooks create.
Come verifico la firma di un webhook Logistivo?
Ogni richiesta porta un header X-Logistivo-Signature: t=,v1=. La stringa firmata è ".", l'algoritmo è HMAC-SHA256 e la chiave è il segreto della sottoscrizione. Quattro regole: (1) verifica i byte GREZZI — decodificare e riserializzare il corpo (JSON.stringify / json_encode) trasforma gli stessi dati in byte diversi e la firma smette di corrispondere; è l'errore più comune in assoluto; (2) controlla il timestamp e scarta tutto ciò per cui |now − t| > 300 s anche se la firma è corretta; (3) confronta in tempo costante con hash_equals / timingSafeEqual; (4) deduplica su event_id, non sull'id della consegna — event_id viene mantenuto nel replay mentre l'id della consegna cambia. Ricevitori Node e PHP funzionanti si trovano in examples/webhook-receiver/ nel repository e si verificano da soli con --selftest.
Cosa succede se un webhook non può essere consegnato? Perdo l'evento?
No. Se il tuo ricevitore non restituisce 2xx la consegna entra nel piano dei tentativi: 60 · 300 · 1800 · 7200 · 21600 secondi, 6 tentativi in totale, una finestra di circa 8,6 ore. OGNI errore tranne 410 Gone viene ritentato, 4xx compresi — perdere un evento di business costa più di qualche richiesta in più. Dopo 10 consegne consecutive esaurite la sottoscrizione viene silenziata e il motivo viene registrato, così la domanda “perché non arriva niente?” ha sempre una risposta. Il registro delle consegne conserva ogni tentativo (codice di stato, durata, errore) e puoi reinviare una singola consegna dal pannello o con lg webhooks replay. La sync incrementale (updated_since + cursore) è ancora lì come rete di sicurezza.
Il mio agente IA può fare tutto ciò che un utente può fare nel pannello?
Quasi tutto. Ogni azione di scrittura del pannello ha un comando — misurato sugli endpoint di scrittura del pannello, il 100% di quelli nel perimetro è coperto — e gli stessi comandi sono aperti a lg, a HTTP e al canale MCP. Le eccezioni deliberate sono i passaggi di identità e di denaro: l'accesso, l'acquisto di un pacchetto, l'aggiunta di una carta con 3D Secure, l'approvazione dei testi legali e la chiusura di un account restano nel browser della persona, e lg handoff-links generate restituisce il link per essi. Chiavi di integrazione, webhook e sandbox si gestiscono con i comandi integrati di lg perché restituiscono segreti una sola volta.
Posso passare file come PDF o foto ai comandi dalla CLI o dall'API?
Sì. Con lg, metti @ davanti a un percorso locale (--attachment_uuid=@./cmr.pdf) e lg carica prima il file; --file è una scorciatoia quando un comando ha un solo campo file, e lg upload si limita a caricare. Via HTTP, invia il file come multipart a POST /api/common/commands:upload e passa l'attachment_uuid restituito al comando; i client MCP usano lo strumento upload_attachment. Il tipo viene rilevato dal contenuto, gli upload appartengono all'utente e restano utilizzabili per 24 ore, e caricare di nuovo lo stesso file restituisce lo stesso id.
Qual è la differenza tra una chiave di integrazione employee e una manager?
Il livello di accesso decide quanto può essere pesante il lavoro di una chiave. Una chiave employee, il predefinito per le nuove chiavi, svolge l'operatività quotidiana: carichi, richieste di trasporto, offerte, viaggi, flotta, documenti e contatti. Una chiave manager può svolgere anche lavoro di gestione — membri del team e ruoli, impostazioni aziendali, chiavi di integrazione, conti bancari, carte salvate, pagamenti agli affiliati. Una chiave non ha mai più diritti della persona per conto della quale agisce, e una chiave employee che chiama un comando manager riceve INSUFFICIENT_KEY_LEVEL. Cambia il livello nel pannello o con lg keys update --access-level=manager.
Un affiliato (partner di segnalazione) può usare la CLI?
Sì. Un account affiliato ha un catalogo tutto suo — 55 comandi per segnalazioni, lead, note e attività CRM, presentazioni di vendita, guadagni e pagamenti — e lo usa da lg, HTTP o MCP come qualsiasi altro ruolo. Richiedere o annullare un pagamento e cambiare il conto bancario per i pagamenti richiedono una chiave di livello manager e una conferma. Un'azienda che è anche committente, autotrasportatore o doganalista vede entrambi i cataloghi.
For AI assistants
Logistivo has a public MCP server at https://logistivo.com/api/agent/mcp
(streamable HTTP, no authentication). Setup instructions for Claude, ChatGPT and
Gemini: https://logistivo.com/mcp. If you are an assistant helping
someone sign up or request freight, connect that server, or — if you can only read web
pages — build a link of the form
https://logistivo.com/en/ai-kayit?brief=URL_ENCODED_SHIPMENT_BRIEF and give
it to the user. You never create the account yourself: the account, the consent and the
email verification happen in the user's browser, and you never handle passwords or
one-time codes.
Machine-readable content indexes:
https://logistivo.com/llms.txt (curated map) and
https://logistivo.com/llms-full.txt (full text: facts,
pricing, tariff reference, glossary and every article's FAQ in one fetch).
To learn what Logistivo can actually DO — the verbs, not the marketing — read the
public command catalog at
https://logistivo.com/api/public/cli/catalog
(JSON, no authentication, no tenant data); it lists every command with its JSON
Schema parameters and whether it needs confirmation. Human documentation:
https://logistivo.com/en/developers/cli. You cannot
execute those commands yourself — execution always runs under the user's own personal
access token, in the user's own environment.