Brevo API: En praktisk guide til udviklere

Guide til Brevo API: autentificering, kontaktopdateringer, webhooks, rate limits og sikre grænser for gentagelser.

Brevo API

Hvad er det korte svar?

Brug https://api.brevo.com/v3/ med en api-key-header. Vælg et stabilt kilde-id, erklærede attributter og en tydelig liste til kontaktsynk, og bevar afmeldinger. Kontroller resultatet og rate-headere, begræns gentagelser efter 429, og behandl webhooks som autentificerede signaler, der kræver deduplikering og afstemning.

Læs mere
På denne side

En kontaktimport kan give 201 og stadig være forkert: kilde-id mangler, den forkerte liste er valgt, eller en tidligere afmelding er overset. Det er valg om dataansvar, ikke HTTP-detaljer.

Guiden får først et Brevo-kald til at virke og viser derefter kontrollerne til en lille, gentagelig kontaktsynk.

Hvad Brevo API dækker

Alt ligger under ét enkelt host og én versionssti. Udviklerdokumentationen opdeler fladen i fire produktområder:

  • Beskeder: transaktionel e-mail, SMS og WhatsApp, inklusive batchafsendelser, planlægning og beskedaktivitet.
  • Marketingplatform: kontakter, lister, segmenter og e-mail-kampagner.
  • eCommerce: produkter, ordrer og sporing af kundehændelser.
  • Conversations: chatwidgetten og programmatisk styring af samtaler.

De områder deler én konto, én kontaktdatabase og én API-nøgle. Det er praktisk og af og til farligt: et script skrevet ud fra en staging-forestilling om dataene taler med præcis de kontakter, dine kampagner sender til.

Transaktionel kontra marketing

De to familier opfører sig forskelligt nok til, at det er den mest almindelige designfejl at blande dem sammen.

TransaktionelMarketing
Primært endpointPOST /v3/smtp/emailPOST /v3/emailCampaigns
AdresseringEksplicitte modtagere i forespørgslenlistIds eller segmentIds
TriggerDin applikation, i realtidPlanlagt eller sendt på kommando
Typisk volumenformKontinuerlig, én besked ad gangenStødvis, én stor afsendelse
Rate limit-positionMeget høj, 1.000 forespørgsler i sekundet på det generelle trinLav, kampagne-endpoints falder ind under det generelle loft

Er du stadig i gang med at beslutte, om Brevo overhovedet er den rigtige platform, dækker platformsoverblikket det terræn.

Autentificering og nøglehåndtering

Brevo bruger en almindelig API-nøgle i en brugerdefineret header. Headeren hedder api-key, ikke Authorization, og der er intet Bearer-præfiks. Det snubler næsten alle over, som har brugt et andet beskeds-API først.

OAuth kan bruge et Bearer-token til understøttede handlinger; en almindelig API-nøgle sendes stadig i api-key.

Terminal window
curl https://api.brevo.com/v3/account \
-H "api-key: $BREVO_API_KEY"

Nøgler oprettes i Brevo-appen under kontoindstillinger, i afsnittet SMTP and API, på fanen API keys. Giv hver nøgle et sigende navn knyttet til det system, der bruger den. Nøgleværdien vises præcis én gang, når den oprettes, så mister du den, opretter du en ny i stedet for at genfinde den gamle.

Et par praktiske regler:

  • Udsted en separat nøgle pr. deployment-miljø og pr. service. At tilbagekalde en kompromitteret nøgle bør aldrig lægge tre urelaterede systemer ned.
  • Almindelige API-nøgler gælder hele kontoen. Betragt enhver nøgle som fuld adgang til kontakter, afsendelse og CRM-data.
  • Brevo understøtter også OAuth 2.0 til applikationer, der handler på vegne af andre Brevo-konti, beskrevet sammen med nøgleflowet i authentication schemes.
  • MCP-serveren, som AI-assistenter bruger, tager et separat token og bruger faktisk en bearer-header. Det token oprettes på den samme API keys-skærm, men kan ikke bruges i stedet for en REST-nøgle.

Base-URL, versionering og din første skrivning

Base-URL’en er https://api.brevo.com/v3/. Versionen ligger i stien frem for i en header, og v3 er den aktuelle generation. Alle stier i denne guide er relative til den base.

