Ako importovať kontakty z CSV alebo Excelu do Brevo pomocou skriptu (Python, Node.js, cURL)
Hromadne importujte kontakty zo súboru CSV alebo Excel do Brevo pomocou API import-contacts. Súčasťou sú pripravené skripty v Pythone a Node.js, jednoriadkový cURL, spracovanie chýb a tipy pre súbory väčšie ako 10 MB.
Ak ste niekedy potrebovali poslať pár tisíc kontaktov z tabuľky do Brevo, viete, že manuálna cesta cez používateľské rozhranie sa rýchlo stáva nepríjemnou: vyberte súbor, namapujte stĺpce, vyberte zoznam, počkajte, opakujte. Skript urobí tú istú prácu za sekundy a, čo je dôležitejšie, môžete ho spustiť znova podľa rozvrhu, po exporte z databázy alebo vždy, keď vaše CRM vypľuje čerstvé CSV.
Táto príručka pokrýva endpoint API, ktorý vám Brevo dáva presne na toto, s plne funkčnými skriptami v Pythone, Node.js a jednoriadkovým cURL. Všetko v tejto príručke smeruje na POST /v3/contacts/import.
Endpoint v skratke
POST https://api.brevo.com/v3/contacts/importContent-Type: application/jsonapi-key: YOUR_API_KEY
{ "listIds": [42], "updateExistingContacts": true, "emailBlacklist": false, "smsBlacklist": false}Odpoveď príde rýchlo:
{ "processId": 78 }To je 202 Accepted. Brevo prijalo import a spracúva ho na pozadí. processId je vaša sledovacia rukoväť, ak chcete polovať dokončenie alebo nastaviť webhook notifyUrl.
Pár vecí, ktoré stojí za zmienku predtým, ako začnete písať kód:
- Telo môže byť CSV (
fileBody), JSON (jsonBody) alebo vzdialená URL (fileUrl). Vyberte si jedno. CSV forma používa bodkočiarky (;) na oddeľovanie stĺpcov, nie čiarky. To je častý kameň úrazu. fileBodyajsonBodysú obmedzené na 10 MB. Brevo odporúča pre istotu zostať okolo 8 MB. Pre čokoľvek väčšie nahrajte súbor na S3, GCS alebo akýkoľvek HTTPS hosting a namiesto toho odovzdajtefileUrl.- Vlastné atribúty, ktoré vo vašom účte neexistujú, sa potichu ignorujú. Vytvorte ich v používateľskom rozhraní Brevo (alebo cez Attributes API) ešte pred importom riadkov, ktoré ich používajú, inak údaje jednoducho zmiznú.
updateExistingContactsmá predvolenetrue. Ak ho nastavíte nafalse, Brevo preskočí kontakty, ktorých e-mail už existuje. Užitočné pre úlohy typu „pridať len nové”.emptyContactsAttributesriadi, či prázdne bunky vo vašom CSV majú vymazať existujúce hodnoty. Predvolenéfalse(prázdne bunky sa ignorujú). Nastavte natrue, ak je vaše CSV zdrojom pravdy a chcete, aby prázdne hodnoty vymazali zastarané údaje.
Získajte API kľúč
Prihláste sa do Brevo, prejdite na Settings → SMTP & API → API Keys a vytvorte nový kľúč. Vyzerá ako xkeysib-.... Odovzdáte ho ako HTTP hlavičku api-key pri každej požiadavke. Zaobchádzajte s ním ako s heslom. Má plný čítaco-zápisový prístup k vášmu účtu.
Čistý vzor: vložte ho do premennej prostredia, aby sa nikdy nedostal do vášho zdrojového stromu.
export BREVO_API_KEY="xkeysib-..."Python: prečítajte CSV a pošlite ho do Brevo
Toto je najjednoduchší možný skript: prečítajte lokálne CSV pomocou štandardnej knižnice a telo pošlite priamo do Brevo. Žiadne SDK tretej strany nie je potrebné okrem requests.
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}")Spustite ho:
python import_csv_to_brevo.py contacts.csvPrvý riadok vášho CSV je hlavička. Názvy stĺpcov sa mapujú na atribúty Brevo cez veľké písmená, presná zhoda: EMAIL, FIRSTNAME, LASTNAME, plus akýkoľvek vlastný atribút, ktorý ste si definovali. EMAIL je povinný.
EMAIL,FIRSTNAME,LASTNAME,COMPANY,CITYTo je celý tok. Skript sa vráti do sekundy. Samotný import beží na strane servera a trvá od pár sekúnd do pár minút v závislosti od objemu.
Súbory Excel: tri rozumné cesty
Importný endpoint Brevo nečíta .xlsx priamo, takže máte tri reálne možnosti podľa toho, kde má práca žiť:
- Spustite VBA makro vo vnútri zošita. Synchronizácia z Excelu samotného jedným klikom, žiadny externý skript. Toto je správna odpoveď, keď súbor žije na ploche a váš tím chce mať tlačidlo na hárku. Plný kód v príručke pre Excel-do-Brevo VBA makro.
- Office Scripts + Power Automate. Ak je zošit v OneDrive/SharePoint a chcete bezobslužnú plánovanú synchronizáciu. Tiež pokryté v Excel príručke.
- Konvertujte
.xlsxna CSV zo skriptu. Toto pokrýva zvyšok tejto sekcie. Najlepšie, ak už beží Python alebo Node na serveri a stačí vám raz denne stiahnuť zošit.
Pre možnosť 3 je pandas otázkou jedného riadku:
# 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")Ak nechcete pandas ako závislosť, samotný openpyxl funguje:
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: tá istá práca, oficiálne SDK
Brevo publikuje @getbrevo/brevo pre Node. Postará sa o autentifikáciu, opätovné pokusy a typovanú podobu požiadavky:
// 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}`);Alebo, ak nechcete SDK, obyčajný fetch funguje rovnako:
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: jednoriadok pre ad hoc importy
Keď chcete iba otestovať endpoint alebo natlačiť dnu malý súbor ručne:
# 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 . zhltne celý súbor a JSON-escapuje ho. Ušetrí vám to manuálne escapovanie nových riadkov a úvodzoviek.
Súbory väčšie ako 10 MB: použite fileUrl
fileBody je obmedzené na 10 MB. Ak je váš výpis kontaktov väčší, hostujte súbor na URL, ktorú Brevo dokáže stiahnuť, a odovzdajte ju:
body = { "fileUrl": "https://files.example.com/contacts/2026-04-30.csv", "listIds": [42], "updateExistingContacts": True,}Funguje čokoľvek dostupné cez verejnú HTTPS URL: pre-podpísané S3 URL, GCS, váš vlastný statický hosting, dokonca aj GitHub raw URL pre jednorazové importy. Brevo stiahne súbor z vašej URL a potom spustí import. Akceptované formáty: .csv, .txt, .json.
Pošlite JSON namiesto CSV
Ak už ťaháte kontakty z databázy, nemusíte robiť obchádzku cez CSV. Pošlite ich ako JSON priamo:
body = { "jsonBody": [ { "attributes": { "FIRSTNAME": "Jane", "LASTNAME": "Doe", "COMPANY": "Acme", }, }, { "attributes": { "FIRSTNAME": "John", "LASTNAME": "Smith", "COMPANY": "Globex", }, }, ], "listIds": [42],}Rovnaký 10 MB strop. Rovnaké asynchrónne správanie.
Polovanie dokončenia
Import je asynchrónny. processId je vaša rukoväť na jeho sledovanie. Existuje samostatný endpoint na kontrolu stavu procesu:
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}")Pre dlhotrvajúce úlohy je čistejším vzorom notifyUrl: odovzdajte HTTPS endpoint, na ktorý Brevo pošle POST, keď sa import dokončí, a polovanie preskočte.
body["notifyUrl"] = "https://your-app.example.com/webhooks/brevo-import"Bežné chyby a ako ich opraviť
400 Bad Request bez zjavnej príčiny. Takmer vždy bodkočiarky vs čiarky v CSV. Importu Brevo treba ;, nie ,. Skontrolujte fileBody po vašom konverznom kroku.
Hodnoty vlastných atribútov miznú. Atribút vo vašom účte neexistuje. Vytvorte ho v Contacts → Settings → Contact attributes pred importom, alebo použite Attributes API na jeho vytvorenie ako súčasť vášho skriptu.
401 Unauthorized. Nesprávny názov hlavičky. Je to api-key (malé písmená, pomlčka), nie Authorization ani X-API-Key.
Import „uspel”, ale kontakty sa v zozname neobjavili. Skontrolujte, či listIds obsahuje správny zoznam. A: ak je updateExistingContacts nastavené na false a kontakty už existujú, Brevo ich potichu preskočí namiesto opätovného pridania do zoznamu.
Niektoré riadky sa importovali, iné nie. Brevo vám po dokončení importu pošle e-mail s chybovou správou na riadok (pokiaľ ste nenastavili disableNotification: true). Správa vám povie, ktoré riadky mali zlé e-maily, chýbajúce povinné polia alebo formátovacie problémy.
Kedy skriptovať a kedy použiť používateľské rozhranie
Používateľské rozhranie je v poriadku pre jednorazové importy do tisíca riadkov. Skript vyhráva hneď, ako:
- Importujete viackrát (napríklad týždenný export z vášho CRM)
- Zdrojové údaje potrebujú vyčistenie predtým, ako pristanú v Brevo (deduplikácia, formátovanie telefónnych čísel, rozdelenie celého mena na krstné a priezvisko)
- Chcete, aby to bežalo podľa rozvrhu bez toho, aby niekto klikal na tlačidlá
- Súbor je väčší ako komfortná zóna používateľského rozhrania
Zabaľte vyššie uvedený skript do cron úlohy alebo GitHub Action a máte automatizovanú synchronizáciu kontaktov. Ďalší príspevok zo série ukazuje, ako urobiť to isté priamo z Google Sheet pomocou Apps Script. Bez servera.