Kako uvoziti stike iz CSV ali Excela v Brevo s skripto (Python, Node.js, cURL)
Množični uvoz stikov iz datoteke CSV ali Excel v Brevo z API-jem import-contacts. Vključuje pripravljene skripte v Pythonu in Node.js, eno vrstico cURL, obravnavanje napak in nasvete za datoteke, večje od 10 MB.
Če ste kdaj morali poslati nekaj tisoč stikov iz preglednice v Brevo, veste, da ročna pot prek vmesnika hitro postane mučna: izberite datoteko, mapirajte stolpce, izberite seznam, počakajte, ponovite. Skripta opravi isto delo v sekundah in, kar je še pomembneje, lahko jo ponovno zaženete po urniku, po izvozu iz baze podatkov ali kadarkoli vaš CRM izvrže svežo CSV.
Ta vodnik pokriva API endpoint, ki ga Brevo nudi prav za to, s polno delujočimi skriptami v Pythonu, Node.js in eno vrstico cURL. Vse v tem vodniku gre na POST /v3/contacts/import.
Endpoint na hitro
POST https://api.brevo.com/v3/contacts/importContent-Type: application/jsonapi-key: YOUR_API_KEY
{ "listIds": [42], "updateExistingContacts": true, "emailBlacklist": false, "smsBlacklist": false}Odziv pride hitro:
{ "processId": 78 }To je 202 Accepted. Brevo je sprejel uvoz in ga obdeluje v ozadju. processId je vaš ročaj za sledenje, če želite preverjati dokončanje ali nastaviti webhook notifyUrl.
Nekaj stvari, ki jih je vredno omeniti, preden začnete pisati kodo:
- Telo je lahko CSV (
fileBody), JSON (jsonBody) ali oddaljeni URL (fileUrl). Izberite eno. Oblika CSV uporablja podpičja (;) za ločevanje stolpcev, ne vejic. To je pogosta past. fileBodyinjsonBodysta omejena na 10 MB. Brevo priporoča, da za varnost ostanete okoli 8 MB. Za karkoli večjega naložite datoteko na S3, GCS ali katerokoli HTTPS gostovanje in namesto tega posredujtefileUrl.- Lastni atributi, ki ne obstajajo v vašem računu, se tiho prezrejo. Ustvarite jih v vmesniku Brevo (ali prek Attributes API), preden uvozite vrstice, ki jih uporabljajo, sicer podatki preprosto izginejo.
updateExistingContactsima privzeto vrednosttrue. Če ga nastavite nafalse, Brevo preskoči stike, katerih e-pošta že obstaja. Uporabno za naloge tipa „dodaj samo nove”.emptyContactsAttributesnadzira, ali naj prazne celice v vašem CSV izbrišejo obstoječe vrednosti. Privzetofalse(prazne celice so prezrte). Nastavite natrue, če je vaš CSV vir resnice in želite, da prazne vrednosti počistijo zastarele podatke.
Pridobite API ključ
Prijavite se v Brevo, pojdite na Settings → SMTP & API → API Keys in ustvarite nov ključ. Izgleda kot xkeysib-.... Posredovali ga boste kot HTTP glavo api-key pri vsaki zahtevi. Obravnavajte ga kot geslo. Ima poln dostop za branje in pisanje na vaš račun.
Čist vzorec: dajte ga v okoljsko spremenljivko, da nikoli ne pristane v vašem izvornem drevesu.
export BREVO_API_KEY="xkeysib-..."Python: preberite CSV in ga pošljite v Brevo
To je najpreprostejša možna skripta: preberite lokalni CSV s standardno knjižnico in telo pošljite naravnost v Brevo. Ne potrebujete SDK tretje osebe razen 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}")Zaženite jo:
python import_csv_to_brevo.py contacts.csvPrva vrstica vašega CSV je glava. Imena stolpcev se mapirajo na atribute Brevo prek velikih črk, natančno ujemanje: EMAIL, FIRSTNAME, LASTNAME, plus vsak lastni atribut, ki ste ga definirali. EMAIL je obvezen.
EMAIL,FIRSTNAME,LASTNAME,COMPANY,CITYTo je celoten potek. Skripta se vrne v sekundi. Sam uvoz teče na strani strežnika in traja od nekaj sekund do nekaj minut, odvisno od količine.
Excelove datoteke: tri sprejemljive poti
Brevo uvozni endpoint ne bere .xlsx neposredno, zato imate tri prave možnosti, odvisno od tega, kje mora delo živeti:
- Zaženite VBA makro znotraj delovnega zvezka. Sinhronizacija iz samega Excela z enim klikom, brez zunanje skripte. To je pravi odgovor, ko datoteka živi na namizju in vaša ekipa želi gumb na listu. Polna koda v vodniku za VBA makro Excel-v-Brevo.
- Office Scripts + Power Automate. Če delovni zvezek živi v OneDrive/SharePoint in želite nenadzorovano sinhronizacijo po urniku. Pokrito tudi v Excel vodniku.
- Pretvorite
.xlsxv CSV iz skripte. To pokriva preostanek tega odseka. Najboljše, če že poganjate Python ali Node na strežniku in morate samo enkrat dnevno potegniti delovni zvezek.
Za možnost 3 je pandas ena vrstica:
# 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")Če ne želite pandas kot odvisnost, sam openpyxl deluje:
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: isto delo, uradni SDK
Brevo objavlja @getbrevo/brevo za Node. Poskrbi za avtentikacijo, ponovne poskuse in tipizirano obliko zahteve:
// 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}`);Ali pa, če nočete SDK, navaden fetch deluje enako:
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: ena vrstica za priložnostne uvoze
Ko želite samo preizkusiti endpoint ali ročno potisniti majhno datoteko:
# 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 . pogoltne celotno datoteko in jo JSON-ubeži, kar vas reši ročnega ubežanja prelomov vrstic in narekovajev.
Datoteke, večje od 10 MB: uporabite fileUrl
fileBody je omejen na 10 MB. Če je vaš izvoz stikov večji, gostujte datoteko na URL-ju, ki ga Brevo lahko pridobi, in posredujte tega:
body = { "fileUrl": "https://files.example.com/contacts/2026-04-30.csv", "listIds": [42], "updateExistingContacts": True,}Vse, kar je dosegljivo prek javnega HTTPS URL-ja, deluje: predpodpisani S3 URL-ji, GCS, vaše lastno statično gostovanje, celo GitHub raw URL za enkratne uvoze. Brevo pridobi datoteko z vašega URL-ja in nato izvede uvoz. Sprejete oblike: .csv, .txt, .json.
Pošljite JSON namesto CSV
Če že vlečete stike iz baze podatkov, vam ni treba iti skozi CSV. Pošljite jih kot JSON neposredno:
body = { "jsonBody": [ { "attributes": { "FIRSTNAME": "Jane", "LASTNAME": "Doe", "COMPANY": "Acme", }, }, { "attributes": { "FIRSTNAME": "John", "LASTNAME": "Smith", "COMPANY": "Globex", }, }, ], "listIds": [42],}Ista omejitev 10 MB. Isto asinhrono vedenje.
Preverjanje za dokončanje
Uvoz je asinhron. processId je vaš ročaj za sledenje. Obstaja ločen endpoint za preverjanje statusa procesa:
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}")Za dolgotrajne naloge je čistejši vzorec notifyUrl: posredujte HTTPS endpoint, na katerega bo Brevo poslal POST, ko se uvoz zaključi, in preskočite preverjanje.
body["notifyUrl"] = "https://your-app.example.com/webhooks/brevo-import"Pogoste napake in kako jih popraviti
400 Bad Request brez očitnega razloga. Skoraj vedno podpičja proti vejicam v CSV. Brevo uvoz pričakuje ;, ne ,. Dvakrat preverite fileBody po vašem koraku pretvorbe.
Vrednosti lastnih atributov izginejo. Atribut ne obstaja v vašem računu. Ustvarite ga pod Contacts → Settings → Contact attributes pred uvozom ali uporabite Attributes API, da ga ustvarite kot del vaše skripte.
401 Unauthorized. Napačno ime glave. Je api-key (male črke, vezaj), ne Authorization ali X-API-Key.
Uvoz je „uspel”, a se stiki niso pojavili na seznamu. Preverite, ali listIds vsebuje pravi seznam. In: če je updateExistingContacts nastavljen na false in stiki že obstajajo, jih Brevo tiho preskoči, namesto da bi jih ponovno dodal na seznam.
Nekaj vrstic je bilo uvoženih, druge ne. Brevo vam po koncu uvoza pošlje e-pošto s poročilom o napakah po vrsticah (razen če ste nastavili disableNotification: true). Poročilo vam pove, katere vrstice so imele slabe e-pošte, manjkajoča obvezna polja ali težave s formatiranjem.
Kdaj skriptirati in kdaj uporabiti vmesnik
Vmesnik je v redu za enkratne uvoze pod tisoč vrsticami. Skripta zmaga, takoj ko:
- Uvažate več kot enkrat (npr. tedenski izvoz iz vašega CRM)
- Izvorni podatki potrebujejo čiščenje, preden pristanejo v Brevo (deduplikacija, formatiranje telefonskih številk, deljenje polnih imen na ime in priimek)
- Želite, da teče po urniku, ne da bi kdorkoli klikal na gumbe
- Datoteka je večja od cone udobja vmesnika
Zavijte zgornjo skripto v cron opravilo ali GitHub Action in imate avtomatizirano sinhronizacijo stikov. Naslednji prispevek v seriji prikazuje, kako narediti isto stvar neposredno iz Google Sheet z Apps Script. Brez strežnika.