Logistivo CLI: अपना लॉजिस्टिक्स संचालन टर्मिनल से और अपने ERP से चलाएँ

एक ही कमांड कैटलॉग तीन सतहों को चलाता है: lg टर्मिनल क्लाइंट, डैशबोर्ड के भीतर का AI सहायक, और वह चैनल जिससे बाहरी AI सहायक जुड़ते हैं। कोई क्षमता एक बार लिखी जाती है और तीनों में दिखाई देती है — और अब पैनल की हर लिखने वाली कार्रवाई के लिए एक कमांड है, इसलिए आपकी स्क्रिप्ट और आपके अपने AI एजेंट वह काम कर सकते हैं जो आपकी टीम स्क्रीन पर करती है। भुगतान, कानूनी सहमति और खाता बंद करना जानबूझकर ब्राउज़र में ही रखे गए हैं। यह पृष्ठ एक कॉन्ट्रैक्ट है। नीचे दी गई कमांड तालिका हाथ से नहीं लिखी गई है; यह हर अनुरोध पर लाइव कमांड रजिस्ट्री से जनरेट होती है।

Logistivo CLI क्या है?

Logistivo CLI (lg) एक कमांड लाइन क्लाइंट है जो आपके Logistivo खाते का काम — लोड और ट्रिप, डिमांड (माल ढुलाई अनुरोध), बोलियाँ और टेंडर, फ़्लीट और ड्राइवर, दस्तावेज़, संपर्क और चालू खाते, इनवॉइस और लेखांकन, गोदाम और स्टॉक, टीम सदस्य और सीमा शुल्क टैरिफ़ — टर्मिनल, स्क्रिप्ट या आपके अपने AI एजेंट से चलाता है। कमांड क्लाइंट में पहले से गढ़ी हुई नहीं होतीं: क्लाइंट सर्वर से कमांड कैटलॉग खींचता है और उसी से अपना रूप बनाता है। यही कमांड बिना कुछ इंस्टॉल किए HTTP पर भी बुलाई जा सकती हैं — ERP और CRM इंटीग्रेशन यही रास्ता अपनाते हैं — और उस MCP चैनल के ज़रिए भी, जिससे बाहरी AI सहायक जुड़ते हैं।

आज क्या लाइव है, और क्या आने वाला है

यह खंड जानबूझकर पृष्ठ के शीर्ष पर रखा गया है। किसी इंटीग्रेशन दस्तावेज़ की सबसे महँगी गलती यह है कि वह किसी ऐसे एंडपॉइंट का वर्णन करे जो अभी खुला नहीं है, मानो वह खुल चुका हो: इंटीग्रेटर कोड लिखता है, एंडपॉइंट 404 लौटाता है, और भरोसा फिर वापस नहीं आता।

क्योंकि कॉन्ट्रैक्ट स्थिर है, आज आप जो इंटीग्रेशन कोड लिखते हैं वह शेष हिस्सों के खुलने पर भी काम करता रहता है। जिन फ़ील्ड को आप नहीं जानते, उन्हें अनदेखा करना अनिवार्य है; यही नियम हमें बिना कुछ तोड़े नई चीज़ें जोड़ने देता है।

इसे क्या अलग बनाता है: क्लाइंट कोई कमांड नहीं जानता, वह उन्हें रचता है

यही वह एक निर्णय है जो इस पृष्ठ के बाकी हिस्से को सार्थक बनाता है। किसी सामान्य CLI में कमांड क्लाइंट के भीतर रहती हैं; Logistivo में वे सर्वर पर रहती हैं।

पारंपरिक व्यवस्था में, जब सर्वर को कोई नई क्षमता मिलती है, तो क्लाइंट की नई रिलीज़ चाहिए होती है और उपयोगकर्ता को उसे इंस्टॉल करना पड़ता है। इस बीच दोनों पक्ष अलग-अलग बातें जानते हैं — और इंटीग्रेशन में यही सबसे चुपचाप होने वाली विफलता है: स्क्रिप्ट चलती है, एग्ज़िट कोड 0 होता है, और कमांड बस वह वर्णन नहीं करती जो सर्वर कर सकता है।

Logistivo में किसी कमांड की परिभाषा एक ही रिकॉर्ड है: उसका नाम, वह क्या करती है, उसके JSON Schema पैरामीटर, कौन-सी भूमिकाएँ उसे देख सकती हैं, क्या उसे पुष्टि चाहिए और क्या उसका प्रभाव पलटा जा सकता है। जब lg शुरू होता है, तो वह यह कैटलॉग खींचता है और उसी से अपना सहायता पाठ, अपने फ़्लैग और अपना इनपुट वैलिडेशन जनरेट करता है। जिस क्षण सर्वर पर कोई कमांड जोड़ी जाती है, lg उसे जान लेता है — बिना किसी क्लाइंट अपडेट के।

यही कैटलॉग डैशबोर्ड के AI सहायक को और उस चैनल को भी चलाता है जिससे बाहरी AI सहायक जुड़ते हैं। कोई क्षमता एक बार लिखी जाती है और तीन जगह दिखाई देती है — और तीनों एक ही भूमिका गेट, एक ही पुष्टि गेट और एक ही ऑडिट लेजर से होकर गुज़रती हैं। CLI कमांड की कोई अलग सूची नहीं है; यदि होती, तो छह महीनों के भीतर तीनों सतहें चुपचाप एक-दूसरे से अलग हो जातीं।

नामकरण नियम — कमांड नाम कैसे बढ़ते हैं

कैटलॉग बढ़ेगा। नई कमांड के नाम मनमाने ढंग से नहीं रखे जाते; छह नियम लागू होते हैं। हम उन्हें यहाँ प्रकाशित करते हैं क्योंकि यही वे नाम हैं जिन्हें आपका इंटीग्रेशन वर्षों तक लिखेगा, और उनकी पूर्वानुमेयता आपके लिए मूल्यवान है।

कवरेज: पैनल का सब कुछ, एक कमांड से

कई टीमें Logistivo को अपने AI एजेंट या ऑटोमेशन हार्नेस से जोड़ती हैं, और एजेंट तभी उपयोगी है जब वह काम पूरा कर सके। इसलिए नियम सरल है: ऑफ़िस उपयोगकर्ता पैनल में जो कुछ भी बदल सकता है, उसे एक कमांड भी बदल सकती है — उसी भूमिका गेट, उसी पुष्टि गेट और उसी ऑडिट लेजर के पीछे।

यह मापा गया है, केवल दावा नहीं किया गया। पैनल के पीछे का हर लिखने वाला एंडपॉइंट कमांड रजिस्ट्री से मिलाकर जाँचा जाता है, और कोई एंडपॉइंट तभी कवर माना जाता है जब कोई कमांड उसे अपने HTTP प्रतिबिंब के रूप में घोषित करे या वही साझा सर्विस बुलाए। दायरे में आने वाले लिखने वाले एंडपॉइंट में से 100% कवर हैं और कोई भी अप्रमाणित नहीं है। बाहर छोड़ा गया हर एंडपॉइंट एक लिखित कारण रखता है — पहचान और भुगतान के चरण, इंटीग्रेशन कंट्रोल प्लेन, ड्राइवर ऐप के अपने एंडपॉइंट, क्लाइंट टेलीमेट्री, बिना किसी कॉलर वाली मृत प्रतियाँ — और जो किसी इंटीग्रेटर के लिए मायने रखते हैं, वे नीचे सूचीबद्ध हैं।

फ़ाइल लेने वाली कमांड भी इसी नियम के अंतर्गत आती हैं: तालिका में 33 कमांड कोई दस्तावेज़ या फ़ोटो लेती हैं, और वे सभी lg से, HTTP पर और MCP पर काम करती हैं ("फ़ाइलें लेने वाली कमांड" देखें)।

प्रबंधन का काम भी कवर है, एक मज़बूत कुंजी के पीछे: तालिका में 62 कमांड — टीम सदस्य और भूमिकाएँ, कंपनी सेटिंग्स, बैंक खाते, सहेजे गए कार्ड, इंटीग्रेशन कुंजियाँ — को manager-स्तर की इंटीग्रेशन कुंजी चाहिए। employee-स्तर की कुंजी, जो डिफ़ॉल्ट है, रोज़मर्रा का संचालन चलाती है और इन कमांड पर INSUFFICIENT_KEY_LEVEL के साथ अस्वीकार कर दी जाती है।

एफ़िलिएट (रेफ़रल पार्टनर) खातों का अपना अलग कैटलॉग है: 20 डोमेन में 55 कमांड — रेफ़रल, लीड, CRM नोट और कार्य, सेल्स डेक, कमाई और भुगतान, साथ में वे खाता और टीम कमांड जो हर भूमिका के पास होती हैं। केवल एफ़िलिएट वाली कमांड नीचे की सार्वजनिक तालिका में नहीं हैं, जो पैनल की तीन भूमिकाओं को सूचीबद्ध करती है; एफ़िलिएट खाता उन्हें GET /api/common/commands में और lg commands में देखता है। जो कंपनी एफ़िलिएट होने के साथ-साथ शिपर, कैरियर या कस्टम्स ब्रोकर भी है, वह दोनों सेट देखती है।

एजेंट को lg users get (API नाम get_current_user) से शुरुआत करनी चाहिए: यह भूमिका, उपयोग में ली जा रही कुंजी का एक्सेस स्तर, प्रभावी अनुमतियाँ, और यह लौटाता है कि क्या कोई लंबित कानूनी स्वीकृति या असत्यापित फ़ोन नंबर इस समय लिखने को रोक रहा है — ताकि एजेंट अस्वीकृति इकट्ठा करने के बजाय उसका पहले से अनुमान लगा सके।

कवरेज एक रिपोर्ट से मापा जाता है जो कमांड रजिस्ट्री की तुलना पैनल के लिखने वाले एंडपॉइंट से करती है; बिना कमांड के जोड़ा गया पैनल एंडपॉइंट उसमें अप्रमाणित के रूप में दिखाई देता है। यदि आपको कोई ऐसी पैनल कार्रवाई मिलती है जिस तक आप किसी कमांड से नहीं पहुँच सकते, तो सपोर्ट को इसकी सूचना दें।

इंस्टॉलेशन और पहचान

lg एक ही फ़ाइल वाली, बिना किसी निर्भरता (dependency) वाली Node स्क्रिप्ट है (Node 18+), जो npm पर @lgstv/lg के नाम से प्रकाशित है। पैकेज दो एक जैसी कमांड इंस्टॉल करता है, lg और logistivo — यदि आपकी मशीन पर lg पहले से किसी alias के रूप में मौजूद है, तो logistivo का उपयोग करें। क्योंकि यह एक ही फ़ाइल है, lg.mjs को किसी ग्राहक के ERP सर्वर पर कॉपी कर देना भी काम करता है। ERP/CRM इंटीग्रेशन बनाने के लिए आपको क्लाइंट की आवश्यकता नहीं है — वही कमांड HTTP पर उपलब्ध हैं।

1. इंस्टॉल करें — आपको केवल Node 18 या उससे नया संस्करण चाहिए; कोई अन्य निर्भरता नहीं है। इसे ग्लोबल रूप से इंस्टॉल करें या npx के ज़रिए बिना इंस्टॉल किए चलाएँ।