Til den første kontaktskrivning skal du bruge en testadresse, du styrer, et gyldigt liste-id og et stabilt kilde-id. Opret attributten FNAME i Brevo først. Med en rigtig nøgle skriver eksemplet direkte:

Terminal window
curl -X POST https://api.brevo.com/v3/contacts \
-H "api-key: $BREVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"ext_id": "test-source-contact-1",
"attributes": { "FNAME": "Dev" },
"listIds": [42],
"updateEnabled": true,
"getId": true
}'

Erstat 42 med id’et for din testliste. Læs kontakten igen og tjek id, navn, liste og blokeringer. Et 2xx alene beviser ikke det ønskede resultat.

De endpoints, du faktisk kommer til at bruge

Kontakter

POST /v3/contacts opretter en kontakt. Indholdet tager email, erklærede attributes, listIds og ext_id som stabil kildenøgle. updateEnabled: true opdaterer en eksisterende kontakt, og getId: true beder om det endelige id. Brevo dokumenterer felterne. Brug den samme ext_id hver gang, og gem forbindelsen mellem kilde-id og Brevo-id.

Afgør før skrivning hvilket system, der ejer hver attribut, og hvilken liste der modtager kontakter med samtykke. Angiv listIds udtrykkeligt. Sæt aldrig emailBlacklisted: false ved almindelige opdateringer. Brevo advarer om, at en adresseændring hos en blokeret kontakt fjerner blokeringen. Håndter den særskilt. Tjek blokeringer og afmeldinger før tilføjelse til en marketingliste. Mellem læsning og skrivning er der et kort tidsvindue; strenge krav kræver et sidste tjek før udsendelse.

Læsninger går gennem GET /v3/contacts, som pagineres med limit (standard 50, maksimum 1000) og offset, og understøtter modifiedSince og createdSince i UTC. Inkrementelle synkroniseringer bør læne sig op ad modifiedSince frem for at gennemløbe hele listen. Bemærk, at parameteren filter kun understøtter en lighedsoperator, så alt mere udtryksfuldt hører hjemme i et segment.

Til masseindlæsning accepterer POST /v3/contacts/import enten fileUrl, fileBody eller jsonBody, rammer listIds og kører asynkront med et processId som svar. Brevo dokumenterer en maksimal body på 10 MB og anbefaler at holde sig omkring 8 MB, fordi parsingen puster payloaden op. Angiv notifyUrl, så du får resultatet at vide i stedet for at polle.

Transaktionel e-mail

POST /v3/smtp/email er arbejdshesten. Ud over sender, to, subject og htmlContent er disse felter værd at kende:

  • templateId med params, som erstatter indbygget indhold med en Brevo-skabelon og dens variabelsubstitutioner. Params pr. version er begrænset til 100 KB, samlet til 1000 KB.
  • messageVersions, som sender personaliserede varianter i ét kald, med op til 99 modtagere pr. version.
  • tags kan hjælpe med at knytte leveringshændelser til den app-proces, der skabte dem.
  • scheduledAt plus batchId, til fremtidige afsendelser, du måske vil annullere samlet.
  • headers, i Title-Case, til brugerdefinerede SMTP-headere.

En enkelt forespørgsel accepterer højst 2.000 modtagere. Forskellen mellem dette endpoint og kampagneafsendelse ser du fra strategisiden i guiden til transaktionel e-mail.

E-mail-kampagner

POST /v3/emailCampaigns kræver name og sender plus præcis én indholdskilde: htmlContent (mindst 10 tegn, under 1 MB), htmlUrl eller templateId. Målgruppen sættes i recipients som listIds eller segmentIds, og scheduledAt bruger UTC-formatet YYYY-MM-DDTHH:mm:ss.SSSZ. Tilhørende ruter dækker afsendelse med det samme, testafsendelse, statusopdatering og udtræk af kampagnerapporten.

Virksomheder, deals og objekter

Brevos CRM har to overlappende skrivestier, og det betyder noget, at du vælger rigtigt.

CRM-ruterne er POST /v3/companies, PATCH /v3/companies/{id}, DELETE /v3/companies/{id} og det tilsvarende sæt til deals. De er synkrone. En PATCH returnerer 204, når ændringen er anvendt.

