ایک اسکرپٹ (Python، Node.js، cURL) کے ساتھ CSV یا Excel گاہکوں کو Brevo میں کیسے امپورٹ کریں
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 نے امپورٹ قبول کر لیا ہے اور بیک گراؤنڈ میں اس پر کام کر رہا ہے۔ اگر آپ مکمل ہونے کے لیے poll کرنا چاہیں یا notifyUrl ویب ہک سیٹ اپ کرنا چاہیں تو processId آپ کا ٹریکنگ ہینڈل ہے۔
کوڈ لکھنے سے پہلے قابل غور چند چیزیں:
- باڈی 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(خالی سیلز نظر انداز ہوتے ہیں)۔ اگر آپ کا CSV سچ کا ذریعہ ہے اور آپ چاہتے ہیں کہ خالی سیلز پرانے ڈیٹا کو صاف کریں توtrueپر سیٹ کریں۔
ایک API کلید حاصل کریں
Brevo میں سائن ان کریں → Settings → SMTP & API → API Keys → ایک نئی کلید بنائیں۔ یہ 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 سے 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 . پوری فائل کو نگل لیتا ہے اور JSON-escape کرتا ہے، آپ کو نئی لائنوں اور کوٹس کو دستی طور پر 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 کی حد۔ وہی ایسنکرونس رویہ۔
مکمل ہونے کے لیے Polling
امپورٹ ایسنکرونس ہے، 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 کے کمفرٹ زون سے بڑی ہے
اوپر دی گئی اسکرپٹ کو ایک cron جاب یا GitHub Action میں لپیٹیں اور آپ کے پاس خودکار گاہک سنک ہے۔ اس سیریز کی اگلی پوسٹ دکھاتی ہے کہ اپنے Apps Script کا استعمال کرتے ہوئے براہ راست Google Sheet سے یہی کام کیسے کیا جائے، کوئی سرور درکار نہیں۔