2. अनुमोदन कोड से साइन इन करें — lg login एक छोटा अनुमोदन कोड दिखाता है और आपके ब्राउज़र में logistivo.com/connect खोलता है; SSH पर, CI में या --no-browser के साथ यह केवल पता प्रिंट करता है, जिसे आप किसी भी डिवाइस पर, अपने फ़ोन पर भी, खोल सकते हैं। वहाँ हमेशा की तरह साइन इन करें, जाँचें कि पेज पर दिखा कोड वही है जो आपके टर्मिनल में है, केवल पढ़ने की या पढ़ने और कार्रवाई करने की पहुँच चुनें और अनुमोदित करें। टर्मिनल में कुछ भी गोपनीय टाइप नहीं किया जाता: न पासवर्ड, न कुंजी, न वन-टाइम कोड। इसके बाद सत्र उस कंप्यूटर पर साइन इन बना रहता है — टर्मिनल बंद करने से आप साइन आउट नहीं होते, और lg एक्सेस टोकन की अवधि समाप्त होने से पहले उसे स्वयं नवीनीकृत कर देता है। lg logout सर्वर पर भी सत्र समाप्त करता है, और आप इसे पैनल में Settings › Integration keys › AI and CLI connections के अंतर्गत हटा भी सकते हैं। lg login --password (ईमेल और पासवर्ड) एक वैकल्पिक (fallback) तरीके के रूप में उपलब्ध रहता है। इसके लिए lg 0.11 या उसके बाद का संस्करण आवश्यक है।

3. सर्वर और CI के लिए: अनुमोदन कोड नहीं, कुंजी — सर्वर या CI जॉब में ब्राउज़र में कोड अनुमोदित करने वाला कोई नहीं होता। पैनल में (Settings › Integration keys) या lg keys create से एक कुंजी जारी करें — चाहें तो किसी समर्पित, सीमित-दायरे वाले टीम सदस्य की ओर से — और उसे LOGISTIVO_TOKEN में रखें, या lg login --api-key से सहेजें। जब तक यह वेरिएबल सेट है, कॉन्फ़िग फ़ाइल कभी नहीं पढ़ी जाती। विवरण: "API कुंजी से कनेक्ट करना" खंड।

4. सत्यापित करें और कैटलॉग देखें — lg commands वह हर कमांड सूचीबद्ध करता है जिसे आपकी भूमिका देख सकती है, डोमेन के अनुसार समूहित; lg help उस डोमेन की क्रियाएँ दिखाता है, और lg help किसी एक कमांड की पूरी पैरामीटर सूची, प्रकारों सहित और यह बताते हुए कि कौन-से अनिवार्य हैं, दिखाता है। इनमें से कोई भी पाठ क्लाइंट के भीतर नहीं रहता — सब कुछ कैटलॉग से आता है। याद रखें कि सूची आपकी भूमिका पर निर्भर करती है: किसी डोमेन की क्रियाएँ कैरियर और शिपर के लिए एक जैसी नहीं होतीं (उदाहरण के लिए, loads set-status केवल कैरियर कैटलॉग में है)। यदि कोई क्रिया गायब है, तो इंस्टॉलेशन जाँचने से पहले अपनी भूमिका जाँचें।

कुंजी को कभी भी वर्ज़न कंट्रोल, CI लॉग या चैट विंडो में न रखें। यदि आपने अनुमोदन कोड या इंटीग्रेशन कुंजी से साइन इन किया है, तो lg logout उसे सर्वर पर भी समाप्त कर देता है; पासवर्ड सत्र (lg login --password) में यह केवल स्थानीय (LOCAL) प्रति हटाता है और यह बात स्पष्ट रूप से बताता है। ऑडिट लेजर आपके आर्गुमेंट संग्रहीत करता है, लेकिन जिस भी फ़ील्ड के नाम में token, password, IBAN, card या OTP हो, उसे *** के रूप में छिपा देता है, और उस हर पैरामीटर को भी जिसे कोई कमांड गोपनीय (secret) घोषित करती है।

क्लाइंट की सुविधाएँ

ये सुविधाएँ `lg` क्लाइंट के रोज़मर्रा के उपयोग को आसान बनाती हैं। इनमें से कोई भी HTTP कॉन्ट्रैक्ट को नहीं बदलती — यदि आप सीधे HTTP पर इंटीग्रेट करते हैं, तो इस खंड को छोड़ दें।

API कुंजी से कनेक्ट करना

कोई ERP, CRM, स्क्रिप्ट या AI एजेंट पैनल में या lg keys create से जारी इंटीग्रेशन कुंजी के साथ Logistivo से जुड़ता है। कुंजी किसी वास्तविक टीम सदस्य की ओर से काम करती है: उस व्यक्ति की भूमिका कमांड सूची तय करती है, कुंजी का एक्सेस स्तर तय करता है कि काम कितना भारी हो सकता है, और जब वह व्यक्ति टीम छोड़ता है तो कुंजी भी उसके साथ समाप्त हो जाती है। कोई कृत्रिम "सर्विस खाता" नहीं है और कभी नहीं होगा — मल्टी-टेनेंट अलगाव उपयोगकर्ता से बँधा है, और बिना मालिक का ब्रिज वही होता है जो वर्षों तक चुपचाप लिखता रहता है।

1. पैनल में कुंजी जारी करें — Settings › Integration keys › New key। इसे एक नाम दें ("ERP रात का सिंक"), स्कोप और एक्सेस स्तर चुनें, और चाहें तो जीवनकाल छोटा करें। कुंजी केवल एक बार, केवल उसी स्क्रीन पर दिखाई जाती है; सर्वर इसे संग्रहीत नहीं करता। यदि यह खो जाए, तो Rotate एक नई कुंजी जारी करता है — पुरानी तुरंत अमान्य हो जाती है।

2. टर्मिनल से कनेक्ट करें — lg login --api-key कुंजी को सत्यापित करता है, पहचान और स्कोप प्रिंट करता है, और कमांड कैटलॉग डाउनलोड करता है। lg whoami सर्वर से पूछता है कि आप किस उपयोगकर्ता, कंपनी, भूमिका और स्कोप के रूप में चल रहे हैं। lg logout सर्वर पर भी कुंजी रद्द कर देता है, ठीक वैसे ही जैसे वह वहाँ अनुमोदन कोड वाले सत्र को समाप्त करता है (केवल पासवर्ड-सत्र वाला lg logout ऐसा नहीं कर सकता)।

3. या सादा HTTP — कुंजी एक एक्सेस टोकन है जो Authorization: Bearer हेडर में भेजा जाता है और तीनों कमांड एंडपॉइंट पर सीधे काम करता है। सर्वर पर या CI में इसे LOGISTIVO_TOKEN में रखें; जब तक वह वेरिएबल सेट है, कॉन्फ़िग फ़ाइल कभी नहीं पढ़ी जाती।

4. या कुंजियाँ टर्मिनल से प्रबंधित करें: lg keys — lg keys पैनल स्क्रीन का टर्मिनल वाला जुड़वाँ है: वही एंडपॉइंट, वही गेट (टीम-प्रबंधन अनुमति, और कुंजी से बुलाने पर manager-स्तर की कुंजी)। create, rotate और transfer एक बार नया टोकन लौटाते हैं: --save-profile=NAME के साथ यह सीधे एक स्थानीय प्रोफ़ाइल में चला जाता है और कभी प्रिंट नहीं होता; अन्यथा lg इसे एक बार प्रिंट करता है। --json मोड में टोकन केवल तभी शामिल होता है जब आप --show-secret जोड़ते हैं, और इनमें से किसी भी फ़्लैग के बिना --json कॉल अनुरोध भेजे जाने से पहले ही अस्वीकार कर दी जाती है, ताकि टोकन चुपचाप किसी स्क्रिप्ट के आउटपुट में न पहुँच जाए। rotate, transfer और revoke पुष्टि माँगते हैं (--yes); कुंजी को उसके सटीक नाम या उसके uuid से संबोधित किया जाता है, कभी अनुमान से नहीं। एक्सेस स्तर रोटेट या ट्रांसफ़र की गई कुंजी पर बिना बदले चला जाता है।

स्कोप पूरी API सतह पर लागू होता है, केवल कमांड कैटलॉग पर नहीं: read-only कुंजी पढ़ने वाले अनुरोध (GET/HEAD/OPTIONS) पास करती है और बाकी हर लिखने वाला अनुरोध 403 forbidden उत्तर देता है। दो जानबूझकर रखे गए अपवाद हैं और दोनों एक बारीक गेट से सुरक्षित हैं: कमांड निष्पादन एंडपॉइंट (निर्णय कमांड के अपने read_only फ़्लैग से आता है, क्योंकि न लिखने वाली कमांड भी POST से बुलाई जाती हैं) और कुंजी का स्वयं को रद्द करना (lg logout, जिसकी अनुमति read-only कुंजी पर भी है)। स्कोप, डोमेन अनुमतियाँ और एक्सेस स्तर तीन स्वतंत्र अक्ष हैं और तीनों पास होने चाहिए: read कुंजी manager स्तर पर भी नहीं लिख सकती, employee write कुंजी टीम प्रबंधित नहीं कर सकती, और loads:write डोमेन अनुमति प्रबंधन का काम नहीं खोलती। कुंजी उस सबसे कम अधिकार वाले सदस्य की ओर से जारी करें जो आपकी ज़रूरतें पूरी करता हो: भूमिका तय करती है कि आप कौन-से रिकॉर्ड देख भी सकते हैं।

पहले दस मिनट: पैनल से आपकी पहली कॉल तक

किसी इंटीग्रेशन के सबसे महँगे मिनट पहले दस होते हैं। नीचे दिए गए चार चरण उस रास्ते को क्रम से बताते हैं; यही क्रम पैनल में एक विज़ार्ड के रूप में मौजूद है (Settings › Integration › Setup wizard), और विज़ार्ड ठीक यहाँ वर्णित एंडपॉइंट को ही बुलाता है। विज़ार्ड तक पहुँच न रखने वाला डेवलपर इस खंड को पढ़कर उसी जगह पहुँचता है।

चारों में से कोई भी चरण "मैंने भेज दिया" पर समाप्त नहीं होता। कुंजी वास्तव में काम करती है या नहीं, इसका उत्तर अनुरोध लेजर देता है; वेबहुक वास्तव में पहुँचता है या नहीं, इसका उत्तर डिलीवरी लेजर देता है। दोनों पैनल में और lg में खुले हैं। जिस सेटअप को कभी मापा नहीं जाता, वह ऐसा सेटअप है जिसके काम करने पर केवल विश्वास किया जाता है।

सैंडबॉक्स: प्रोडक्शन को छुए बिना लिखने का अभ्यास करें

प्रीफ़्लाइट (dry_run) बताता है कि कोई कमांड क्या करेगी; लेकिन आइडेम्पोटेंसी वास्तव में replay करती है या नहीं, वेबहुक वास्तव में डिलीवर होता है या नहीं, त्रुटि शाखाएँ कैसी दिखती हैं और क्रेडिट कहाँ से आता है — यह केवल एक वास्तविक लेखन में ही देखा जा सकता है। सैंडबॉक्स इसी के लिए है: एक अलग टेनेंट जो आपकी कंपनी का प्रतिबिंब है — वही कोड, वही कमांड कैटलॉग — और कभी आपके लाइव लेजर को नहीं छूता।