Objekt-API’et er bulkstien: POST /v3/objects/{object_type}/batch/upsert tager op til 1000 poster og 1 MB pr. forespørgsel, op til 500 attributter pr. post og op til 10 associationsposter pr. objekttype pr. post. Den returnerer 202 med et processId, hvilket betyder modtaget, ikke anvendt.

Terminal window
curl -X POST https://api.brevo.com/v3/objects/company/batch/upsert \
-H "api-key: $BREVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"identifiers": { "id": 12345 },
"attributes": { "domain": "acme.example", "industry": "retail" }
}
]
}'

Brevo CRM-guiden gennemgår objektmodellen fra operatørens side.

Officielle SDK’er

Brevo vedligeholder klienter under GitHub-organisationen getbrevo:

SprogRepository
Node.jsgithub.com/getbrevo/brevo-node
Pythongithub.com/getbrevo/brevo-python
PHPgithub.com/getbrevo/brevo-php
Javagithub.com/getbrevo/brevo-java
C#github.com/getbrevo/brevo-csharp
Gogithub.com/getbrevo/brevo-go
Rubygithub.com/getbrevo/brevo-ruby

Node-klienten installeres som @getbrevo/brevo:

Terminal window
npm install @getbrevo/brevo
import { BrevoClient } from "@getbrevo/brevo";
// Reconcile uncertain send outcomes before retrying.
const brevo = new BrevoClient({ apiKey: process.env.BREVO_API_KEY, maxRetries: 0 });
const result = await brevo.transactionalEmails.sendTransacEmail({
subject: "Order confirmed",
htmlContent: "<html><body><p>Thanks for your order.</p></body></html>",
sender: { name: "Acme", email: "[email protected]" },
to: [{ email: "[email protected]", name: "Customer" }],
tags: ["order-confirmation"],
});
console.log("Message ID:", result.messageId);

Python-klienten installeres med pip install brevo-python. Vil du hellere undgå en SDK-afhængighed for to endpoints, er den rå HTTP-flade lille nok til at kalde direkte, hvilket samtidig holder dig fri af SDK-versionsuro:

Python-klienten installeres med pip install brevo-python. Ved få endpoints kan du også kalde HTTP direkte:

import os
import requests
BASE = "https://api.brevo.com/v3"
HEADERS = {"api-key": os.environ["BREVO_API_KEY"]}
def upsert_consented_contact(source_id, email, first_name, list_id, consent):
if not consent:
raise ValueError("No marketing consent in the source")
if not source_id or not isinstance(list_id, int):
raise ValueError("Stable source ID and numeric list ID required")
# Configure FNAME in Brevo before using this explicit field mapping.
response = requests.post(
f"{BASE}/contacts",
headers=HEADERS,
json={
"email": email,
"ext_id": source_id,
"attributes": {"FNAME": first_name},
"listIds": [list_id],
"updateEnabled": True,
"getId": True,
},
timeout=30,
)
response.raise_for_status()
return response.json().get("id") if response.content else None

En vellykket opdatering kan give et tomt 204-svar. None betyder da, at du skal læse kontakten igen for at få id’et.

Eksemplet forudsætter, at kalderen allerede har kontrolleret samtykke og blokeringer i Brevo. Det beder ikke om at fjerne blokering. Med en rigtig nøgle skriver koden direkte; test først med simulerede svar. Identitetskonflikter kan give forskellige 4xx-koder. Læs svaret og afstem id’erne i stedet for altid at antage 409.

Webhooks

Webhooks er den måde, du finder ud af, hvad der skete efter en afsendelse. POST /v3/webhooks opretter en, med url, events, type og valgfrit channel (email eller sms), batched, brugerdefinerede headers og et auth-objekt.

Der er tre webhook-typer med hver sit hændelsesvokabular:

  • Transaktionel: sent, request, delivered, hardBounce, softBounce, blocked, spam, invalid, deferred, click, opened, uniqueOpened, unsubscribed.
  • Marketing: spam, opened, click, hardBounce, softBounce, unsubscribed, listAddition, delivered, contactUpdated, contactDeleted.
  • Indgående: inboundEmailProcessed og reply, som derudover kræver et domain.
