På denna sida
En kontaktimport kan ge 201 och ändå vara fel: käll-ID har tappats, fel lista valts eller en tidigare avregistrering förbisetts. Det handlar om dataansvar, inte HTTP-detaljer.
Guiden visar ett fungerande Brevo-anrop och sedan kontrollerna för en liten, upprepningsbar kontaktsynk.
Vad Brevos API täcker
Allt ligger under en enda värd och en enda versionssökväg. Utvecklardokumentationen grupperar ytan i fyra produktområden:
- Meddelanden: transaktionell e-post, SMS och WhatsApp, inklusive batchsändningar, schemaläggning och meddelandeaktivitet.
- Marknadsföringsplattform: kontakter, listor, segment och e-postkampanjer.
- E-handel: produkter, ordrar och spårning av kundhändelser.
- Konversationer: chattwidgeten och programmatisk hantering av konversationer.
Områdena delar ett konto, en kontaktdatabas och en API-nyckel. Det är bekvämt och ibland farligt: ett skript som skrivits utifrån en föreställning om testdata pratar med samma kontakter som dina kampanjer går ut till.
Transaktionellt kontra marknadsföring
De två familjerna beter sig så olika att förväxla dem är det vanligaste designfelet.
| Transaktionellt | Marknadsföring | |
|---|---|---|
| Primär slutpunkt | POST /v3/smtp/email | POST /v3/emailCampaigns |
| Adressering | Explicita mottagare i anropet | listIds eller segmentIds |
| Utlösare | Din applikation, i realtid | Schemalagt eller skickat på begäran |
| Typisk volymform | Kontinuerlig, ett meddelande i taget | Stötvis, en stor sändning |
| Hastighetsgräns | Mycket hög, 1 000 anrop per sekund på den generella nivån | Låg, kampanjslutpunkter faller under det generella taket |
Om du fortfarande funderar på om Brevo är rätt plattform över huvud taget täcker plattformsöversikten det området.
Autentisering och nyckelhantering
Brevo använder en vanlig API-nyckel i en egen header. Headern heter api-key, inte Authorization, och det finns inget Bearer-prefix. Det snubblar nästan alla på som har använt ett annat meddelande-API först.
OAuth kan använda en Bearer-token för åtgärder som stöds; en vanlig API-nyckel ska fortfarande skickas i api-key.
curl https://api.brevo.com/v3/account \ -H "api-key: $BREVO_API_KEY"Nycklar skapas i Brevo-appen under kontoinställningar, i avsnittet SMTP and API, på fliken API keys. Ge varje nyckel ett beskrivande namn kopplat till systemet som använder den. Nyckelvärdet visas exakt en gång när det skapas, så om du tappar bort det skapar du en ny nyckel i stället för att återställa den gamla.
Några praktiska regler:
- Skapa en egen nyckel per driftsmiljö och per tjänst. Att återkalla en komprometterad nyckel ska aldrig slå ut tre orelaterade system.
- Vanliga API-nycklar gäller hela kontot. Behandla varje nyckel som full åtkomst till kontakter, sändning och CRM-data.
- Brevo stöder även OAuth 2.0 för applikationer som agerar för andra Brevo-kontos räkning, beskrivet vid sidan av nyckelflödet i authentication schemes.
- MCP-servern som AI-assistenter använder tar en separat token och använder faktiskt en bearer-header. Den token skapas i samma API keys-vy men går inte att byta mot en REST-nyckel.
Bas-URL, versionshantering och din första skrivning
Bas-URL är https://api.brevo.com/v3/. Versionen ligger i sökvägen i stället för i en header, och v3 är den aktuella generationen. Varje sökväg i den här guiden är relativ till den basen.
Använd för den första kontaktskrivningen en testadress du kontrollerar, ett riktigt list-ID och ett stabilt käll-ID. Skapa först attributet FNAME i Brevo. Med riktig nyckel skriver exemplet live:
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 }'Byt 42 till ditt testlist-ID. Läs tillbaka kontakten och kontrollera ID, namn, lista och blockeringar. Enbart 2xx bevisar inte önskad synk.
Slutpunkterna du faktiskt kommer att använda
Kontakter
POST /v3/contacts skapar en kontakt. Innehållet tar email, deklarerade attributes, listIds och ext_id som stabil källnyckel. updateEnabled: true uppdaterar en befintlig kontakt och getId: true begär dess slutliga ID. Brevo dokumenterar fälten. Använd samma ext_id varje gång och spara kopplingen mellan käll-ID och Brevo-ID för avstämning.
Bestäm före skrivning vilket system som äger varje attribut och vilken lista som ska få kontakter med samtycke. Ange listIds uttryckligen. Sätt aldrig emailBlacklisted: false vid vanliga uppdateringar. Brevo varnar för att en ändrad adress på en blockerad kontakt häver blockeringen. Hantera det separat. Kontrollera blockeringar och avregistreringar före tillägg till en marknadsföringslista. Det finns fortfarande ett tidsfönster mellan läsning och skrivning; vid strikta krav behövs en sista kontroll före utskick.
Läsningar går via GET /v3/contacts, som paginerar med limit (standard 50, max 1000) och offset, och stöder modifiedSince och createdSince i UTC. Inkrementella synkroniseringar bör luta sig mot modifiedSince i stället för att gå igenom hela listan. Observera att parametern filter bara stöder likhetsoperatorn, så allt mer uttrycksfullt hör hemma i ett segment.
För massinläsning tar POST /v3/contacts/import emot fileUrl, fileBody eller jsonBody, riktar sig mot listIds och körs asynkront med ett processId i svaret. Brevo dokumenterar en maxgräns på 10 MB och rekommenderar att du håller dig runt 8 MB, eftersom tolkningen blåser upp nyttolasten. Ange notifyUrl så att du får veta utfallet i stället för att polla.
Transaktionell e-post
POST /v3/smtp/email är arbetshästen. Utöver sender, to, subject och htmlContent är dessa fält värda att känna till:
templateIdmedparams, som byter ut inbäddat innehåll mot en Brevo-mall och dess variabelsubstitutioner. Enskilda versionsparametrar är begränsade till 100 KB, kumulativa parametrar till 1000 KB.messageVersions, som skickar personaliserade varianter i ett anrop, med upp till 99 mottagare per version.tagskan hjälpa dig koppla leveranshändelser till arbetsflödet i appen som skapade dem.scheduledAtplusbatchId, för framtida sändningar du kanske vill avbryta som en grupp.headers, i Title-Case, för egna SMTP-headers.
Ett enskilt anrop tar emot högst 2 000 mottagare. För skillnaden mellan den här slutpunkten och kampanjsändning har guiden om transaktionell e-post det strategiska perspektivet.
E-postkampanjer
POST /v3/emailCampaigns kräver name och sender, plus exakt en innehållskälla: htmlContent (minst 10 tecken, under 1 MB), htmlUrl eller templateId. Målgruppen anges i recipients som listIds eller segmentIds, och scheduledAt använder UTC-formatet YYYY-MM-DDTHH:mm:ss.SSSZ. Kompletterande rutter täcker omedelbar sändning, testsändning, statusuppdatering och hämtning av kampanjrapporten.
Företag, affärer och objekt
Brevos CRM har två överlappande skrivvägar, och att välja rätt spelar roll.
CRM-rutterna är POST /v3/companies, PATCH /v3/companies/{id}, DELETE /v3/companies/{id} och motsvarande uppsättning för affärer. De är synkrona. En PATCH svarar 204 när ändringen är tillämpad.
Objekt-API:et är massvägen: POST /v3/objects/{object_type}/batch/upsert tar upp till 1000 poster och 1 MB per anrop, upp till 500 attribut per post och upp till 10 associationsposter per objekttyp och post. Det svarar 202 med ett processId, vilket betyder mottaget snarare än tillämpat.
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" } } ] }'Guiden till Brevo CRM täcker objektmodellen från operatörens sida.
Officiella SDK:er
Brevo underhåller klienter under GitHub-organisationen getbrevo:
| Språk | Repository |
|---|---|
| Node.js | github.com/getbrevo/brevo-node |
| Python | github.com/getbrevo/brevo-python |
| PHP | github.com/getbrevo/brevo-php |
| Java | github.com/getbrevo/brevo-java |
| C# | github.com/getbrevo/brevo-csharp |
| Go | github.com/getbrevo/brevo-go |
| Ruby | github.com/getbrevo/brevo-ruby |
Node-klienten installeras som @getbrevo/brevo:
npm install @getbrevo/brevoimport { 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>", tags: ["order-confirmation"],});
console.log("Message ID:", result.messageId);Python-klienten installeras med pip install brevo-python. Om du hellre slipper bära ett SDK-beroende för två slutpunkter är den råa HTTP-ytan liten nog att anropa direkt, vilket också skyddar dig mot versionsstök i SDK:erna:
Python-klienten installeras med pip install brevo-python. För få slutpunkter kan du även anropa HTTP direkt:
import osimport 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 NoneEn lyckad uppdatering kan ge ett tomt 204-svar. None betyder då att du ska läsa kontakten igen för att få dess ID.
Exemplet förutsätter att anroparen redan kontrollerat samtycke och Brevo-blockeringar. Det begär ingen avblockering. Med riktig nyckel skriver koden live; testa först med mockar. Identitetskonflikter kan ge olika 4xx-koder. Läs svaret och stäm av ID:n, förutsätt inte alltid 409.
Webhooks
Webhooks är hur du får veta vad som hände efter en sändning. POST /v3/webhooks skapar en, med url, events, type och valfritt channel (email eller sms), batched, egna headers och ett auth-objekt.
Det finns tre typer av webhooks med skilda händelsevokabulärer:
- Transaktionella:
sent,request,delivered,hardBounce,softBounce,blocked,spam,invalid,deferred,click,opened,uniqueOpened,unsubscribed. - Marknadsföring:
spam,opened,click,hardBounce,softBounce,unsubscribed,listAddition,delivered,contactUpdated,contactDeleted. - Inkommande:
inboundEmailProcessedochreply, som dessutom kräver endomain.
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" }'Registrera en marknadsföringswebhook med contactUpdated för kontaktändringar. Brevo kallar händelsen contact_updated i meddelandet. Autentisera mottagaren med auth-bearertoken eller egna headers enligt Brevos säkerhetsguide. Kontrollera hemligheten före behandling och logga den inte.
Spara en dedupliceringsnyckel av händelsetyp, kontakt-ID och tidsstämpel så länge omleveranser kan ske. En tidsstämpel ensam är inte unik. Leveranser kan upprepas eller komma i fel ordning. Läs den aktuella kontakten efter en händelse och stäm av mot din auktoritativa källa. Definiera ett uppspelningsfönster, avvisa gamla händelser efter återställning och gör regelbundna inkrementella kontroller. En webhook signalerar ändring; den skapar inte ensam tvåvägssynk. Anslutningsguiden går igenom valet.
Hastighetsgränser och felhantering
Brevos hastighetsgränser gäller per slutpunkt och per plannivå, och spridningen mellan slutpunkter är enorm.
| Slutpunkt | General (alla planer) | Advanced (Professional och Enterprise) |
|---|---|---|
POST /v3/smtp/email | 1 000 RPS | 2 000 RPS |
POST /v3/transactionalSMS/send | 150 RPS | 200 RPS |
/v3/contacts/... | 10 RPS, 36 000 RPH | 20 RPS, 72 000 RPH |
POST /v3/events | 10 RPS, 36 000 RPH | 20 RPS, 72 000 RPH |
GET /v3/smtp/emails | 2 RPS, 7 200 RPH | 3 RPS, 10 800 RPH |
| Slutpunkter utan egen gräns | 100 RPH | 200 RPH |
Brevo dokumenterar x-sib-ratelimit-limit, x-sib-ratelimit-remaining och x-sib-ratelimit-reset för begränsade slutpunkter. Läs dem även efter lyckade anrop. Vid 429, vänta på återställning och försök bara igen inom fasta gränser för antal försök och väntetid. Resetvärdet är en varaktighet i tidsfönstrets enhet, oftast sekunder, inte Unix-tid.
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)); }}Om den väntetid som krävs överstiger 60 sekunder returnerar funktionen 429. Schemalägg ett nytt försök senare.
Hjälpfunktionen gäller bara anrop som du kontrollerat kan upprepas säkert. Vid tvetydigt utskicksfel, stäm först av ditt meddelande-ID innan du skickar igen. Logga status och gränsheaders, inte API-nyckeln eller kontaktdata.
Försök inte blint igen vid 4xx. Referensen för kontaktskapande nämner 400 och 425; identitetskonflikt behöver inte ge 409. Efter 5xx vid skrivning, kontrollera om ändringen redan gjordes.
Vilken status kom tillbaka?
-
429
Vänta inom en gräns
Använd återställningstiden och sluta efter några försök.
-
5xx efter skrivning
Kontrollera resultatet
Servern kan ha skrivit före felet.
-
400
Rätta anropet
Begäran är ofta felaktig.
-
Identitetskonflikt
Läs och stäm av ID:n
API:et lovar ingen viss konfliktkod.
Testa utan att skicka e-post
Lägg till headern X-Sib-Sandbox med värdet drop i en transaktionell sändning. Brevo validerar anropet, svarar 201 med ett messageId, levererar ingenting och skriver ingen e-postlogg.
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>" }'Förstå vad detta bevisar och inte bevisar. Sandbox-läget validerar bara anropets format. Det säger ingenting om avsändarautentisering, mallrendering eller leveransbarhet. Ha ett separat Brevo-konto för integrationstester av allt som rör kontakter eller CRM-data, eftersom sandbox-läget täcker sändning och inte resten av API:et.
Kontrollera före kontaktsynk
- Välj ett stabilt käll-ID för
ext_idoch spara Brevo-ID:t som returneras. - Verifiera attribut före skrivning. Brevo kan ignorera okända eller feltypade fält; läs tillbaka en testkontakt.
- Använd ett tydligt list-ID och ett tillförlitligt samtyckesbevis. Hoppa över blockeringar och avregistreringar.
- Räkna mottagna, tillämpade, överhoppade och misslyckade poster separat. 202 för batch eller objekt bekräftar först bara mottagandet.
- Använd marknadsföringswebhooks som signaler och stäm av aktuell status. Autentisera, deduplicera och begränsa uppspelning.
- Följ gränsheaders och sluta efter några försök.
Tajo fokuserar på att synka handelsdata med Brevo. Om du bygger delen själv jämför Brevos anslutningsguide vägar och fel.
Vanliga Frågor
Vad är bas-URL för Brevos API?
Alla REST-anrop till Brevo går till https://api.brevo.com/v3/. Versionen ingår i sökvägen, och v3 är den aktuella generationen, så en slutpunkt som transaktionell sändning har den fullständiga sökvägen https://api.brevo.com/v3/smtp/email.
Hur autentiserar du mot Brevos API?
Skicka din nyckel i en HTTP-header som heter api-key. Brevo använder inte en Authorization- eller Bearer-header för vanliga API-nycklar. Nycklar skapas under kontoinställningar, SMTP and API, API keys, och värdet visas bara en gång.
Vilka hastighetsgränser gäller för Brevos API?
Gränserna sätts per slutpunkt och per nivå för hastighetsgränser. På den generella nivån, som alla planer får, tillåter slutpunkten för transaktionell sändning 1 000 anrop per sekund, kontaktslutpunkterna 10 per sekund, och slutpunkter utan egen gräns är begränsade till 100 anrop per timme. Professional och Enterprise kan använda nivån Advanced, och Enterprise nivån Extended. Om du överskrider en gräns får du 429.
Har Brevo officiella SDK:er?
Ja. Brevo publicerar klienter för Node.js, Python, PHP, Java, C#, Go och Ruby under GitHub-organisationen getbrevo. Node-paketet heter @getbrevo/brevo på npm och Python-paketet heter brevo-python på PyPI.
Hur testar jag Brevos API utan att skicka riktig e-post?
Lägg till headern X-Sib-Sandbox med värdet drop i en transaktionell sändning. Brevo validerar anropet, svarar 201 med ett messageId, skickar ingenting och skriver ingen e-postlogg. Det kontrollerar bara anropets format, inte leveransbarheten.
Vilka webhook-händelser stöder Brevo?
Transactionella webhooks täcker bland annat leverans, studs och avregistrering. Marknadsföringswebhooks omfattar contactUpdated och contactDeleted. För inkommande händelser dokumenterar Brevo inboundEmailProcessed.
Hur skyddar en kontaktuppdatering en tidigare avregistrering?
Använd ett stabilt käll-ID och deklarerade attribut. Sätt inte emailBlacklisted till false i vanliga uppdateringar. Kontrollera kontakten och samtyckeskällan innan du lägger den till en marknadsföringslista.
Räcker en webhook för tvåvägssynk?
Nej. Autentisera mottagaren, ta bort dubbla leveranser och stäm av missade eller oordnade händelser mot en auktoritativ källa. En webhook signalerar förändring men bevisar inte att systemen är överens.