सैंडबॉक्स कोई अनुरोध फ़्लैग नहीं, बल्कि एक टेनेंट है। आपकी कंपनी के लिए खोली गई एक अलग Logistivo कंपनी: उसका अपना उपयोगकर्ता, अपना पैकेज, अपना क्रेडिट लेजर, अपने वेबहुक सब्सक्रिप्शन। वातावरण कुंजी की कंपनी से निकाला जाता है और कॉल करने वाला उसे नहीं भेज सकता, इसलिए यदि आप गलत प्रोफ़ाइल भी चुन लें, तो अनुरोध सर्वर की ओर 403 ENVIRONMENT_MISMATCH के साथ रुक जाता है। "मुझे लगा मैं सैंडबॉक्स में लिख रहा था और प्रोडक्शन में लिख दिया" — यह संरचनात्मक रूप से असंभव है।

सतह एक जैसी है — मापी हुई: सैंडबॉक्स कुंजी जो कैटलॉग पाती है, वह वही है जो आपकी लाइव कुंजी पाती है (शिपर कुंजी पर, दोनों ओर 448 कमांड)। जो ब्रिज सैंडबॉक्स में काम करता है, वह प्रोडक्शन में काम करता है; आपको कुछ भी दो बार नहीं सीखना पड़ता।

सैंडबॉक्स खाली नहीं खुलता: इसमें जनरेट किया गया (कॉपी नहीं किया गया) प्रारंभिक डेटा होता है — संपर्क, दोनों दिशाओं के लोड, और डिमांड। नाम खुले तौर पर काल्पनिक हैं और ई-मेल पते @sandbox.invalid डोमेन में हैं; किसी भी वास्तविक टेनेंट की पंक्ति कभी पढ़ी, क्लोन या टेम्पलेट के रूप में उपयोग नहीं की जाती।

जानबूझकर कोई रीसेट बटन नहीं है, और कोई भी रिकॉर्ड, फ़ाइल या दस्तावेज़ कभी हटाया नहीं जाता। यदि आप नई शुरुआत चाहते हैं, तो नवीनीकरण एक नया जनरेशन खोलता है और पुराना सेवानिवृत्त होकर बना रहता है। कुछ सौ जमा हुई अभ्यास पंक्तियों की लागत, गलत टेनेंट से जुड़ी किसी हटाने वाली प्रक्रिया की तुलना में कुछ भी नहीं है।

कमांड मॉडल

व्याकरण एक ही है और उसमें कोई अपवाद नहीं है। किसी कमांड को कैसे बुलाना है, यह जानने के लिए आपको केवल वही चाहिए जो कैटलॉग उसके बारे में कहता है।

lg loads list --status=in_transport --limit=20 --json

फ़्लैग नाम स्कीमा के पैरामीटर नाम हैं, और lg दोनों वर्तनियाँ स्वीकार करता है: --load_code और --load-code एक ही फ़ील्ड तक पहुँचते हैं (lg help kebab-case रूप दिखाता है)। इसलिए किसी फ़्लैग को देखकर ही आप जान जाते हैं कि वह किस JSON फ़ील्ड में जाता है, और CLI से HTTP पर जाने के लिए नामों का कोई अनुवाद नहीं करना पड़ता। बिना मान के लिखा गया boolean पैरामीटर true होता है (--only_open); इसका उलटा --no-only_open है। जिस आर्गुमेंट का मान डैश से शुरू होता है, उसे --flag=value के रूप में लिखें, अन्यथा कोई भूला हुआ फ़्लैग अगले फ़्लैग को चुपचाप अपने मान के रूप में निगल लेता है। फ़ाइल लेने वाली कमांड पर स्थानीय पथ के आगे @ लगाएँ (--attachment_uuid=@./cmr.pdf) — "फ़ाइलें लेने वाली कमांड" देखें।

वास्तविक उदाहरण

नीचे दी गई हर कमांड आज कैटलॉग में मौजूद है; यहाँ कोई भी नाम या पैरामीटर गढ़ा हुआ नहीं है। आउटपुट संक्षिप्त किए गए हैं। आउटपुट `data.result` स्तर दिखाते हैं; HTTP पर यही ऑब्जेक्ट `{success, data:{…}}` लिफ़ाफ़े (envelope) के भीतर आता है (HTTP कमांड API देखें)।

क्लाइंट के बिना: HTTP कमांड API

lg एक सुविधा है, एकमात्र दरवाज़ा नहीं। कैटलॉग और निष्पादन दोनों तीन HTTP एंडपॉइंट से होकर जाते हैं (फ़ाइलों के लिए एक चौथा, अपलोड एंडपॉइंट है — "फ़ाइलें लेने वाली कमांड" देखें); ERP या CRM इंटीग्रेशन सीधे यहीं जुड़ता है। पहचान एक व्यक्तिगत एक्सेस टोकन है जो Authorization: Bearer में भेजा जाता है। हर एक प्रतिक्रिया एक ही लिफ़ाफ़े (envelope) में आती है: `{ "success": bool, "data": { … }, "code": "…", "message": { … } }`। पूरा कॉन्ट्रैक्ट `data` के भीतर रहता है — `contract_version`, `command`, `status` और, कमांड के आउटपुट के रूप में, `result`; विफलता पर `error_code`, `error_key` और `error`। जगह बचाने के लिए इस पृष्ठ के प्रतिक्रिया उदाहरण लिफ़ाफ़े के बजाय `data` ऑब्जेक्ट दिखाते हैं; अपने कोड में `data` को खोलना (unwrap करना) न भूलें। `lg --json` भी पूरा का पूरा लिफ़ाफ़ा प्रिंट करता है, इसीलिए jq पथ `.data.result…` से शुरू होते हैं। एकमात्र अपवाद `/api/public/status` है: वह एंडपॉइंट बिना लिफ़ाफ़े का है ताकि वॉचडॉग उसे पार्स किए बिना अलर्ट कर सकें।

पुष्टि को 200 + ok:false के साथ माँगना वर्जित है और ऐसा कभी नहीं होगा। कारण सरल है: क्लाइंट 200 को सफलता मानते हैं, इसलिए 200 के रूप में लौटाया गया पुष्टि अनुरोध प्रवाह को चुपचाप खत्म कर देता और किसी को पता भी नहीं चलता। पुष्टि हमेशा 409 होती है।

फ़ाइलें लेने वाली कमांड

तालिका में 33 कमांड कोई दस्तावेज़ या फ़ोटो लेती हैं: किसी लोड के साथ CMR जोड़ना, इनवॉइस से HS कोड पढ़ना, वाहन के पंजीकरण दस्तावेज़ से वाहन बनाना, फ़ोटो से पैलेट का अनुमान लगाना, कंपनी का कोई दस्तावेज़ अपलोड करना, इनवॉइस का पैकिंग लिस्ट से मिलान करना। ब्राउज़र में आप फ़ाइल को किसी फ़ॉर्म में डाल देते हैं; बाकी हर जगह इसमें दो चरण लगते हैं — फ़ाइल अपलोड करें, फिर उसकी id कमांड को दें।

कोई पैरामीटर तब फ़ाइल लेता है जब उसका नाम attachment_uuid या attachment_uuids पर समाप्त होता है — सूची के भीतर photos[].attachment_uuid, चेक पर front_attachment_uuid। आपको यह याद रखने की ज़रूरत नहीं है: हर कैटलॉग पंक्ति सटीक पथों के साथ file_params रखती है, स्कीमा उन फ़ील्ड को चिह्नित करता है (format: uuid, x-logistivo-file: true), और कैटलॉग प्रतिक्रिया एक attachments ब्लॉक रखती है जिसमें अपलोड पता, स्वीकृत प्रकार, आकार सीमाएँ और जीवनकाल (time to live) होता है। lg help भी इन्हें दिखाता है।

अपलोड करना एक लेखन है, इसलिए read स्कोप वाली कुंजी अपलोड नहीं कर सकती; write स्कोप वाली कोई भी कुंजी, किसी भी एक्सेस स्तर पर, कर सकती है। अपलोड उपयोगकर्ता के होते हैं, कुंजी के नहीं: एक ही उपयोगकर्ता की दो कुंजियाँ वही अपलोड देखती हैं, और कोई भी किसी दूसरे के अपलोड का उपयोग नहीं कर सकता। जो id अज्ञात, समाप्त या आपकी नहीं है, वह बस नहीं मिलती, और कारण नहीं बताया जाता।

डैशबोर्ड चैट के अटैचमेंट और कमांड अपलोड अलग-अलग स्थान हैं: सहायक चैट में जोड़ी गई फ़ाइल को id से किसी कमांड को नहीं दिया जा सकता, और कमांड अपलोड कभी किसी चैट थ्रेड में दिखाई नहीं देता।

अपलोड कोई कमांड नहीं है और अपने आप में उसका कोई व्यावसायिक प्रभाव नहीं होता: जब तक कोई कमांड उस id का उपयोग नहीं करती, आपके डेटा के साथ कुछ नहीं होता। इसीलिए अपलोड करना कभी पुष्टि नहीं माँगता — फ़ाइल का उपभोग करने वाली कमांड ही गेट रखती है।

पुष्टि गेट और अपरिवर्तनीय कमांड

कैटलॉग की हर कमांड दो फ़्लैग रखती है: confirmation_needed (क्या चलने से पहले उसे स्पष्ट स्वीकृति चाहिए) और irreversible (क्या उसका प्रभाव पलटा जा सकता है)। ये अलग-अलग प्रश्न हैं, और दोनों सर्वर पर लागू किए जाते हैं, क्लाइंट की भलमनसाहत पर नहीं छोड़े जाते।

गेट ज़िम्मेदारी के बारे में है, व्यावसायिक नियमों के बारे में नहीं। बोली लगाना माल ढुलाई अनुबंध की ओर पहला कदम है; इनवॉइस जारी करने से एक लेखांकन प्रविष्टि बनती है; स्टॉक की आवाजाही एक लेजर को बदलती है। इनमें से कोई भी ऐसा काम कभी नहीं होना चाहिए जिसे आप गलती से दो बार चला सकें।

गेट प्रभावी (EFFECTIVE) कमांड से पढ़ा जाता है। जब एक कमांड दूसरी को लपेटती है — जैसा चैट का सामान्य एक्ज़ीक्यूटर करता है — तो गेट उस कमांड के फ़्लैग से आता है जो वास्तव में चलेगी, रैपर से नहीं। किसी निश्चित फ़्लैग के साथ दो में से एक विफलता अनिवार्य होती: या तो इनवॉइस कमांड बिना पुष्टि के चल जाती, या हर देश-खोज एक पुष्टि कार्ड खड़ा कर देती।

read_only और बिना गेट (ungated) एक ही चीज़ नहीं हैं। तीन अलग-अलग अवस्थाएँ हैं: invoices preview बिना गेट की है और कुछ नहीं लिखती; loads create गेट वाली है और लिखती है; invoices create बिना गेट की है लेकिन लिखती है — एक ड्राफ़्ट अस्तित्व में आता है। एक ही परीक्षण इसका निर्णय करता है: जब कमांड लौटती है, तो क्या डेटाबेस में कोई पंक्ति बदली है?