Terminal window
curl -X POST https://api.brevo.com/v3/webhooks \
-H "api-key: $BREVO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.example/hooks/brevo",
"type": "transactional",
"events": ["delivered", "hardBounce", "spam", "unsubscribed"],
"description": "Deliverability signals"
}'

Registrer en marketingwebhook med contactUpdated for kontaktændringer. Brevo kalder hændelsen contact_updated i dataene. Autentificer modtageren med auth-bearertoken eller egne headere efter Brevos sikkerhedsguide. Kontroller hemmeligheden før behandling, og log den ikke.

Gem en deduplikeringsnøgle af hændelsestype, kontakt-id og tidsstempel længe nok til at dække gentagne leveringer. Tidsstemplet alene er ikke unikt. Hændelser kan leveres igen eller i forkert rækkefølge. Læs kontakten igen efter en hændelse og afstem med din autoritative kilde. Definér et replay-vindue, afvis gamle hændelser efter gendannelse, og lav regelmæssige inkrementelle kontroller. En webhook signalerer en ændring; alene giver den ikke tovejssynk. Forbindelsesguiden beskriver valgene.

Rate limits og fejlhåndtering

Brevos rate limits gælder pr. endpoint og pr. plantrin, og spredningen mellem endpoints er enorm.

EndpointGeneral (alle planer)Advanced (Professional og Enterprise)
POST /v3/smtp/email1.000 RPS2.000 RPS
POST /v3/transactionalSMS/send150 RPS200 RPS
/v3/contacts/...10 RPS, 36.000 RPH20 RPS, 72.000 RPH
POST /v3/events10 RPS, 36.000 RPH20 RPS, 72.000 RPH
GET /v3/smtp/emails2 RPS, 7.200 RPH3 RPS, 10.800 RPH
Endpoints uden deres egen grænse100 RPH200 RPH

Brevo dokumenterer x-sib-ratelimit-limit, x-sib-ratelimit-remaining og x-sib-ratelimit-reset for begrænsede endpoints. Læs dem også ved succes. Ved 429 venter du til nulstilling og gentager kun inden for faste grænser for antal forsøg og tid. Resetværdien er en varighed i tidsvinduets enhed, typisk sekunder, ikke et Unix-tidspunkt.

