På denne siden
- Endepunktet i et øyekast
- Hent en API-nøkkel
- Python: les en CSV, send den til Brevo
- Excel-filer: tre brukbare veier
- Node.js: samme jobb, offisiell SDK
- cURL: en one-liner for ad-hoc-importer
- Filer større enn 10 MB: bruk fileUrl
- Send JSON i stedet for CSV
- Polling for ferdigstillelse
- Vanlige feil og hvordan fikse dem
- Når skal du skrive skript vs bruke UI
- Videre lesning
Illustrasjon · eksempeldata
Eksempel på synkronisering
Kilde
CSV
Koblingsstatus: Eget verktøy
Mål
Brevo
Koblingsstatus: Aktiv
Feltkobling
| Kildefelt | Målfelt | Eksempelverdi |
|---|---|---|
EMAIL | EMAIL | [email protected] |
FIRSTNAME | FIRSTNAME | Alex |
LASTNAME | LASTNAME | Example |
- Utkast
- Se gjennom én oppføring
- Godkjenn denne versjonen
Status gjelder hver enkelt kobling og garanterer ikke at denne synkroniseringen er klar. Feltene er illustrative. Kontroller faktisk skjema og tillatelser før synkroniseringen kjører.
Hvis du noen gang har trengt å sende noen tusen kontakter fra et regneark inn i Brevo, blir den manuelle UI-veien fort slitsom: velg filen, mapp kolonner, velg en liste, vent, gjenta. Et skript gjør samme jobb på sekunder, og (viktigere) du kan kjøre det på nytt etter en tidsplan, etter en database-eksport, eller når CRM-en din spytter ut en fersk CSV.
Denne guiden dekker API-endepunktet Brevo gir deg for nøyaktig dette, med fullt fungerende skript i Python, Node.js, og en cURL-one-liner. Alt i denne guiden treffer POST /v3/contacts/import.
Endepunktet i et øyekast
POST https://api.brevo.com/v3/contacts/importContent-Type: application/jsonapi-key: YOUR_API_KEY
{ "listIds": [42], "updateExistingContacts": true, "emailBlacklist": false, "smsBlacklist": false}Responsen kommer raskt:
{ "processId": 78 }Det er en 202 Accepted, Brevo har akseptert importen og prosesserer den i bakgrunnen. processId er ditt sporingshåndtak hvis du vil polle for ferdigstillelse eller sette opp en notifyUrl-webhook.
Noen ting verdt å merke seg før du skriver kode:
- Body kan være CSV (
fileBody), JSON (jsonBody), eller en ekstern URL (fileUrl). Velg én. CSV-formen bruker semikolon (;) for å skille kolonner, ikke komma, det er en vanlig felle. fileBodyogjsonBodyer begrenset til 10 MB. Brevo anbefaler å holde seg rundt 8 MB for å være på den sikre siden. For noe større, last opp filen til S3, GCS, eller hvilken som helst HTTPS-host og sendfileUrli stedet.- Egendefinerte attributter som ikke finnes i kontoen din blir stille ignorert. Opprett dem i Brevos UI (eller via Attributes API) før du importerer rader som bruker dem, ellers forsvinner dataen bare.
updateExistingContactser som standardtrue. Hvis du setter den tilfalse, hopper Brevo over kontakter hvis e-post allerede finnes, nyttig for “legg bare til nye”-jobber.emptyContactsAttributesstyrer om tomme celler i CSV-en din sletter eksisterende verdier. Standardfalse(tomme celler ignoreres). Sett tiltruehvis CSV-en er sannhetskilden og du vil at blanke skal fjerne utdatert data.
Hent en API-nøkkel
Logg inn på Brevo -> Settings -> SMTP & API -> API Keys -> opprett en ny nøkkel. Den ser ut som xkeysib-.... Du sender den som api-key HTTP-header på hver forespørsel. Behandle den som et passord, den har full lese/skrive-tilgang på kontoen din.
Et rent mønster: legg den i en miljøvariabel slik at den aldri havner i kildetreet ditt.
export BREVO_API_KEY="xkeysib-..."Python: les en CSV, send den til Brevo
Dette er det enklest mulige skriptet: les en lokal CSV med standardbiblioteket, send body-en rett til Brevo. Ingen tredjeparts-SDK nødvendig utover 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}")Kjør det:
python import_csv_to_brevo.py contacts.csvCSV-ens første rad er headeren. Kolonnenavn mappes til Brevo-attributter med store bokstaver, eksakt match: EMAIL, FIRSTNAME, LASTNAME, pluss eventuelle egendefinerte attributter du har definert. EMAIL er obligatorisk.
EMAIL,FIRSTNAME,LASTNAME,COMPANY,CITYDet er hele flyten. Skriptet returnerer innen et sekund; selve importen kjører serverside og tar fra noen sekunder til noen minutter avhengig av volum.
Excel-filer: tre brukbare veier
Brevos import-endepunkt leser ikke .xlsx direkte, så du har tre reelle alternativer avhengig av hvor jobben må leve:
- Kjør en VBA-makro inne i arbeidsboken, ett-klikks synkronisering fra Excel selv, ingen ekstern skript. Dette er riktig svar når filen lever på en stasjonær PC og teamet ditt vil ha en knapp på arket. Full kode i Excel-til-Brevo VBA-makroguiden.
- Office Scripts + Power Automate, hvis arbeidsboken ligger i OneDrive/SharePoint og du vil ha uovervåket planlagt synkronisering. Også dekket i Excel-guiden.
- Konverter
.xlsxtil CSV fra et skript, det resten av denne seksjonen dekker. Best hvis du allerede kjører Python eller Node på en server og bare trenger å hente en arbeidsbok inn én gang om dagen.
For alternativ 3, gjør pandas det til en one-liner:
# 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")Hvis du ikke vil ha pandas som avhengighet, fungerer openpyxl alene:
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: samme jobb, offisiell SDK
Brevo publiserer @getbrevo/brevo for Node. Den håndterer auth, retries og typet forespørselsform:
// 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}`);Eller, hvis du ikke vil ha SDK-en, fungerer vanlig fetch på samme måte:
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: en one-liner for ad-hoc-importer
Når du bare vil teste endepunktet eller dytte en liten fil inn for hånd:
# 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 . sluker hele filen og JSON-escaper den, sparer deg fra å måtte escape newlines og quotes manuelt.
Filer større enn 10 MB: bruk fileUrl
fileBody er begrenset til 10 MB. Hvis kontakteksporten din er større, host filen på en URL Brevo kan hente og send den:
body = { "fileUrl": "https://files.example.com/contacts/2026-04-30.csv", "listIds": [42], "updateExistingContacts": True,}Alt som kan nås via en offentlig HTTPS-URL fungerer, pre-signerte S3-URL-er, GCS, din egen statiske host, til og med en GitHub raw-URL for engangsimporter. Brevo henter filen fra URL-en din, så kjører importen. Aksepterte formater: .csv, .txt, .json.
Send JSON i stedet for CSV
Hvis du allerede henter kontakter fra en database, trenger du ikke gå via CSV, send dem som JSON direkte:
body = { "jsonBody": [ { "attributes": { "FIRSTNAME": "Jane", "LASTNAME": "Doe", "COMPANY": "Acme", }, }, { "attributes": { "FIRSTNAME": "John", "LASTNAME": "Smith", "COMPANY": "Globex", }, }, ], "listIds": [42],}Samme 10 MB-tak. Samme async-oppførsel.
Polling for ferdigstillelse
Importen er asynkron, processId er håndtaket ditt for å spore den. Det er et eget endepunkt for å sjekke prosess-status:
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}")For lange jobber er det renere mønsteret notifyUrl: send en HTTPS-endepunkt Brevo POSTer til når importen er ferdig, og hopp over pollingen.
body["notifyUrl"] = "https://your-app.example.com/webhooks/brevo-import"Vanlige feil og hvordan fikse dem
400 Bad Request uten åpenbar årsak. Nesten alltid semikolon vs komma i CSV-en. Brevos import forventer ;, ikke ,. Dobbeltsjekk fileBody etter konverteringssteget ditt.
Verdier for egendefinerte attributter forsvinner. Attributtet finnes ikke i kontoen din. Opprett det under Contacts -> Settings -> Contact attributes før import, eller bruk Attributes API-et for å opprette det som del av skriptet ditt.
401 Unauthorized. Feil header-navn. Det er api-key (små bokstaver, bindestrek), ikke Authorization eller X-API-Key.
Importen “lyktes” men kontaktene dukket ikke opp i listen. Sjekk at listIds inneholder riktig liste. Også: hvis updateExistingContacts er false og kontaktene allerede finnes, hopper Brevo stille over dem i stedet for å legge dem til på listen igjen.
Noen rader importerte, noen ikke. Brevo sender deg en e-post med en feilrapport per rad etter at importen er ferdig (med mindre du setter disableNotification: true). Rapporten forteller deg hvilke rader som hadde dårlige e-poster, manglende påkrevde felt eller formateringsproblemer.
Når skal du skrive skript vs bruke UI
UI-et fungerer fint for engangsimporter under tusen rader. Et skript vinner så snart:
- Du importerer mer enn én gang (f.eks. ukentlig eksport fra CRM-en din)
- Kildedataen trenger rensing før den lander i Brevo (deduplisering, formatering av telefonnumre, splitte fulle navn til fornavn/etternavn)
- Du vil at den skal kjøre etter en tidsplan uten at noen klikker knapper
- Filen er større enn UI-ets komfortsone
Pakk skriptet over i en cron-jobb eller en GitHub Action og du har automatisert kontaktsynkronisering. Neste innlegg i denne serien viser hvordan du gjør det samme rett fra et Google Sheet med Apps Script, ingen server nødvendig.
Videre lesning
Ofte Stilte Spørsmål
Hva er Brevos API-endepunkt for bulk-import av kontakter?
POST https://api.brevo.com/v3/contacts/import. Det aksepterer CSV-innhold (fileBody), en ekstern fil-URL (fileUrl), eller et JSON-array (jsonBody). Endepunktet er asynkront, det returnerer en processId umiddelbart og fullfører importen i bakgrunnen.
Hva er maksimal filstørrelse?
10 MB for inline CSV (fileBody) eller JSON (jsonBody). For større filer, host filen et sted som er tilgjengelig og send URL-en via fileUrl i stedet, den banen har ingen dokumentert størrelsesbegrensning.
Hvordan importerer jeg en .xlsx-fil?
Brevos import-API tar bare .csv, .txt eller .json. Konverter .xlsx til .csv først, pandas, openpyxl, eller LibreOffice headless kan gjøre det på én linje. Skriptet i denne guiden inkluderer en xlsx til csv-konvertering.
Vil det overskrive eksisterende kontakter?
Som standard, ja, updateExistingContacts er som standard true og matcher på e-post. Sett den til false for å hoppe over kontakter som allerede finnes. Sett emptyContactsAttributes til true hvis du vil at tomme CSV-celler skal slette eksisterende verdier (ellers ignoreres tomme celler).