कुछ कार्रवाइयाँ इस गेट के पीछे नहीं हैं क्योंकि वे कमांड हैं ही नहीं: पैकेज खरीदना, 3D Secure के साथ कार्ड जोड़ना, कानूनी पाठों को स्वीकृत करना और खाता बंद करना व्यक्ति के अपने ब्राउज़र में होते हैं। इनके लिए lg handoff-links generate एक logistivo.com लिंक लौटाता है — मुफ़्त, कुछ भी न लिखने वाला, कोई गोपनीय मान न रखने वाला — और व्यक्ति वह चरण वहीं पूरा करता है। कोई भी फ़्लैग, चाहे उसे कैसे भी सेट किया जाए, भुगतान या सहमति को API कॉल में नहीं बदलता।

तकनीकी रूप से किसी इंटीग्रेशन के लिए हर कॉल पर गेट को अपने आप पार करना संभव है, लेकिन यह उचित नहीं है। सही तरीका यह है कि गेट को केवल उन कमांड के लिए स्वचालित करें जिन्हें आप पलटने योग्य जानते हैं, और अपरिवर्तनीय कमांड को किसी इंसान की कतार में भेजें।

प्रीफ़्लाइट: देखें कि कोई लिखने वाली कमांड क्या करेगी, उसे चलाए बिना

ERP ब्रिज जोड़ने का सबसे महँगा चरण यह पता लगाना है कि आपकी बॉडी सही है या नहीं, और वह भी कमांड को वास्तव में चलाकर: लाइव लेजर में एक ड्राफ़्ट इनवॉइस, जला हुआ क्रेडिट, हाथ से सफ़ाई। dry_run इसे खत्म करता है — आप अनुरोध में एक फ़ील्ड जोड़ते हैं, कमांड नहीं चलती, और आप पढ़ लेते हैं कि क्या होता।

रजिस्ट्री में आज 519 कमांड हैं; उनमें से 233 केवल पढ़ती हैं और कुछ नहीं लिखतीं। शेष 286 लिखने वाली कमांड में से 251 गेट वाली हैं: confirm के बिना बुलाए जाने पर वे पहले से ही 409 लौटाती हैं और बताती हैं कि वे क्या करेंगी। कमी बाकी 35 में थी — इनवॉइस ड्राफ़्ट, निर्यात-दस्तावेज़ ड्राफ़्ट, लाइन आइटम: ठीक वही शृंखला जिसे कोई ब्रिज सबसे पहले जोड़ता है। उनके लिए बुलाने का मतलब था कर देना।

गेट वाली कमांड पर भी एक दूसरी कमी थी: स्कीमा वैलिडेशन गेट के बाद चलता है। इसलिए किसी गायब आर्गुमेंट वाली कॉल को पहले पुष्टि कार्ड मिलता, उसकी पुष्टि होती, और तभी जाकर सुनाई देता कि "यह फ़ील्ड गायब है"। प्रीफ़्लाइट दोनों प्रश्नों का उत्तर एक ही राउंड ट्रिप में देता है।

और ब्रिज का सबसे आम — और सबसे देर से पकड़ा जाने वाला — बग यह है: आप ऐसा फ़ील्ड भेजते हैं जो स्कीमा में नहीं है (जहाँ recipient_contact_id अपेक्षित है वहाँ customer_id), सर्वर उसे चुपचाप छोड़ देता है, कमांड 200 लौटाती है और रिकॉर्ड गलत जगह पहुँच जाता है। प्रीफ़्लाइट प्रतिक्रिया ऐसे फ़ील्ड को arguments.ignored के अंतर्गत नाम से सूचीबद्ध करती है; कोई त्रुटि संदेश कभी ऐसा नहीं करेगा।

प्रीफ़्लाइट कुछ नहीं लिखता, और यह मापन से पहले संरचना की बात है: प्रीफ़्लाइट का रास्ता कभी कमांड के हैंडलर में प्रवेश नहीं करता, इसलिए यह हर कमांड पर लागू होता है, बाद में जोड़ी गई कमांड पर भी। जारी होते समय इसे मापा भी गया था: उस समय कैटलॉग की हर लिखने वाली कमांड का प्रीफ़्लाइट करते हुए (दो आर्गुमेंट सेट, दो भूमिकाएँ, 178 प्रीफ़्लाइट) जारी हुआ हर SQL स्टेटमेंट रिकॉर्ड किया गया। एक भी INSERT/UPDATE/DELETE नहीं, एक भी कतारबद्ध जॉब नहीं, एक भी ईमेल नहीं; 31 तालिकाओं में पंक्तियों की संख्या और क्रेडिट शेष अपरिवर्तित रहे।

एग्ज़िट कोड वही होता है जो असली कॉल देती — चल जाती तो 0, पुष्टि गेट 4, आइडेम्पोटेंसी टकराव 2, बाकी सब 1 — इसलिए "lg … --dry-run || exit" किसी CI चरण में एक सार्थक गेट है।

आइडेम्पोटेंसी: दोबारा प्रयास करने से डुप्लिकेट क्यों नहीं बनते

ERP आपका त्रुटि संदेश नहीं पढ़ता, आपकी स्क्रीन नहीं देखता, और टाइमआउट के बाद वही अनुरोध फिर से भेज देगा। यह खंड ठीक इसी व्यवहार के लिए है।

idempotency_key वाली कॉल अधिकतम एक बार चलती है। दूसरी कॉल कमांड को फिर से निष्पादित नहीं करती; वह दर्ज परिणाम को replayed स्थिति के साथ लौटाती है। जब नेटवर्क टूटता है, जब कोई अनुरोध टाइमआउट होता है, या जब कोई कतार एक ही जॉब को दो बार उठा लेती है, तो आपको डुप्लिकेट इनवॉइस के बजाय पहला परिणाम मिलता है।

हर लिखने वाली कमांड पर कुंजी का उपयोग करें। कैटलॉग का read_only फ़ील्ड यह अंतर आपको मुफ़्त में देता है: read_only: false वाली हर कमांड को आइडेम्पोटेंसी कुंजी मिलनी चाहिए।

आपकी पुनः प्रयास रणनीति में एक्सपोनेंशियल बैकऑफ़ होना चाहिए और हर प्रयास पर वही कुंजी भेजी जानी चाहिए। हर प्रयास के लिए नई कुंजी जनरेट करना बिल्कुल वैसा ही है जैसे आइडेम्पोटेंसी का उपयोग ही न करना। एक ही कुंजी समानांतर में न भेजें: अधिकतम-एक-बार (at-most-once) की गारंटी क्रमिक पुनः प्रयासों के लिए है, एक-दूसरे से होड़ करते दो अनुरोधों के लिए नहीं।

इंक्रीमेंटल सिंक और पेजिनेशन

ERP/CRM ब्रिज को हर घंटे सब कुछ नहीं, बल्कि केवल वही खींचना चाहिए जो बदला है। हर सूची कमांड — loads list, demands list-own, contacts list, invoices list, teammates list, load-groups list, reservations list, drivers list, tenders list, products search, warehouses search — दो साझा पैरामीटर स्वीकार करती है और एक साझा फ़ील्ड लौटाती है।

offset क्यों नहीं है: लाइव तालिका पर offset खिसकता रहता है। दो पेजों के बीच डाली गई एक पंक्ति आपसे कोई रिकॉर्ड छुड़वा देती है या उसे दो बार गिनवा देती है, और वह भी चुपचाप। कर्सर केवल आगे की ओर चलता है, इसलिए बीच में डाला या अपडेट किया गया रिकॉर्ड सूची के अंत में पहुँचता है: कुछ भी खोता नहीं, कुछ भी डुप्लिकेट नहीं होता।

पूरा प्रारंभिक लोड भी यही तंत्र है: updated_since=1970-01-01T00:00:00Z से शुरू करें और next_cursor का पालन तब तक करें जब तक वह null न हो जाए। कोई अलग “export” एंडपॉइंट नहीं है क्योंकि उसकी कोई ज़रूरत नहीं है।

lg के साथ भी यही: lg loads list --updated_since=2026-09-01T00:00:00Z --limit=100 --json, फिर lg loads list --cursor= --json।

अगले सिंक के लिए updated_since को आपके द्वारा देखे गए सबसे बड़े updated_at पर सेट करें। टाइमस्टैम्प की सटीकता एक सेकंड की है, इसलिए सीमा पर पड़ने वाला रिकॉर्ड दो बार आ सकता है — यह तब तक हानिरहित है जब तक आप अपनी ओर external_ref या code के आधार पर upsert करते हैं। updated_since या cursor के बिना कमांड चैट मोड में चलती है: इंसानों के लिए क्रम, अधिकतम 20 पंक्तियाँ, next_cursor null और truncated यह बताते हुए कि “और भी है”। सिंक के लिए उस मोड का उपयोग न करें।

इस खंड की मशीन-पठनीय त्रुटि कुंजियाँ: INVALID_CURSOR, INVALID_UPDATED_SINCE, DUPLICATE_EXTERNAL_REF, EXTERNAL_REF_TOO_LONG, EXTERNAL_REF_INVALID। ये सभी बॉडी में error_code: "failed" और result.error_key के साथ HTTP 422 उत्तर देती हैं। शाखा कुंजी के आधार पर बनाएँ, पाठ के आधार पर कभी नहीं।

आपकी अपनी कुंजी: external_ref

हमारी ऑटो-इंक्रीमेंट id (invoice_id, contact_id) को अपने ERP में व्यावसायिक कुंजी न बनाएँ; वे अपारदर्शी हैं और आपकी कंपनी के लिए निजी हैं। लोड, डिमांड, संपर्क, इनवॉइस, उत्पाद और गोदाम इसके बजाय आपकी कुंजी रखते हैं।

आउटगोइंग वेबहुक: कुछ होने पर हम आपको POST करते हैं

यहाँ तक सब कुछ पुल (pull) था: आप पूछते हैं, हम उत्तर देते हैं। किसी ERP ब्रिज को यह जानने के लिए हर मिनट पूछना पड़ता था कि किसी लोड की स्थिति बदली, कोई इनवॉइस जारी हुआ या कोई बोली आई। अब और नहीं: एक https पता पंजीकृत करें, उन इवेंट को चुनें जिनकी आपको परवाह है, और उनके होते ही एक हस्ताक्षरित POST पहुँचता है।

पुश को पुल के साथ-साथ जोड़ा गया, उसकी जगह नहीं। इंक्रीमेंटल सिंक (updated_since + cursor) अछूता है और अब भी सही उपकरण है: पहला पूरा लोड, इतिहास का बैकफ़िल और "क्या मुझसे कुछ छूट गया" का उत्तर — सब वहीं रहते हैं। वेबहुक विलंब को मिनटों से घटाकर सेकंड कर देते हैं। एक स्वस्थ ब्रिज दोनों का उपयोग करता है — वेबहुक ट्रिगर के रूप में, सिंक सुरक्षा जाल के रूप में।

पेलोड एक संकेत (signal) है, रिकॉर्ड की प्रति नहीं। इसमें पहचानकर्ता होते हैं (id, आपका अपना external_ref, status, समय); विवरण आप अपनी कुंजी से GET के ज़रिए प्राप्त करते हैं, और वह कॉल पहले से ही आपके अपने प्राधिकरण गेट से होकर गुज़रती है। इसलिए जोखिम की सतह पहचानकर्ता स्तर पर ही रहती है। दो फ़ील्ड जानबूझकर अनुपस्थित हैं: बोली लगाने वाली कंपनी की पहचान (ब्लाइंड बोलियाँ पैनल में एक उपनाम के तहत दिखती हैं; पहचान को वेबहुक में डालना उस गोपनीयता को दूसरे चैनल से भेद देता) और आरक्षण के संपर्क विवरण (व्यक्तिगत डेटा को एक अतिरिक्त चैनल से ले जाने की कोई ज़रूरत नहीं)।