async function callBrevo(path, init) {
for (let attempt = 0; attempt < 3; attempt++) {
const response = await fetch(`https://api.brevo.com/v3${path}`, {
...init,
headers: { "api-key": process.env.BREVO_API_KEY, ...init.headers },
});
if (response.status !== 429 || attempt === 2) return response;
const raw = Number(response.headers.get("x-sib-ratelimit-reset"));
const seconds = Number.isFinite(raw) && raw > 0 ? raw : 2 ** attempt;
const delayMs = (seconds + 2 ** attempt) * 1000;
if (delayMs > 60_000) return response;
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}

Hvis den nødvendige ventetid overstiger 60 sekunder, returnerer funktionen 429. Planlæg et nyt forsøg senere.

Hjælpefunktionen er kun til kald, du har kontrolleret kan gentages sikkert. Efter en uklar sendefejl skal du afstemme besked-id, før du sender igen. Log status og rate-headere, aldrig API-nøgle eller kontaktdata.

Gentag ikke 4xx blindt. Reference til kontaktoprettelse nævner 400 og 425; konflikt betyder ikke nødvendigvis 409. Efter 5xx ved skrivning skal du tjekke, om ændringen allerede er sket.

Hvilken status kom tilbage?

  1. 429

    Vent inden for en grænse

    Brug resetvarigheden og stop efter få forsøg.

  2. 5xx efter skrivning

    Kontroller resultatet

    Serveren kan have skrevet før fejlen.

  3. 400

    Ret forespørgslen

    Den er ofte ugyldig.

  4. Identitetskonflikt

    Læs og afstem id’erne

    API’et lover ingen bestemt kode.

Test uden at sende mails

Tilføj headeren X-Sib-Sandbox med værdien drop til en transaktionel afsendelse. Brevo validerer forespørgslen, returnerer 201 med et messageId, leverer ingenting og skriver ingen e-maillog.

Terminal window
curl -X POST https://api.brevo.com/v3/smtp/email \
-H "api-key: $BREVO_API_KEY" \
-H "X-Sib-Sandbox: drop" \
-H "Content-Type: application/json" \
-d '{ "sender": { "email": "[email protected]" }, "to": [{ "email": "[email protected]" }], "subject": "Sandbox", "htmlContent": "<p>hi</p>" }'

Forstå, hvad det beviser, og hvad det ikke beviser. Sandbox-tilstand validerer kun forespørgslens format. Den siger intet om afsenderautentificering, skabelonrendering eller leveringsevne. Hold en separat Brevo-konto til integrationstest af alt, der rører kontakter eller CRM-data, for sandbox-tilstand dækker afsendelse og ikke resten af API’et.

Tjek før kontaktsynk

  • Vælg et stabilt kilde-id til ext_id, og gem det returnerede Brevo-id.
  • Kontroller attributter før skrivning. Brevo kan ignorere ukendte eller forkert typede felter; læs en testkontakt igen.
  • Brug en tydelig liste og pålidelig dokumentation for samtykke. Spring blokerede og afmeldte kontakter over.
  • Tæl modtagne, anvendte, oversprungne og fejlede poster hver for sig. 202 ved batch eller objekt betyder først kun modtaget.
  • Brug marketingwebhooks som signaler og afstem den aktuelle tilstand. Autentificer, dedupliker og begræns replay.
  • Overvåg rate-headere, og stop efter få forsøg.

Tajo fokuserer på at synkronisere handelsdata med Brevo. Hvis du bygger dette selv, sammenligner Brevo-forbindelsesguiden muligheder og fejl.

Ofte Stillede Spørgsmål

Hvad er base-URL'en til Brevo API?

Alle Brevo REST-kald går til https://api.brevo.com/v3/. Versionen er en del af stien, og v3 er den aktuelle generation, så et endpoint som transaktionel afsendelse har den fulde sti https://api.brevo.com/v3/smtp/email.

Hvordan autentificerer du dig mod Brevo API?

Du sender din nøgle i en HTTP-header ved navn api-key. Brevo bruger ikke en Authorization- eller Bearer-header til almindelige API-nøgler. Nøgler oprettes under kontoindstillinger, SMTP and API, API keys, og værdien vises kun én gang.

Hvad er rate limits i Brevo API?

Grænserne gælder pr. endpoint og pr. rate limit-trin. På det generelle trin, som alle planer får, tillader endpointet til transaktionel afsendelse 1.000 forespørgsler i sekundet, kontakt-endpoints tillader 10 i sekundet, og endpoints uden deres egen grænse er begrænset til 100 forespørgsler i timen. Professional- og Enterprise-planer kan bruge trinnet Advanced, og Enterprise trinnet Extended. Overskrider du en grænse, får du 429.

Har Brevo officielle SDK'er?

Ja. Brevo udgiver klienter til Node.js, Python, PHP, Java, C#, Go og Ruby under GitHub-organisationen getbrevo. Node-pakken hedder @getbrevo/brevo på npm, og Python-pakken hedder brevo-python på PyPI.

Hvordan tester jeg Brevo API uden at sende rigtige e-mails?

Tilføj headeren X-Sib-Sandbox med værdien drop til en transaktionel afsendelse. Brevo validerer forespørgslen, returnerer 201 med et messageId, sender ingenting og skriver ingen e-maillog. Den tjekker kun forespørgslens format, ikke leveringsevnen.

Hvilke webhook-events understøtter Brevo?

Transaktionelle webhooks dækker blandt andet levering, bounce og afmelding. Marketingwebhooks omfatter contactUpdated og contactDeleted. For indgående hændelser dokumenterer Brevo inboundEmailProcessed.

Hvordan beskytter en kontaktopdatering en tidligere afmelding?

Brug et stabilt kilde-id og erklærede attributter. Sæt ikke emailBlacklisted til false ved almindelige opdateringer. Kontroller kontakten og samtykkekilden, før du føjer den til en marketingliste.

Er en webhook nok til tovejssynkronisering?

Nej. Autentificer modtageren, fjern dublerede leveringer og afstem manglende eller omordnede hændelser mod en autoritativ kilde. En webhook varsler om en ændring, men beviser ikke at systemerne er enige.

Bed om tidlig adgang til Tajo

Indtast dit fornavn og din arbejds-e-mailadresse. Vi sender dig et link til at bekræfte din anmodning om adgang til Tajo.

Få Brevo