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.

Featured image for article: Ako importovať kontakty z CSV alebo Excelu do Brevo pomocou skriptu (Python, Node.js, cURL)

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/import
Content-Type: application/json
api-key: YOUR_API_KEY
{
"fileBody": "EMAIL;FIRSTNAME;LASTNAME\n[email protected];Jane;Doe",
"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.
  • fileBody a jsonBody sú 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 odovzdajte fileUrl.
  • 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ú.
  • updateExistingContacts má predvolene true. Ak ho nastavíte na false, Brevo preskočí kontakty, ktorých e-mail už existuje. Užitočné pre úlohy typu „pridať len nové”.
  • emptyContactsAttributes riadi, či prázdne bunky vo vašom CSV majú vymazať existujúce hodnoty. Predvolené false (prázdne bunky sa ignorujú). Nastavte na true, 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.

Terminal window
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_csv_to_brevo.py
import csv
import io
import os
import sys
import requests
API_KEY = os.environ["BREVO_API_KEY"]
LIST_ID = 42 # the Brevo list to add contacts to
INPUT_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:

Terminal window
python import_csv_to_brevo.py contacts.csv

Prvý 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,CITY
[email protected],Jane,Doe,Acme,Berlin
[email protected],John,Smith,Globex,Paris

To 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ť:

  1. 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.
  2. 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.
  3. Konvertujte .xlsx na 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 openpyxl
import 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_workbook
import 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:

import-csv-to-brevo.mjs
// npm install @getbrevo/brevo
import 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 needed
const 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:

Terminal window
# Convert commas to semicolons, then send the file inline
csv=$(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": [
{
"email": "[email protected]",
"attributes": {
"FIRSTNAME": "Jane",
"LASTNAME": "Doe",
"COMPANY": "Acme",
},
},
{
"email": "[email protected]",
"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.

Ďalšie čítanie

Frequently Asked Questions

Aký je endpoint Brevo API na hromadný import kontaktov?
POST https://api.brevo.com/v3/contacts/import. Prijíma obsah CSV (fileBody), URL vzdialeného súboru (fileUrl) alebo JSON pole (jsonBody). Endpoint je asynchrónny: okamžite vráti processId a import dokončí na pozadí.
Aká je maximálna veľkosť súboru?
10 MB pre vložené CSV (fileBody) alebo JSON (jsonBody). Pre väčšie súbory hostujte súbor na dostupnom mieste a namiesto toho odovzdajte jeho URL cez fileUrl. Táto cesta nemá zdokumentovaný strop veľkosti.
Ako importujem súbor .xlsx?
Importné API Brevo prijíma iba .csv, .txt alebo .json. Najprv konvertujte .xlsx na .csv. Pandas, openpyxl alebo LibreOffice headless to zvládnu jedným riadkom. Skript v tejto príručke obsahuje konverziu z xlsx na csv.
Prepíše to existujúce kontakty?
Štandardne áno. updateExistingContacts má predvolene true a porovnáva podľa e-mailu. Nastavte ho na false, ak chcete preskočiť kontakty, ktoré už existujú. Nastavte emptyContactsAttributes na true, ak chcete, aby prázdne bunky CSV vymazali existujúce hodnoty (inak sa prázdne bunky ignorujú).
Začnite zadarmo s Brevo