इवेंट नाम स्थिर (फ़्रीज़) हैं। यदि किसी नाम का अर्थ बदलता है, तो एक नया नाम खोला जाता है और पुराना नाम एक अप्रचलन (deprecation) विंडो तक चलता रहता है। पेलोड में नया फ़ील्ड जोड़ने से कॉन्ट्रैक्ट संस्करण नहीं बढ़ता — उपभोक्ता को उन फ़ील्ड को अनदेखा करना होगा जिन्हें वह नहीं जानता।

इवेंट कैटलॉग

नीचे दिए गए 13 इवेंट में से हर एक के पीछे एक इवेंट क्लास है जो वास्तव में डिस्पैच होती है। कैटलॉग में "होता तो अच्छा था" वाले नाम नहीं हैं: जिस इवेंट की घोषणा की गई हो लेकिन जो कभी फ़ायर न हो, उसकी प्रतीक्षा इंटीग्रेटर हमेशा करता रहता है, और वह विफलता चुपचाप होती है। यह तालिका भी हाथ से नहीं लिखी गई है — यह हर पेज लोड पर लाइव कैटलॉग से बनती है।

invoice.payment_recorded जानबूझकर अनुपस्थित है: वह इवेंट क्लास कोड में मौजूद है, लेकिन कहीं से भी डिस्पैच नहीं होती। भुगतान इवेंट उसी दिन जोड़ा जाएगा जिस दिन क्लास वास्तव में फ़ायर होगी — उससे पहले नहीं। किसी इवेंट की जल्दी घोषणा करना उसे कभी न जोड़ने से भी बुरा है।

हस्ताक्षर का सत्यापन

हर अनुरोध एक X-Logistivo-Signature हेडर रखता है: t=,v1=। हस्ताक्षरित स्ट्रिंग "." है और एल्गोरिदम HMAC-SHA256 है। v1 उपसर्ग योजना को संस्करण-योग्य बनाए रखता है: यदि कभी दूसरी योजना आती है, तो हेडर t=…,v1=…,v2=… रखेगा और आप वह चुनेंगे जिसे आप जानते हैं।

हम बिना निर्भरता वाले दो संदर्भ रिसीवर प्रकाशित करते हैं, एक Node के लिए और एक सादे PHP के लिए। दोनों ऊपर दिए गए चार नियम लागू करते हैं और --selftest के साथ स्वयं का परीक्षण करते हैं: वैध हस्ताक्षर, छेड़छाड़ की गई बॉडी, गलत सीक्रेट, विंडो से बाहर का टाइमस्टैम्प, विकृत हेडर, री-सीरियलाइज़ेशन का जाल और दोनों प्रकार की पुनरावृत्ति (वही डिलीवरी / वही तथ्य)। सत्यापनकर्ता ठीक उसी कोड का समकक्ष है जिसका हम स्वयं उपयोग करते हैं — जो कॉन्ट्रैक्ट हम प्रकाशित करते हैं, उसका उपभोग हम खुद करते हैं।

डिलीवरी, पुनः प्रयास और म्यूट करना

आपका रिसीवर हमेशा चालू नहीं रहेगा। यह रेल इसे मानकर चलती है: अस्थायी विफलता पुनः प्रयास शेड्यूल में जाती है, स्थायी विफलता सब्सक्रिप्शन को म्यूट कर देती है — और म्यूट करने का कारण हमेशा दर्ज किया जाता है।

म्यूट करने का कारण मशीन-पठनीय और स्थिर है (delivery_failures, endpoint_gone, unsafe_target, key_revoked, by_user) और पैनल तथा `lg webhooks list` दोनों में दिखाई देता है। बिना कारण के म्यूट करने पर "कुछ भी क्यों नहीं आ रहा" का कोई उत्तर नहीं रहता। फिर से सक्षम करने पर काउंटर और मुहर (stamp) रीसेट हो जाते हैं।

पता आप लिखते हैं; अनुरोध हमारा सर्वर करता है। बिना गेट के, कोई टेनेंट जो क्लाउड मेटाडेटा पता डाल दे, हमसे हमारे अपने नेटवर्क के भीतर से अनुरोध करवा सकता था। इसलिए पते की जाँच पंजीकरण के समय भी होती है और हर एक डिलीवरी पर भी:

स्वास्थ्य और स्थिति: किसी को भी आपसे पहले एक चुप पड़े ब्रिज का पता नहीं चलना चाहिए

कोई इंटीग्रेशन ब्रिज शायद ही कभी शोर मचाकर बंद होता है। आमतौर पर वह देर रात चुपचाप शांत हो जाता है: कोई टोकन समाप्त हो जाता है, जिस व्यक्ति की ओर से कुंजी चलती है वह टीम छोड़ देता है, कोई स्कोप सीमित कर दिया जाता है, या प्राप्त करने वाला एंडपॉइंट 403 लौटाने लगता है। सबसे पहले ध्यान देने वाला लगभग हमेशा ग्राहक होता है। lg status इसी क्रम को उलटने के लिए है।

एक ही कमांड दो प्रश्नों का उत्तर एक साथ देती है, क्योंकि आउटेज के दौरान दोनों एक ही क्षण पूछे जाते हैं: क्या प्लेटफ़ॉर्म चालू है, और क्या मेरा ब्रिज स्वस्थ है। प्लेटफ़ॉर्म वाली पंक्ति बिना टोकन के काम करती है — विफलता के दौरान टोकन स्वयं पहला संदिग्ध होता है, और स्थिति के प्रश्न को उससे बाँधने पर ठीक उसी समय आपको कोई उत्तर नहीं मिलता जब आपको उसकी ज़रूरत होती है।

स्वास्थ्य सारांश कोई नया लेजर नहीं रखता; यह तीन मौजूदा स्रोतों को एक ही वाक्य में समेटता है: दैनिक उपयोग काउंटर (आपने कितनी कॉल कीं और कितनी विफल हुईं), अनुरोध लेजर (कौन-सा अनुरोध, कब, और क्यों अस्वीकार हुआ) और आउटगोइंग वेबहुक डिलीवरी लेजर (क्या इवेंट रिसीवर तक पहुँचा)। त्रुटि दर हमेशा दैनिक काउंटर से पढ़ी जाती है; विवरण वाले लेजर की एक सीमा है और सीमा पूरी होने पर वह यह बात साफ़-साफ़ बताता है।

यही सारांश पैनल में भी दिखाई देता है: Settings › Integration › Keys के अंतर्गत हर पंक्ति एक बैज रखती है और उसके नीचे कारण। सीमाएँ (थ्रेशोल्ड) क्लाइंट की ओर गणना नहीं की जातीं; सर्वर ने जो भी स्तर तय किया, वही पैनल और lg status दोनों दिखाते हैं, इसलिए दोनों स्क्रीन एक ही कुंजी के बारे में कभी अलग-अलग बातें नहीं कह सकतीं।

आपके वॉचडॉग को किसी टोकन की ज़रूरत नहीं है। एंडपॉइंट केवल स्थिति वाले शब्द लौटाता है; इसमें कोई संस्करण, होस्ट नाम, कतार का नाम, जॉब की संख्या, त्रुटि पाठ या ग्राहक डेटा नहीं होता — और हो भी नहीं सकता।

स्वास्थ्य सारांश प्रति अनुरोध क्वेरी की एक स्थिर संख्या से तैयार होता है; क्वेरी की संख्या कुंजियों की संख्या के साथ नहीं बढ़ती। विवरण के लिए, उस कुंजी के हाल के अनुरोध lg logs से और आउटगोइंग ब्रिज को lg webhooks list से पढ़ें।

त्रुटियाँ और एग्ज़िट कोड

मशीन जिस पर शाखा बनाती है, वह एक स्थिर स्ट्रिंग है। error फ़ील्ड का पाठ इंसानों के लिए है, स्थानीयकृत है, और बिना सूचना के बदलता है — संदेश के पाठ पर शाखा बनाने वाला इंटीग्रेशन समर्थित नहीं है, और उसका टूटना कोई बग नहीं है।

दो वर्गीकरण, दो फ़ील्ड। error_code ट्रांसपोर्ट स्तर है (ऊपर की तालिका) और इसी पर आप सबसे पहले शाखा बनाते हैं। error_key, failed के भीतर की स्थिर व्यावसायिक-नियम कुंजी है — INSUFFICIENT_CREDITS, NOT_FOUND, DUPLICATE_CONTACT, INSUFFICIENT_STOCK — जो कैटलॉग में (error_keys) और नीचे एक शब्दकोश के रूप में प्रकाशित है। जो कमांड अभी कोई कुंजी नहीं देती, वह error_key: null लौटाती है; शब्दकोश में न मिलने वाली कुंजी को सामान्य विफलता मानें।

स्थिरता का वादा

किसी इंटीग्रेशन कॉन्ट्रैक्ट में सबसे महँगा प्रश्न है “क्या आज मैं जो कोड लिखता हूँ, वह कल भी चलेगा?” एक संख्या इसका उत्तर देती है: कैटलॉग में contract_version, और हर प्रतिक्रिया पर X-Contract-Version हेडर। यह ठीक एक प्रश्न का उत्तर देती है — क्या पहले लिखा गया कोड बिना बदलाव के अब भी चलता है? यदि संख्या नहीं बढ़ी, तो हाँ। यदि बढ़ी, तो नहीं: जिस चीज़ पर आप निर्भर थे, उसे हटाया या सीमित किया गया।

क्योंकि घोषणा कुछ भी नहीं हटाती: आपका मौजूदा कोड अगले दिन भी ठीक पहले की तरह चलता है। घोषणा पर संस्करण बढ़ाने से एक बदलाव के लिए दो संकेत निकलते और आपको पहले संकेत को अनदेखा करने की आदत पड़ जाती — जिससे वह संकेत कमज़ोर होता जो वास्तव में मायने रखता है। घोषणा पहले से ही उस कॉल के साथ आती है जो आप कर रहे हैं: कैटलॉग पंक्ति पर deprecated_at और replaced_by, उस कमांड की प्रतिक्रिया पर X-Deprecated हेडर और एक deprecated ब्लॉक, और यदि आप lg उपयोग करते हैं तो stderr पर एक-पंक्ति की चेतावनी। कुछ हटने वाला है, यह जानने के लिए आपको कुछ भी करने की ज़रूरत नहीं; यह पहले से आपके लॉग में है।

घोषणा और हटाने के बीच कम से कम दो कैलेंडर तिमाहियाँ बीतती हैं। पूरी विंडो के दौरान पुरानी कमांड उत्तर देती रहती है, और हर कॉल पर चेतावनी देती है। जब कोई CLI नाम सेवानिवृत्त होता है, तो उसका उत्तराधिकारी उस नाम को alias के रूप में अपना लेता है: विंडो के दौरान पुराना नाम पुरानी कमांड तक पहुँचता है, और जिस दिन उसे हटाया जाता है, वही कॉल नई कमांड पर पहुँचती है — बिना आपके कोई क्लाइंट रिलीज़ भेजे।

