Brevo में CSV या Excel कॉन्टैक्ट्स को स्क्रिप्ट से कैसे इम्पोर्ट करें (Python, Node.js, cURL)
import-contacts API का उपयोग करके CSV या Excel फ़ाइल से Brevo में कॉन्टैक्ट्स को बल्क-इम्पोर्ट करें। तैयार Python और Node.js स्क्रिप्ट्स, cURL वन-लाइनर, एरर हैंडलिंग, और 10 MB से बड़ी फ़ाइलों के लिए टिप्स शामिल हैं।
अगर आपको कभी स्प्रेडशीट से कुछ हज़ार कॉन्टैक्ट्स को Brevo में पुश करने की ज़रूरत पड़ी है, तो मैनुअल UI पाथ जल्दी ही मुश्किल हो जाता है: फ़ाइल चुनें, कॉलम मैप करें, लिस्ट चुनें, इंतज़ार करें, फिर से करें। एक स्क्रिप्ट वही काम सेकंड्स में कर देती है, और (अधिक महत्वपूर्ण बात) आप इसे शेड्यूल पर, डेटाबेस एक्सपोर्ट के बाद, या जब भी आपका CRM ताज़ा CSV निकाले, फिर से चला सकते हैं।
यह गाइड बिल्कुल इसी के लिए Brevo द्वारा दिए गए API एंडपॉइंट को कवर करती है, Python, Node.js में पूरी काम करने वाली स्क्रिप्ट्स के साथ, और एक cURL वन-लाइनर। इस गाइड में सब कुछ POST /v3/contacts/import पर हिट करता है।
एंडपॉइंट एक नज़र में
POST https://api.brevo.com/v3/contacts/importContent-Type: application/jsonapi-key: YOUR_API_KEY
{ "listIds": [42], "updateExistingContacts": true, "emailBlacklist": false, "smsBlacklist": false}रिस्पॉन्स तेज़ी से वापस आता है:
{ "processId": 78 }यह 202 Accepted है, Brevo ने इम्पोर्ट को स्वीकार कर लिया है और इसे बैकग्राउंड में प्रोसेस कर रहा है। processId आपका ट्रैकिंग हैंडल है यदि आप पूर्ण होने के लिए पोल करना चाहते हैं या notifyUrl वेबहुक सेट करना चाहते हैं।
कोड लिखने से पहले ध्यान देने योग्य कुछ बातें:
- बॉडी CSV (
fileBody), JSON (jsonBody), या रिमोट URL (fileUrl) हो सकती है। एक चुनें। CSV फ़ॉर्म कॉलम अलग करने के लिए सेमीकोलन (;) का उपयोग करता है, कॉमा का नहीं, यह एक सामान्य गलती है। fileBodyऔरjsonBodyकी सीमा 10 MB है। Brevo सुरक्षित रहने के लिए लगभग 8 MB के आसपास रहने की सलाह देता है। इससे बड़े के लिए, फ़ाइल को S3, GCS, या किसी भी HTTPS होस्ट पर अपलोड करें और इसके बजायfileUrlपास करें।- आपके अकाउंट में मौजूद नहीं होने वाले कस्टम एट्रिब्यूट्स को चुपचाप नज़रअंदाज़ कर दिया जाता है। उन्हें उपयोग करने वाली रोज़ इम्पोर्ट करने से पहले Brevo के UI में (या Attributes API के माध्यम से) बनाएँ, अन्यथा डेटा गायब हो जाता है।
updateExistingContactsका डिफ़ॉल्टtrueहै। यदि आप इसेfalseपर सेट करते हैं, तो Brevo उन कॉन्टैक्ट्स को स्किप कर देता है जिनका ईमेल पहले से मौजूद है, “केवल नए जोड़ें” वाली जॉब्स के लिए उपयोगी।emptyContactsAttributesनियंत्रित करता है कि क्या आपके CSV में खाली सेल्स मौजूदा वैल्यूज़ को मिटाते हैं। डिफ़ॉल्टfalse(खाली सेल्स को नज़रअंदाज़ किया जाता है)।trueपर सेट करें यदि CSV सत्य का स्रोत है और आप चाहते हैं कि ब्लैंक्स पुराने डेटा को साफ़ करें।
API key प्राप्त करें
Brevo में लॉग इन करें -> Settings -> SMTP & API -> API Keys -> एक नई key बनाएँ। यह xkeysib-... जैसा दिखता है। आप इसे हर रिक्वेस्ट पर api-key HTTP हेडर के रूप में पास करेंगे। इसे पासवर्ड की तरह ट्रीट करें, इसके पास आपके अकाउंट पर पूर्ण रीड/राइट एक्सेस है।
एक साफ़ पैटर्न: इसे एनवायरनमेंट वेरिएबल में रखें ताकि यह कभी भी आपके सोर्स ट्री में न आए।
export BREVO_API_KEY="xkeysib-..."Python: एक CSV पढ़ें, इसे Brevo में पुश करें
यह सबसे सरल संभव स्क्रिप्ट है: स्टैंडर्ड लाइब्रेरी के साथ एक लोकल CSV पढ़ें, बॉडी को सीधे Brevo में भेजें। requests के अलावा कोई थर्ड-पार्टी SDK की ज़रूरत नहीं है।
import csvimport ioimport osimport sysimport requests
API_KEY = os.environ["BREVO_API_KEY"]LIST_ID = 42 # the Brevo list to add contacts toINPUT_FILE = sys.argv[1] if len(sys.argv) > 1 else "contacts.csv"
# Brevo wants semicolon-separated CSV. If your file uses commas (most do),# convert it on the fly so you don't have to edit the source spreadsheet.def to_brevo_csv(path: str) -> str: with open(path, newline="", encoding="utf-8") as f: reader = csv.reader(f) # default: comma-separated out = io.StringIO() writer = csv.writer(out, delimiter=";") for row in reader: writer.writerow(row) return out.getvalue()
body = { "fileBody": to_brevo_csv(INPUT_FILE), "listIds": [LIST_ID], "updateExistingContacts": True, "emptyContactsAttributes": False, "emailBlacklist": False, "smsBlacklist": False,}
resp = requests.post( "https://api.brevo.com/v3/contacts/import", json=body, headers={"api-key": API_KEY, "Content-Type": "application/json"}, timeout=60,)
if resp.status_code != 202: print(f"Import failed: {resp.status_code} {resp.text}") sys.exit(1)
process_id = resp.json()["processId"]print(f"Import accepted. Process ID: {process_id}")इसे चलाएँ:
python import_csv_to_brevo.py contacts.csvआपके CSV की पहली रो हेडर है। कॉलम नाम Brevo एट्रिब्यूट्स से अपरकेस, सटीक मैच द्वारा मैप होते हैं: EMAIL, FIRSTNAME, LASTNAME, साथ ही कोई भी कस्टम एट्रिब्यूट जो आपने डिफ़ाइन किया है। EMAIL अनिवार्य है।
EMAIL,FIRSTNAME,LASTNAME,COMPANY,CITYबस यही पूरा फ़्लो है। स्क्रिप्ट एक सेकंड के भीतर वापस आ जाती है; वास्तविक इम्पोर्ट सर्वर साइड पर चलता है और वॉल्यूम के आधार पर कुछ सेकंड से लेकर कुछ मिनट तक का समय लेता है।
Excel फ़ाइलें: तीन व्यावहारिक रास्ते
Brevo का इम्पोर्ट एंडपॉइंट .xlsx को सीधे नहीं पढ़ता, इसलिए इस पर निर्भर करते हुए कि काम कहाँ रहना है, आपके पास तीन वास्तविक विकल्प हैं:
- वर्कबुक के अंदर एक VBA मैक्रो चलाएँ, स्वयं Excel से एक-क्लिक सिंक, कोई बाहरी स्क्रिप्ट नहीं। यह सही उत्तर है जब फ़ाइल डेस्कटॉप पर रहती है और आपकी टीम शीट पर एक बटन चाहती है। पूरा कोड Excel-to-Brevo VBA मैक्रो गाइड में।
- Office Scripts + Power Automate, यदि वर्कबुक OneDrive/SharePoint पर है और आप अनअटेंडेड शेड्यूल्ड सिंक चाहते हैं। Excel गाइड में भी कवर किया गया है।
- स्क्रिप्ट से
.xlsxको CSV में कन्वर्ट करें, इस सेक्शन का बाकी हिस्सा यही कवर करता है। सबसे अच्छा यदि आप पहले से ही सर्वर पर Python या Node चला रहे हैं और बस दिन में एक बार वर्कबुक पुल करने की ज़रूरत है।
विकल्प 3 के लिए, pandas इसे एक-लाइनर बना देता है:
# pip install pandas openpyxlimport pandas as pd
def xlsx_to_brevo_csv(path: str, sheet_name: str | int = 0) -> str: df = pd.read_excel(path, sheet_name=sheet_name) return df.to_csv(sep=";", index=False)
body["fileBody"] = xlsx_to_brevo_csv("contacts.xlsx")यदि आप pandas को डिपेंडेंसी के रूप में नहीं चाहते, तो अकेले openpyxl काम करता है:
from openpyxl import load_workbookimport csv, io
def xlsx_to_brevo_csv(path: str) -> str: wb = load_workbook(path, read_only=True) ws = wb.active out = io.StringIO() writer = csv.writer(out, delimiter=";") for row in ws.iter_rows(values_only=True): writer.writerow(["" if v is None else v for v in row]) return out.getvalue()Node.js: वही काम, ऑफ़िशियल SDK
Brevo Node के लिए @getbrevo/brevo पब्लिश करता है। यह ऑथ, रिट्राइज़, और टाइप्ड रिक्वेस्ट शेप को हैंडल करता है:
// npm install @getbrevo/brevoimport fs from 'node:fs/promises';import { BrevoClient } from '@getbrevo/brevo';
const API_KEY = process.env.BREVO_API_KEY;const LIST_ID = 42;const INPUT_FILE = process.argv[2] ?? 'contacts.csv';
const client = new BrevoClient({ apiKey: API_KEY });
// Read the CSV and convert commas to semicolons if neededconst raw = await fs.readFile(INPUT_FILE, 'utf-8');const csv = raw.includes(';') ? raw : raw.replace(/,/g, ';');
const result = await client.contacts.importContacts({ fileBody: csv, listIds: [LIST_ID], updateExistingContacts: true, emptyContactsAttributes: false,});
console.log(`Import accepted. Process ID: ${result.processId}`);या, यदि आप SDK नहीं चाहते, तो साधारण fetch उसी तरह काम करता है:
const resp = await fetch('https://api.brevo.com/v3/contacts/import', { method: 'POST', headers: { 'api-key': process.env.BREVO_API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ fileBody: csv, listIds: [42], updateExistingContacts: true, }),});
if (resp.status !== 202) { throw new Error(`Import failed: ${resp.status} ${await resp.text()}`);}
const { processId } = await resp.json();console.log(`Process ID: ${processId}`);cURL: ऐड-हॉक इम्पोर्ट्स के लिए वन-लाइनर
जब आप बस एंडपॉइंट को टेस्ट करना चाहते हैं या एक छोटी फ़ाइल को हाथ से पुश करना चाहते हैं:
# Convert commas to semicolons, then send the file inlinecsv=$(sed 's/,/;/g' contacts.csv | jq -Rs .)
curl -X POST https://api.brevo.com/v3/contacts/import \ -H "api-key: $BREVO_API_KEY" \ -H "Content-Type: application/json" \ -d "{\"fileBody\": $csv, \"listIds\": [42], \"updateExistingContacts\": true}"jq -Rs . पूरी फ़ाइल को slurp करता है और उसे JSON-escape करता है, यह आपको न्यूलाइन्स और कोट्स को मैन्युअली एस्केप करने से बचाता है।
10 MB से बड़ी फ़ाइलें: fileUrl का उपयोग करें
fileBody 10 MB पर कैप्ड है। यदि आपका कॉन्टैक्ट डंप इससे बड़ा है, तो फ़ाइल को एक URL पर होस्ट करें जिसे Brevo फ़ेच कर सके और उसे पास करें:
body = { "fileUrl": "https://files.example.com/contacts/2026-04-30.csv", "listIds": [42], "updateExistingContacts": True,}पब्लिक HTTPS URL के माध्यम से पहुँच योग्य कुछ भी काम करता है, प्री-साइन्ड S3 URLs, GCS, आपका अपना स्टैटिक होस्ट, यहाँ तक कि वन-ऑफ़ इम्पोर्ट्स के लिए GitHub raw URL भी। Brevo आपके URL से फ़ाइल फ़ेच करता है, फिर इम्पोर्ट चलाता है। स्वीकृत फ़ॉर्मेट्स: .csv, .txt, .json।
CSV के बजाय JSON भेजें
यदि आप पहले से ही डेटाबेस से कॉन्टैक्ट्स पुल कर रहे हैं, तो आपको CSV के माध्यम से राउंड-ट्रिप करने की ज़रूरत नहीं है, उन्हें सीधे JSON के रूप में भेजें:
body = { "jsonBody": [ { "attributes": { "FIRSTNAME": "Jane", "LASTNAME": "Doe", "COMPANY": "Acme", }, }, { "attributes": { "FIRSTNAME": "John", "LASTNAME": "Smith", "COMPANY": "Globex", }, }, ], "listIds": [42],}वही 10 MB कैप। वही async व्यवहार।
पूर्ण होने के लिए पोलिंग
इम्पोर्ट asynchronous है, processId इसे ट्रैक करने के लिए आपका हैंडल है। प्रोसेस स्टेटस चेक करने के लिए एक अलग एंडपॉइंट है:
def wait_for_import(process_id: int, timeout_s: int = 600) -> dict: import time deadline = time.time() + timeout_s while time.time() < deadline: r = requests.get( f"https://api.brevo.com/v3/processes/{process_id}", headers={"api-key": API_KEY}, timeout=30, ) r.raise_for_status() status = r.json() if status["status"] in ("completed", "failed"): return status time.sleep(5) raise TimeoutError(f"Import {process_id} did not finish in {timeout_s}s")
result = wait_for_import(process_id)print(f"Import {result['status']}: {result}")लंबे समय तक चलने वाली जॉब्स के लिए, क्लीनर पैटर्न notifyUrl है: एक HTTPS एंडपॉइंट पास करें जिस पर इम्पोर्ट पूरा होने पर Brevo POST करेगा, और पोलिंग को छोड़ दें।
body["notifyUrl"] = "https://your-app.example.com/webhooks/brevo-import"सामान्य एरर और उन्हें कैसे ठीक करें
बिना स्पष्ट कारण के 400 Bad Request. लगभग हमेशा CSV में सेमीकोलन बनाम कॉमा। Brevo का इम्पोर्ट ; अपेक्षा करता है, , नहीं। अपने कन्वर्शन स्टेप के बाद fileBody को डबल-चेक करें।
कस्टम एट्रिब्यूट वैल्यूज़ गायब हो जाती हैं. एट्रिब्यूट आपके अकाउंट में मौजूद नहीं है। इम्पोर्ट करने से पहले इसे Contacts -> Settings -> Contact attributes के तहत बनाएँ, या अपनी स्क्रिप्ट के हिस्से के रूप में बनाने के लिए Attributes API का उपयोग करें।
401 Unauthorized. ग़लत हेडर नाम। यह api-key है (छोटे अक्षर, हाइफ़न), Authorization या X-API-Key नहीं।
इम्पोर्ट “सफल” हुआ लेकिन कॉन्टैक्ट्स लिस्ट में दिखाई नहीं दिए. चेक करें कि listIds में सही लिस्ट है। साथ ही: यदि updateExistingContacts false है और कॉन्टैक्ट्स पहले से मौजूद हैं, तो Brevo उन्हें लिस्ट में फिर से जोड़ने के बजाय चुपचाप स्किप कर देता है।
कुछ रोज़ इम्पोर्ट हुईं, कुछ नहीं. Brevo इम्पोर्ट पूरा होने के बाद आपको प्रति-रो एरर रिपोर्ट ईमेल करता है (जब तक कि आप disableNotification: true सेट न करें)। रिपोर्ट आपको बताती है कि किन रोज़ में ख़राब ईमेल, गुम आवश्यक फ़ील्ड्स, या फ़ॉर्मेटिंग समस्याएँ थीं।
स्क्रिप्ट कब लिखें बनाम UI का उपयोग कब करें
UI एक हज़ार रोज़ से कम के वन-ऑफ़ इम्पोर्ट्स के लिए ठीक है। एक स्क्रिप्ट तब जीतती है जब:
- आप एक से अधिक बार इम्पोर्ट कर रहे हैं (जैसे आपके CRM से साप्ताहिक एक्सपोर्ट)
- सोर्स डेटा को Brevo में जाने से पहले साफ़ करने की ज़रूरत है (डीडुप्लिकेशन, फ़ोन नंबर फ़ॉर्मेटिंग, फ़ुल नेम्स को फ़र्स्ट/लास्ट में स्प्लिट करना)
- आप चाहते हैं कि यह बिना किसी के बटन क्लिक किए शेड्यूल पर चले
- फ़ाइल UI के कम्फर्ट ज़ोन से बड़ी है
ऊपर की स्क्रिप्ट को क्रॉन जॉब या GitHub Action में रैप करें और आपके पास ऑटोमेटेड कॉन्टैक्ट सिंक है। इस सीरीज़ की अगली पोस्ट दिखाती है कि Apps Script का उपयोग करके सीधे Google Sheet से वही चीज़ कैसे करें, बिना किसी सर्वर के।