preview_invoice → get_invoice (3 सितंबर 2026 को घोषित)। get_invoice वही preview ब्लॉक लौटाती है और साथ में लाइन आइटम, कर का ब्योरा, दर्ज भुगतान, शेष राशि और आपकी अपनी ERP कुंजी (external_ref) से संबोधन जोड़ती है। preview_invoice काम करती रहती है, और lg invoices preview भी — दोनों चेतावनी देती हैं।

कमांड पहचान तालिका

नीचे दी गई तालिका हाथ से नहीं लिखी गई है: यह पृष्ठ परोसे जाने पर हर बार लाइव कमांड रजिस्ट्री से जनरेट होती है। सर्वर पर जोड़ी गई कमांड यहाँ अपने आप दिखाई देती है। "गेट" कॉलम बताता है कि कोई कमांड पुष्टि माँगती है या नहीं और उसका प्रभाव पलटा जा सकता है या नहीं; "भूमिकाएँ" कॉलम बताता है कि किन खाता प्रकारों को वह अपने कैटलॉग में मिलेगी। बैज उन कमांड को चिह्नित करते हैं जिन्हें manager-स्तर की कुंजी चाहिए, जो कोई फ़ाइल लेती हैं और जो केवल lg से चलती हैं।

API नाम (list_loads) स्थिर है और नहीं बदलेगा; HTTP कॉल में आप यही नाम उपयोग करते हैं। CLI पहचान (loads list) संस्करण नीति के अधीन है: घोषित होने के बाद यह केवल संस्करण वृद्धि और एक माइग्रेशन विंडो के साथ बदलती है, जिसके दौरान कैटलॉग पुरानी जोड़ी को alias के रूप में परोसता है। यहाँ के विवरण हर कमांड के अपने रिकॉर्ड से आते हैं और छोटे किए गए हैं — पूरे पाठ, पैरामीटर प्रकारों और enum मानों के लिए, कैटलॉग एंडपॉइंट पढ़ें या lg help चलाएँ। केवल एफ़िलिएट के लिए बनी कमांड यहाँ सूचीबद्ध नहीं हैं; एफ़िलिएट खाता उन्हें अपने कैटलॉग में देखता है।

ERP और CRM इंटीग्रेशन — पहचान: कोई सर्विस खाता नहीं, बल्कि एक वास्तविक उपयोगकर्ता

ERP या CRM, Logistivo से एक वास्तविक कंपनी उपयोगकर्ता के रूप में जुड़ता है, जिसके पास पैनल से बनाया गया व्यक्तिगत एक्सेस टोकन होता है। कोई कृत्रिम सर्विस खाता — बिना कंपनी, स्कोपिंग से मुक्त, जिसकी कोई ज़िम्मेदारी न ले — कभी नहीं बनाया जाता।

यह आर्किटेक्चर है, पसंद नहीं। मल्टी-टेनेंट अलगाव पूरी तरह उपयोगकर्ता की कंपनी पर टिका है; बिना कंपनी वाली पहचान के लिए अलगाव का दायरा निष्क्रिय हो जाता है, और उस टोकन पर एक गलत क्वेरी ऐसा डेटा पढ़ लेती है जो उसका नहीं है। दूसरा कारण ऑडिट है: लेजर का उपयोगकर्ता कॉलम "इसे किसने चलाया" को एक व्यक्ति से जोड़ता है; सर्विस खाता उस कॉलम को निरर्थक बना देता है और इनवॉइस जारी करने वाले इंटीग्रेशन को बिना मालिक के छोड़ देता है। तीसरा कारण रद्द करना है: यदि टोकन किसी व्यक्ति का है, तो उस व्यक्ति के जाने पर इंटीग्रेशन चुप हो जाता है। बिना मालिक का ब्रिज वही ब्रिज है जो वर्षों तक चुपचाप लिखता रहता है।

ERP और CRM इंटीग्रेशन — संस्करण प्रबंधन और अप्रचलन

कैटलॉग प्रतिक्रिया एक contract_version पूर्णांक रखती है; कमांड पंक्तियाँ since, deprecated_at और replaced_by रखती हैं। कॉन्ट्रैक्ट संस्करण केवल तोड़ने वाले (breaking) बदलावों पर बढ़ता है।

ERP और CRM इंटीग्रेशन — स्थिर पहचानकर्ता: अपने ERP को कभी भी ऑटो-इंक्रीमेंट id कुंजी के रूप में न दें

आंतरिक ऑटो-इंक्रीमेंट id अपारदर्शी और टेनेंट-सीमित हैं: किसी दूसरी कंपनी की वैध id आपको डेटा नहीं, बल्कि "नहीं मिला" लौटाती है। लेकिन अपारदर्शी होना उन्हें व्यावसायिक कुंजी नहीं बनाता। ERP अपने रिकॉर्ड में जो संग्रहीत करता है, वह एक व्यावसायिक कुंजी होनी चाहिए।

ERP और CRM इंटीग्रेशन — पेजिनेशन, फ़िल्टरिंग और इंक्रीमेंटल सिंक

सूची कमांड limit लेती हैं और count लौटाती हैं। रात के सिंक के लिए कॉन्ट्रैक्ट निम्नलिखित के लिए प्रतिबद्ध है; जिस सूची कमांड ने इसे अपना लिया है, वह अपने JSON Schema में cursor और updated_since घोषित करती है, और जब तक ऐसा नहीं होता, उसे एक छोटी विंडो मानें (अधिकतम 20 पंक्तियाँ, कोई कर्सर नहीं)।

ERP और CRM इंटीग्रेशन — रेट लिमिट

लिमिट की कुंजी टोकन है, IP नहीं: ERP एक ही NAT के पीछे से आता है, और IP-आधारित लिमिट पूरी कंपनी को एक उपयोगकर्ता गिन लेती। दो कुंजियों वाले दो इंटीग्रेशन कभी एक-दूसरे का कोटा नहीं खाते — "प्रति कुंजी एक इंटीग्रेशन" का यह दूसरा कारण है।

ERP और CRM इंटीग्रेशन — जो हम नहीं करेंगे

यह अक्सर किसी कॉन्ट्रैक्ट का सबसे उपयोगी हिस्सा होता है: यह जानना कि क्या कभी नहीं आएगा, आपको उसके इर्द-गिर्द डिज़ाइन करने देता है।

मशीन-पठनीय कैटलॉग

यह पृष्ठ लोगों के लिए लिखा गया था। किसी AI सहायक या स्वचालित क्लाइंट के लिए, यही जानकारी एक संरचित, बिना प्रमाणीकरण वाली प्रति के रूप में मौजूद है।

GET /api/public/cli/catalog को किसी प्रमाणीकरण की आवश्यकता नहीं है और यह कमांड की सार्वजनिक पहचान लौटाता है: स्थिर API नाम, CLI की domain/verb पहचान, विवरण, JSON Schema पैरामीटर, read_only, confirmation_needed और irreversible फ़्लैग, credit_cost, और एक्सेस फ़ील्ड key_level, permission, file_params, secret_parameters और cli_only। यह कोई व्यक्तिगत डेटा, कोई टेनेंट डेटा और कोई नमूना रिकॉर्ड नहीं लौटाता — केवल यह कि सतह क्या है।

किसी बाहरी एजेंट के लिए इसके उपयोग का सही तरीका: कैटलॉग पढ़ें, अपने शब्दों में समझाएँ कि कौन-से काम संभव हैं, और जब निष्पादन की ज़रूरत हो, तो उपयोगकर्ता को इसे अपने वातावरण में अपने टोकन से चलाने की ओर निर्देशित करें। एजेंट कभी भी उपयोगकर्ता का टोकन नहीं माँगता, नहीं बनाता और न आगे भेजता है।

साइनअप और माल ढुलाई अनुरोधों के लिए Logistivo को किसी AI सहायक से जोड़ना एक अलग चैनल है, जिसका अपना पृष्ठ है:

मशीन-पठनीय परिभाषा: OpenAPI 3.1 और Postman

ऊपर का कैटलॉग Logistivo का अपना प्रारूप है। यही जानकारी दो उद्योग-मानक प्रारूपों में भी प्रकाशित है जिन्हें आपके टूल पहले से समझते हैं: एक OpenAPI 3.1 परिभाषा और एक Postman कलेक्शन। दोनों में से कोई भी हाथ से नहीं लिखा गया — दोनों हर अनुरोध पर लाइव कमांड रजिस्ट्री से जनरेट होते हैं, इसलिए वे पुराने नहीं पड़ सकते।

परिभाषा ही कैटलॉग है, कोई दूसरी वास्तविकता नहीं। हर कमांड एक POST /api/common/commands/ ऑपरेशन के रूप में दिखाई देती है; बॉडी स्कीमा कमांड का अपना JSON Schema है (बाइट दर बाइट वही जो सहायक देखता है), प्रतिक्रिया स्कीमा साझा लिफ़ाफ़ा है, गेट फ़्लैग (read_only, confirmation_needed, irreversible और क्रेडिट बैज) x-logistivo एक्सटेंशन में हैं, और व्यावसायिक त्रुटि कुंजियाँ x-error-keys के अंतर्गत हैं। सेवानिवृत्त कमांड deprecated: true से चिह्नित होती है और अपनी छह महीने की विंडो के दौरान बुलाई जा सकती है।

कमांड सतह के साथ-साथ, इंटीग्रेशन कॉन्ट्रैक्ट वहन करने वाले REST एंडपॉइंट भी परिभाषा में हैं: इंक्रीमेंटल सिंक (updated_since + cursor + limit) वाले 10 सूची एंडपॉइंट और आपकी अपनी कुंजी (external_ref) स्वीकार करने वाले 7 लिखने वाले एंडपॉइंट। Logistivo की REST सतह इससे कहीं बड़ी है; बाकी को जानबूझकर बाहर रखा गया है। वे पेलोड उत्पाद का अपना कॉन्ट्रैक्ट हैं, और अनुमान से लिखा गया स्कीमा आपके जनरेट किए गए क्लाइंट को पहली ही कॉल पर तोड़ देता — और आप बग अपने कोड में खोजते, हमारे में नहीं।

परिभाषा पूछने वाले की भूमिका के लिए जनरेट होती है: किसी दूसरी भूमिका की कमांड कभी दस्तावेज़ में नहीं आती, क्योंकि परिभाषा एक कॉन्ट्रैक्ट है, शब्दकोश नहीं, और उसके भीतर की हर चीज़ उस टोकन से बुलाई जा सकनी चाहिए। बिना प्रमाणीकरण वाला संस्करण तीनों भूमिकाओं का संघ (union) है, और वहाँ हर ऑपरेशन x-logistivo.roles के अंतर्गत बताता है कि कौन-सी भूमिकाएँ उसे देखती हैं।

हमारी बात पर भरोसा न करें — जाँच लें: npx @redocly/cli lint logistivo-openapi.json शून्य चेतावनियों के साथ पास होता है।

कोड जनरेशन: परिभाषा से एक टाइप्ड क्लाइंट

आपके पास परिभाषा है; अब उससे काम करने वाला कोड जनरेट करें। `lg codegen` OpenAPI दस्तावेज़ पढ़ता है और एक ही फ़ाइल वाला, बिना निर्भरता का क्लाइंट लिखता है — TypeScript (टाइप घोषणाएँ और एक पतला कॉल रैपर) या PHP (PHPDoc array shapes वाली एक क्लाइंट क्लास)। कोई `npm install` नहीं, कोई composer नहीं: TypeScript की ओर `fetch`, PHP की ओर `ext-curl`।

जनरेशन आपकी मशीन पर होता है, हमारे सर्वर पर नहीं। यह पसंद की बात नहीं है: परिभाषा को एक बार अपनी रिपॉज़िटरी में पिन करें (`lg spec --out=...`) और वही कमांड हर बिल्ड पर बिना नेटवर्क और बिना टोकन के चलती है, इसलिए आपका CI कभी हमारे अपटाइम पर निर्भर नहीं होता। और क्योंकि जनरेट किया गया कोड वह कोड है जो आपके ERP में चलता है, उसे किसी API से खींचने के बजाय अपनी रिपॉज़िटरी में रखने का मतलब है कि हर बदलाव `git diff` में दिखाई देता है।

जनरेट किया गया क्लाइंट Logistivo की तीनों रेल को सही ढंग से संभालता है, और कौन-सी रेल कौन-सी है, यह अनुमान से नहीं बल्कि दस्तावेज़ से सीखता है: हर ऑपरेशन `x-logistivo.surface` में अपनी रेल घोषित करता है। कमांड रेल `{success, data:{…}}` लिफ़ाफ़े को खोलती है; REST सिंक सूची लिफ़ाफ़े में नहीं होती और जैसी है वैसी लौटाई जाती है (उसे खोलने से `next_cursor` गिर जाता); REST लेखन एंडपॉइंट की अपनी उत्पाद बॉडी लौटाता है। सामान्य-उद्देश्य वाला जनरेटर यह अंतर नहीं जानता — हमारा जानता है।

टाइप अनुमान पर आधारित नहीं हैं: हर कमांड का आर्गुमेंट इंटरफ़ेस उसी JSON Schema से जनरेट होता है जिसे सहायक देखता है। अनिवार्य अनिवार्य ही रहता है, enum यूनियन टाइप बन जाते हैं, नेस्टेड ऑब्जेक्ट नेस्टेड टाइप बन जाते हैं। व्यवहार में: यदि सर्वर किसी फ़ील्ड को अनिवार्य मानता है, तो उसे भूलने वाली कॉल प्रोडक्शन में 422 के साथ विफल नहीं होती — वह कंपाइल के समय ही विफल हो जाती है।

फ़ाइल में कोई जनरेशन टाइमस्टैम्प नहीं लिखा जाता: समान फ़्लैग के साथ समान परिभाषा एक जैसे बाइट्स बनाती है। इसलिए दोबारा जनरेट करने से `git diff` में कोई शोर नहीं होता, और जो एक चीज़ वास्तव में बदली — कॉन्ट्रैक्ट — वह दिखाई देती रहती है।

ईमानदार दायरा

हम इस खंड को छोटा करने के बजाय बढ़ाना पसंद करेंगे। किसी इंटीग्रेशन कॉन्ट्रैक्ट का मूल्य इस बात में कम है कि वह क्या वादा करता है, और इसमें अधिक है कि वह कितनी स्पष्टता से बताता है कि वह क्या नहीं करता।

अक्सर पूछे जाने वाले प्रश्न

Logistivo CLI का उपयोग किस लिए होता है?

यह आपके Logistivo खाते का काम टर्मिनल, स्क्रिप्ट या आपके अपने AI एजेंट से चलाता है: लोड और ट्रिप, डिमांड, बोलियाँ और टेंडर, फ़्लीट, ड्राइवर और उनके खर्च, दस्तावेज़, संपर्क और चालू खाते, इनवॉइस और लेखांकन, गोदाम और स्टॉक, टीम सदस्य, HS टैरिफ़ और एंटी-डंपिंग शुल्क। पैनल की हर लिखने वाली कार्रवाई के लिए एक कमांड है; भुगतान, कानूनी सहमति और खाता बंद करना जानबूझकर ब्राउज़र में ही रहते हैं। यही कमांड ERP/CRM इंटीग्रेशन के लिए HTTP पर और MCP चैनल के ज़रिए भी बुलाई जा सकती हैं।

Logistivo CLI में कमांड के नाम कैसे रखे जाते हैं?

आकार है: lg --parameter=value — डोमेन एक बहुवचन इकाई है (loads, demands, invoices, export-documents) और क्रिया एक बंद शब्दावली से आती है जो केवल सोच-समझकर लिए गए निर्णय से बढ़ती है (list, get, create, update, search, set-status, generate आदि)। एक इकाई की हर क्रिया एक ही डोमेन में रहती है, और (domain, verb) जोड़ी पूरे कैटलॉग में अद्वितीय है।

मैं CLI में प्रमाणीकरण कैसे करूँ?

इंटरैक्टिव रूप से, lg login एक अनुमोदन कोड दिखाता है, जिसकी पुष्टि आप Logistivo में साइन इन करने के बाद अपने ब्राउज़र में करते हैं — टर्मिनल में कोई पासवर्ड या कुंजी टाइप नहीं की जाती, और सत्र तब तक साइन इन रहता है और स्वयं को नवीनीकृत करता रहता है जब तक आप lg logout नहीं चलाते। lg login --password (ईमेल और पासवर्ड) एक वैकल्पिक (fallback) तरीके के रूप में उपलब्ध रहता है। सर्वर पर और CI में, पैनल में या lg keys create से जारी इंटीग्रेशन कुंजी का उपयोग करें: lg login --api-key उसे एक स्थानीय प्रोफ़ाइल में सहेजता है, या उसे LOGISTIVO_TOKEN एनवायरनमेंट वेरिएबल में रखें। HTTP पर टोकन Authorization: Bearer हेडर में जाता है।

क्या मैं अपने ERP इंटीग्रेशन के लिए एक सर्विस खाता बना सकता हूँ?

नहीं। इंटीग्रेशन पैनल में बनाए गए किसी वास्तविक कंपनी उपयोगकर्ता के टोकन से जुड़ता है। बिना कंपनी वाली कृत्रिम पहचान मल्टी-टेनेंट अलगाव को निष्क्रिय कर देती है, ऑडिट लेजर में "इसे किसने चलाया" कॉलम को निरर्थक बना देती है, और एक ऐसा ब्रिज छोड़ जाती है जो उसके मालिक के जाने पर भी चुप नहीं होता। सही तरीका है एक समर्पित उपयोगकर्ता, जिसकी भूमिका सीमित हो और जिसका एक नामित मालिक हो।

क्या Logistivo में परीक्षण (सैंडबॉक्स) वातावरण है?

हाँ, और यह स्वयं-सेवा है: आपकी कंपनी के लिए एक अलग सैंडबॉक्स टेनेंट खोला जाता है — वही कोड, वही कमांड कैटलॉग, उसका अपना क्रेडिट लेजर। वातावरण कुंजी की कंपनी से निकाला जाता है और अनुरोध के साथ नहीं भेजा जा सकता; गलत प्रोफ़ाइल से की गई कॉल सर्वर की ओर 403 ENVIRONMENT_MISMATCH के साथ रुक जाती है। सैंडबॉक्स में खोली गई डिमांड कभी वास्तविक कैरियरों तक नहीं पहुँचती, सैंडबॉक्स इवेंट कभी आपके लाइव वेबहुक सब्सक्रिप्शन पर डिलीवर नहीं होता, और आपका लाइव शेष नहीं बदलता। एंडपॉइंट: POST /api/common/integration-sandbox (खोलना), POST /api/common/integration-sandbox/keys (कुंजी), GET /api/common/integration-sandbox/go-live (go-live चेकलिस्ट)। lg की ओर, lg --sandbox और lg --live एक बार चलाने के लिए प्रोफ़ाइल चुनने वाले विकल्प हैं।

किसी स्क्रिप्ट में lg --json आउटपुट कैसे पढ़ें?

आउटपुट पूरा HTTP लिफ़ाफ़ा है: { "success": bool, "data": { "contract_version", "command", "status", "result" }, "code", "message" }। व्यावसायिक पेलोड .data.result के नीचे होता है; सूची कमांड पर पंक्तियाँ .data.result. हैं, गिनती .data.result.count है और अगला पेज .data.result.next_cursor है। इसलिए सही jq पथ कुछ ऐसा दिखता है: lg loads list --json | jq -r '.data.result.loads[].load_code'। लिफ़ाफ़े को छोड़ देने वाला पथ त्रुटि नहीं देता, वह चुपचाप null लौटाता है — किसी वॉचडॉग स्क्रिप्ट में यह ऐसा अलार्म बन जाता है जो कभी बजना बंद नहीं करता। एकमात्र अपवाद /api/public/status है, जिसकी बॉडी जानबूझकर बिना लिफ़ाफ़े की है।

यदि मैं एक ही अनुरोध दो बार भेजूँ, तो क्या डुप्लिकेट रिकॉर्ड बनेंगे?

नहीं, यदि आपने idempotency_key भेजी है। उसी कुंजी के साथ दूसरी कॉल कमांड को फिर से नहीं चलाती; वह पहला परिणाम replayed स्थिति के साथ लौटाती है। कुंजी एक UUID होनी चाहिए और सभी पुनः प्रयासों में वही रहनी चाहिए — हर प्रयास के लिए नई कुंजी बनाना आइडेम्पोटेंसी का उपयोग न करने के बराबर है।

--yes क्या करता है?

यह पुष्टि गेट पार करता है। जब किसी गेट वाली कमांड को --yes के बिना बुलाया जाता है, तो कुछ नहीं बदलता: सर्वर एक वाक्य में बताता है कि वह क्या करने वाला है, यह भी बताता है कि वह अपरिवर्तनीय है या नहीं, और रुक जाता है (HTTP 409, CLI एग्ज़िट कोड 4)। कमांड को --yes के साथ दोहराने पर काम हो जाता है।

किसी स्क्रिप्ट में विफल कमांड का पता कैसे लगाऊँ?

एग्ज़िट कोड पढ़ें, संदेश का पाठ कभी नहीं: 0 सफलता, 1 व्यावसायिक नियम द्वारा अस्वीकृति, 2 कमांड या आर्गुमेंट त्रुटि, 3 प्रमाणीकरण या भूमिका त्रुटि, 4 पुष्टि आवश्यक। HTTP पर इनके समकक्ष 200, 422, 404, 403 और 409 हैं, और बॉडी में error_code फ़ील्ड स्थिर है। त्रुटि संदेश स्थानीयकृत है और बिना सूचना के बदलता है।

उपलब्ध कमांड को प्रोग्राम के ज़रिए कैसे खोजूँ?

बिना प्रमाणीकरण वाली खोज के लिए GET /api/public/cli/catalog, और आपका खाता वास्तव में जो सूची देख सकता है उसके लिए GET /api/common/commands — दोनों हर कमांड के JSON Schema पैरामीटर लौटाते हैं; कमांड सूची हार्ड-कोड करने के बजाय अपना क्लाइंट उन्हीं से बनाएँ।

नई कमांड जुड़ने पर क्या मुझे अपना क्लाइंट अपडेट करना होगा?

नहीं। क्लाइंट अपनी कमांड सूची कैटलॉग से खींचता है, इसलिए सर्वर पर जोड़ी गई कमांड बिना किसी नई क्लाइंट रिलीज़ के दिखाई देती है। अपडेट की ज़रूरत केवल ऐसे तोड़ने वाले बदलाव पर होती है जो कॉन्ट्रैक्ट संस्करण बढ़ाता है, और उस स्थिति में पुराना रूप कम से कम छह महीने तक जीवित रहता है।

क्या CLI मौजूदा REST API की जगह लेता है?

नहीं। वेब और मोबाइल ऐप को चलाने वाली REST सतह अपनी जगह पर रहती है। कमांड कैटलॉग संसाधन CRUD की जगह नहीं लेता; यह क्रियाओं की परत है — कोई कार्रवाई करने का एकमात्र, भूमिका-गेट वाला, पुष्टि-गेट वाला और ऑडिट किया गया तरीका।

मुझे Logistivo API कुंजी कैसे मिलती है और वह क्या कर सकती है?

टीम-प्रबंधन अनुमति वाला कोई मैनेजर इसे पैनल में Settings › Integration keys के अंतर्गत, या टर्मिनल से lg keys create से जारी करता है। कुंजी किसी वास्तविक टीम सदस्य की ओर से काम करती है और उसकी तीन स्वतंत्र सेटिंग्स हैं: स्कोप (read कैटलॉग और न लिखने वाली कमांड खोलता है, write हर कमांड खोलता है — पुष्टि गेट जैसा है वैसा रहता है), वैकल्पिक डोमेन अनुमतियाँ, और एक एक्सेस स्तर — रोज़मर्रा के संचालन के लिए employee (डिफ़ॉल्ट), या टीम, सेटिंग्स, कुंजियों और पैसे के लिए manager। यह केवल एक बार दिखाई जाती है और सर्वर पर संग्रहीत नहीं की जाती; इसे रोटेट, ट्रांसफ़र और रद्द किया जा सकता है। जिस सदस्य की ओर से यह काम करती है, उसके जाने पर कुंजी भी बंद हो जाती है। कोई सर्विस खाता नहीं है।

यदि मैं किसी आइडेम्पोटेंसी कुंजी को किसी दूसरी कमांड के लिए दोबारा उपयोग करूँ तो क्या होगा?

सर्वर 409 idempotency_conflict उत्तर देता है और उस कमांड का नाम बताता है जिसके लिए कुंजी पहली बार उपयोग हुई थी; कुछ नहीं चलता और कुछ भी दोहराया नहीं जाता। कुंजियाँ आपकी कंपनी तक सीमित हैं, एक कमांड से बँधी हैं और 24 घंटे के लिए लॉक रहती हैं — उसके बाद वही कुंजी एक नया निष्पादन शुरू करती है।

मेरे इंटीग्रेशन पर रेट लिमिट कैसे लागू होती हैं?

प्रति टोकन, प्रति मिनट, तीन बकेट में: कैटलॉग पढ़ना 120, पढ़ने वाली कमांड 120, लिखने वाली कमांड 30। 429 हमेशा Retry-After और retry_after, limit तथा bucket वाली बॉडी रखता है; उतनी देर प्रतीक्षा करें और पुनः प्रयास करें। कैटलॉग वर्तमान संख्याएँ rate_limits के अंतर्गत प्रकाशित करता है।

व्यावसायिक अस्वीकृति और ट्रांसपोर्ट त्रुटि में अंतर कैसे करूँ?

पहले error_code पर शाखा बनाएँ: failed (422) व्यावसायिक अस्वीकृति है और INSUFFICIENT_CREDITS या NOT_FOUND जैसी स्थिर error_key रखती है; server_error (5xx) और नेटवर्क त्रुटियों का पुनः प्रयास उसी आइडेम्पोटेंसी कुंजी के साथ किया जाता है; rate_limited (429) पर प्रतीक्षा की जाती है। त्रुटि के पाठ पर कभी शाखा न बनाएँ।

क्या Logistivo वेबहुक भेजता है? किन इवेंट के लिए?

हाँ। आप एक https पता पंजीकृत करते हैं और अपनी ज़रूरत के इवेंट चुनते हैं; उनके होते ही एक हस्ताक्षरित POST पहुँचता है। आज 13 इवेंट सब्सक्राइब किए जा सकते हैं: लोड बनाया गया/स्थिति बदली/ड्राइवर असाइन हुआ, डिमांड बनाई गई और स्थिति बदली, बोली लगाई गई/संशोधित हुई/स्वीकृत हुई, इनवॉइस ड्राफ़्ट/जारी/रद्द, और गोदाम आरक्षण बनाया गया/स्थिति बदली। हर नाम के पीछे एक इवेंट क्लास है जो वास्तव में डिस्पैच होती है — ऐसा कुछ नहीं है जिसकी घोषणा की गई हो और जो फिर कभी फ़ायर न हुआ हो, क्योंकि ऐसा इवेंट एक चुपचाप होने वाली विफलता है जिसकी प्रतीक्षा इंटीग्रेटर हमेशा करता रहता है। सब्सक्रिप्शन Settings › Integration › Webhooks के अंतर्गत, या टर्मिनल से lg webhooks create से बनाए जाते हैं।

Logistivo वेबहुक हस्ताक्षर का सत्यापन कैसे करूँ?

हर अनुरोध एक X-Logistivo-Signature हेडर रखता है: t=,v1=। हस्ताक्षरित स्ट्रिंग "." है, एल्गोरिदम HMAC-SHA256 है और कुंजी सब्सक्रिप्शन सीक्रेट है। चार नियम: (1) कच्चे (RAW) बाइट्स का सत्यापन करें — बॉडी को डिकोड करके फिर से सीरियलाइज़ करना (JSON.stringify / json_encode) उसी डेटा को अलग बाइट्स में बदल देता है और हस्ताक्षर मेल खाना बंद कर देता है; यही सबसे आम गलती है; (2) टाइमस्टैम्प जाँचें और ऐसा कुछ भी छोड़ दें जहाँ |now − t| > 300 s हो, भले ही हस्ताक्षर सही हो; (3) hash_equals / timingSafeEqual से स्थिर समय में तुलना करें; (4) डुप्लिकेट event_id के आधार पर हटाएँ, डिलीवरी id के आधार पर नहीं — replay पर event_id अपरिवर्तित रहता है जबकि डिलीवरी id बदल जाती है। काम करने वाले Node और PHP रिसीवर रिपॉज़िटरी में examples/webhook-receiver/ में हैं और --selftest के साथ स्वयं का परीक्षण करते हैं।

यदि कोई वेबहुक डिलीवर नहीं हो पाता तो क्या होता है? क्या मैं इवेंट खो देता हूँ?

नहीं। यदि आपका रिसीवर 2xx नहीं लौटाता, तो डिलीवरी पुनः प्रयास शेड्यूल में जाती है: 60 · 300 · 1800 · 7200 · 21600 सेकंड, कुल 6 प्रयास, लगभग 8.6 घंटे की विंडो। 410 Gone को छोड़कर हर एक विफलता का पुनः प्रयास होता है, 4xx सहित — किसी व्यावसायिक इवेंट को खोना कुछ अतिरिक्त अनुरोधों से अधिक महँगा है। लगातार 10 डिलीवरी के सभी प्रयास समाप्त होने के बाद सब्सक्रिप्शन म्यूट हो जाता है और कारण दर्ज किया जाता है, ताकि "कुछ भी क्यों नहीं आ रहा" का उत्तर मिल सके। डिलीवरी लेजर हर प्रयास (स्टेटस कोड, अवधि, त्रुटि) रखता है और आप पैनल से या lg webhooks replay से किसी एक डिलीवरी को फिर से भेज सकते हैं। इंक्रीमेंटल सिंक (updated_since + cursor) सुरक्षा जाल के रूप में अब भी मौजूद है।

क्या मेरा AI एजेंट वह सब कर सकता है जो कोई उपयोगकर्ता पैनल में कर सकता है?

लगभग सब कुछ। पैनल की हर लिखने वाली कार्रवाई के लिए एक कमांड है — पैनल के लिखने वाले एंडपॉइंट से मापने पर, दायरे में आने वाले 100% एंडपॉइंट कवर हैं — और यही कमांड lg, HTTP और MCP चैनल के लिए खुली हैं। जानबूझकर रखे गए अपवाद पहचान और पैसे से जुड़े चरण हैं: साइन इन करना, पैकेज खरीदना, 3D Secure के साथ कार्ड जोड़ना, कानूनी पाठों को स्वीकृत करना और खाता बंद करना व्यक्ति के ब्राउज़र में रहते हैं, और lg handoff-links generate उनके लिए लिंक लौटाता है। इंटीग्रेशन कुंजियाँ, वेबहुक और सैंडबॉक्स lg की बिल्ट-इन कमांड से प्रबंधित होते हैं, क्योंकि वे सीक्रेट केवल एक बार लौटाते हैं।

क्या मैं CLI या API से कमांड को PDF या फ़ोटो जैसी फ़ाइलें दे सकता हूँ?

हाँ। lg के साथ, किसी स्थानीय पथ के आगे @ लगाएँ (--attachment_uuid=@./cmr.pdf) और lg पहले फ़ाइल अपलोड करता है; जब किसी कमांड में एक ही फ़ाइल फ़ील्ड हो, तो --file एक शॉर्टकट है, और lg upload केवल अपलोड करता है। HTTP पर, फ़ाइल को multipart के रूप में POST /api/common/commands:upload पर भेजें और लौटाया गया attachment_uuid कमांड को पास करें; MCP क्लाइंट upload_attachment टूल का उपयोग करते हैं। प्रकार सामग्री से पहचाना जाता है, अपलोड उपयोगकर्ता के होते हैं और 24 घंटे तक उपयोग योग्य रहते हैं, और उसी फ़ाइल को दोबारा अपलोड करने पर वही id लौटती है।

employee और manager इंटीग्रेशन कुंजी में क्या अंतर है?

एक्सेस स्तर तय करता है कि कोई कुंजी कितना भारी काम कर सकती है। employee कुंजी, जो नई कुंजियों का डिफ़ॉल्ट है, रोज़मर्रा का संचालन चलाती है: लोड, डिमांड, बोलियाँ, ट्रिप, फ़्लीट, दस्तावेज़ और संपर्क। manager कुंजी प्रबंधन का काम भी कर सकती है — टीम सदस्य और भूमिकाएँ, कंपनी सेटिंग्स, इंटीग्रेशन कुंजियाँ, बैंक खाते, सहेजे गए कार्ड, एफ़िलिएट भुगतान। कोई कुंजी कभी भी उस व्यक्ति से अधिक अधिकार नहीं रखती जिसकी ओर से वह काम करती है, और manager कमांड बुलाने वाली employee कुंजी को INSUFFICIENT_KEY_LEVEL मिलता है। स्तर पैनल में या lg keys update --access-level=manager से बदलें।

क्या कोई एफ़िलिएट (रेफ़रल पार्टनर) CLI का उपयोग कर सकता है?

हाँ। एफ़िलिएट खाते को अपना अलग कैटलॉग मिलता है — रेफ़रल, लीड, CRM नोट और कार्य, सेल्स डेक, कमाई और भुगतान के लिए 55 कमांड — और वह इसे किसी भी अन्य भूमिका की तरह lg, HTTP या MCP से उपयोग करता है। भुगतान का अनुरोध करने या उसे रद्द करने और भुगतान वाले बैंक खाते को बदलने के लिए manager-स्तर की कुंजी और पुष्टि आवश्यक है। जो कंपनी शिपर, कैरियर या कस्टम्स ब्रोकर भी है, वह दोनों कैटलॉग देखती है।

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.