Brevo API: ghid practic pentru dezvoltatori

Ghid Brevo API: autentificare, actualizarea contactelor, webhook-uri, limite de rată și reluări sigure.

Brevo API

Care este răspunsul scurt?

Folosește https://api.brevo.com/v3/ cu antetul api-key. Pentru sincronizarea contactelor alege un ID sursă stabil, atribute declarate și o listă explicită, păstrând dezabonările. Verifică rezultatul și antetele de limită, restrânge reluările după 429 și tratează webhook-urile ca semnale autentificate ce cer deduplicare și reconciliere.

Află mai mult
Pe această pagină

Un import de contact poate întoarce 201 și totuși să fie greșit: ID-ul sursă s-a pierdut, lista este greșită sau o dezabonare a fost ignorată. Sunt decizii despre date, nu detalii HTTP.

Ghidul pornește cu o cerere Brevo funcțională și continuă cu verificările pentru o sincronizare mică, repetabilă.

Ce acoperă Brevo API

Totul stă sub o singură gazdă și o singură cale de versiune. Documentația pentru dezvoltatori grupează suprafața în patru zone de produs:

  • Mesagerie: e-mail tranzacțional, SMS și WhatsApp, inclusiv trimiteri în lot, programare și activitatea mesajelor.
  • Platformă de marketing: contacte, liste, segmente și campanii de e-mail.
  • eCommerce: produse, comenzi și urmărirea evenimentelor clienților.
  • Conversations: widgetul de chat și gestionarea programatică a conversațiilor.

Aceste zone împart un singur cont, o singură bază de date de contacte și o singură cheie API. Este convenabil și, ocazional, periculos: un script scris pornind de la o idee de staging despre date vorbește cu aceleași contacte către care trimit campaniile tale.

Tranzacțional față de marketing

Cele două familii se comportă suficient de diferit încât confundarea lor este cea mai frecventă eroare de proiectare.

TranzacționalMarketing
Endpoint principalPOST /v3/smtp/emailPOST /v3/emailCampaigns
AdresareDestinatari expliciți în cererelistIds sau segmentIds
DeclanșatorAplicația ta, în timp realProgramat sau trimis la cerere
Forma tipică a volumuluiContinuu, câte un mesaj o datăÎn valuri, o singură trimitere mare
Poziția față de limita de ratăFoarte ridicată, 1.000 de cereri pe secundă pe nivelul generalScăzută, endpointurile de campanii intră sub plafonul general

Dacă încă decizi dacă Brevo este platforma potrivită, prezentarea generală a platformei acoperă acel teren.

Autentificare și gestionarea cheilor

Brevo folosește o cheie API simplă într-un antet propriu. Antetul se numește api-key, nu Authorization, și nu există niciun prefix Bearer. Asta încurcă aproape pe oricine a folosit mai întâi un alt API de mesagerie.

OAuth poate folosi un token Bearer pentru operațiunile acceptate; o cheie API standard se trimite în antetul api-key.

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

Cheile se generează în aplicația Brevo, în setările contului, în secțiunea SMTP and API, pe fila API keys. Dă fiecărei chei un nume descriptiv legat de sistemul care o folosește. Valoarea cheii este afișată exact o singură dată, la generare, deci dacă o pierzi generezi una nouă în loc să o recuperezi pe cea veche.

Câteva reguli practice:

  • Emite o cheie separată pentru fiecare mediu de implementare și pentru fiecare serviciu. Revocarea unei chei compromise nu ar trebui niciodată să pice trei sisteme fără legătură între ele.
  • Cheile API standard sunt valabile la nivel de cont. Tratează orice cheie ca acces complet la contacte, trimitere și date CRM.
  • Brevo acceptă și OAuth 2.0 pentru aplicațiile care acționează în numele altor conturi Brevo, descris alături de fluxul cu chei în schemele de autentificare.
  • Serverul MCP folosit de asistenții AI ia un token separat și chiar folosește un antet bearer. Tokenul se generează din același ecran de chei API, dar nu este interschimbabil cu o cheie REST.

URL de bază, versionare și prima ta scriere

URL-ul de bază este https://api.brevo.com/v3/. Versiunea stă în cale, nu într-un antet, iar v3 este generația curentă. Fiecare cale din acest ghid este relativă la acea bază.

Pentru prima scriere de contact folosește o adresă de test controlată de tine, un ID de listă real și un ID sursă stabil. Creează mai întâi atributul FNAME în Brevo. Cu o cheie reală, exemplul scrie în cont:

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
}'

Înlocuiește 42 cu ID-ul listei de test. Recitește contactul și verifică ID-ul, numele, lista și blocările. Un 2xx singur nu dovedește rezultatul dorit.

Endpointurile pe care chiar le vei folosi

Contacte

POST /v3/contacts creează un contact. Corpul acceptă email, attributes declarate, listIds și ext_id ca identificator sursă stabil. updateEnabled: true actualizează un contact existent, iar getId: true solicită ID-ul rezultat. Brevo documentează aceste câmpuri. Refolosește același ext_id la fiecare rulare și păstrează legătura dintre ID-ul sursă și cel Brevo.

Înainte de scriere, decide ce sistem deține fiecare atribut și ce listă primește contactele cu consimțământ. Specifică listIds explicit. Nu seta emailBlacklisted: false în actualizări obișnuite. Brevo avertizează că schimbarea adresei unui contact blocat îi elimină blocarea. Trateaz-o separat. Verifică blocările și dezabonările înainte de a adăuga persoana la o listă de marketing. Între citire și scriere rămâne o scurtă fereastră; pentru garanție strictă verifică încă o dată înainte de trimitere.

Citirile trec prin GET /v3/contacts, care paginează cu limit (implicit 50, maximum 1000) și offset și acceptă modifiedSince și createdSince în UTC. Sincronizările incrementale ar trebui să se sprijine pe modifiedSince, nu pe parcurgerea listei complete. Reține că parametrul filter acceptă doar un operator de egalitate, așa că orice lucru mai expresiv aparține unui segment.

Pentru încărcare în masă, POST /v3/contacts/import acceptă fileUrl, fileBody sau jsonBody, țintește listIds și rulează asincron, returnând un processId. Brevo documentează un corp maxim de 10 MB și recomandă să rămâi în jur de 8 MB, pentru că parsarea umflă payloadul. Furnizează notifyUrl ca să afli rezultatul în loc să interoghezi repetat.

E-mail tranzacțional

POST /v3/smtp/email este calul de povară. Dincolo de sender, to, subject și htmlContent, câmpurile pe care merită să le cunoști sunt:

  • templateId împreună cu params, care înlocuiește conținutul inline cu un șablon Brevo și substituțiile lui de variabile. Parametrii unei versiuni individuale sunt plafonați la 100 KB, iar parametrii cumulați la 1000 KB.
  • messageVersions, care trimite variante personalizate într-un singur apel, cu până la 99 de destinatari per versiune.
  • tags pot ajuta la corelarea evenimentelor de livrare cu fluxul aplicației care le-a produs.
  • scheduledAt plus batchId, pentru trimiteri viitoare pe care ai putea vrea să le anulezi ca grup.
  • headers, scrise în Title-Case, pentru anteturi SMTP personalizate.

O singură cerere acceptă cel mult 2.000 de destinatari. Pentru diferența dintre acest endpoint și trimiterea de campanii, ghidul de e-mail tranzacțional oferă perspectiva de strategie a mesajelor.

Campanii de e-mail

POST /v3/emailCampaigns cere name și sender, plus exact o sursă de conținut: htmlContent (minimum 10 caractere, sub 1 MB), htmlUrl sau templateId. Publicul se pune în recipients ca listIds sau segmentIds, iar scheduledAt folosește formatul UTC YYYY-MM-DDTHH:mm:ss.SSSZ. Rutele însoțitoare acoperă trimiterea imediată, trimiterea unui test, actualizarea statusului și extragerea raportului campaniei.

Companii, tranzacții și obiecte

CRM-ul Brevo are două căi de scriere care se suprapun, iar alegerea corectă contează.

Rutele CRM sunt POST /v3/companies, PATCH /v3/companies/{id}, DELETE /v3/companies/{id} și setul echivalent pentru tranzacții. Acestea sunt sincrone. Un PATCH returnează 204 imediat ce modificarea este aplicată.

API-ul de obiecte este calea de masă: POST /v3/objects/{object_type}/batch/upsert acceptă până la 1000 de înregistrări și 1 MB per cerere, până la 500 de atribute per înregistrare și până la 10 înregistrări de asociere per tip de obiect per înregistrare. Returnează 202 cu un processId, adică acceptat, nu aplicat.

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" }
}
]
}'

Ghidul Brevo CRM acoperă modelul de obiecte din perspectiva operatorului.

SDK-uri oficiale

Brevo întreține clienți în organizația GitHub getbrevo:

LimbajRepository
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

Clientul Node se instalează ca @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);

Clientul Python se instalează cu pip install brevo-python. Dacă preferi să nu cari o dependență de SDK pentru două endpointuri, suprafața HTTP brută este suficient de mică încât să o apelezi direct, ceea ce te ține și izolat de schimbările de versiune ale SDK-ului:

Clientul Python se instalează cu pip install brevo-python. Pentru câteva endpointuri poți apela HTTP direct:

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

O actualizare reușită poate întoarce 204 fără corp. None înseamnă atunci că trebuie să recitești contactul pentru ID.

Exemplul presupune că apelantul a verificat consimțământul și blocările Brevo. Nu solicită deblocare. Cu o cheie reală, codul scrie în cont; testează-l întâi cu simulări. Conflictele de identitate pot da coduri 4xx diferite. Citește răspunsul și reconciliază ID-urile, fără să presupui 409.

Webhook-uri

Webhook-urile sunt modul în care afli ce s-a întâmplat după o trimitere. POST /v3/webhooks creează unul, cu url, events, type și, opțional, channel (email sau sms), batched, headers personalizate și un obiect auth.

Există trei tipuri de webhook, cu vocabulare de evenimente distincte:

  • Tranzacțional: sent, request, delivered, hardBounce, softBounce, blocked, spam, invalid, deferred, click, opened, uniqueOpened, unsubscribed.
  • Marketing: spam, opened, click, hardBounce, softBounce, unsubscribed, listAddition, delivered, contactUpdated, contactDeleted.
  • Inbound: inboundEmailProcessed, care necesită un 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"
}'

Pentru schimbări de contacte înregistrează un webhook marketing cu contactUpdated. Brevo numește evenimentul contact_updated în datele primite. Autentifică receptorul prin tokenul bearer auth sau antetele personalizate din ghidul de securitate. Verifică secretul înainte de procesare și nu îl salva în jurnale.

Păstrează o cheie de deduplicare din tipul evenimentului, ID-ul contactului și marcajul temporal pentru o perioadă care acoperă retransmiterile. Timpul singur nu este unic. Evenimentele pot fi duplicate sau sosesc în altă ordine. După eveniment recitește contactul și reconciliază starea cu sursa de încredere. Definește o fereastră de replay, respinge evenimente vechi după recuperare și verifică periodic schimbările incremental. Webhook-ul anunță o schimbare, dar nu creează singur sincronizare în ambele sensuri. Ghidul conectorilor explică alegerea.

Limite de rată și tratarea erorilor

Limitele de rată ale Brevo sunt per endpoint și per nivel de plan, iar distanța dintre endpointuri este enormă.

EndpointGeneral (orice plan)Advanced (Professional și 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
Endpointuri fără o limită proprie100 RPH200 RPH

Brevo documentează x-sib-ratelimit-limit, x-sib-ratelimit-remaining și x-sib-ratelimit-reset pentru endpointurile limitate. Citește-le și după succes. La 429 așteaptă resetarea și reîncearcă numai în limite fixe de încercări și timp. Valoarea reset este o durată în unitatea ferestrei, de obicei secunde, nu un timp Unix.

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));
}
}

Dacă așteptarea necesară depășește 60 de secunde, funcția returnează 429. Programează o încercare ulterioară.

Acest ajutor este numai pentru cereri pe care le-ai verificat ca sigure pentru reluare. După o eroare ambiguă de trimitere, reconciliază ID-ul mesajului înainte de a retrimite. Înregistrează starea și antetele de limită, niciodată cheia API sau datele contactului.

Nu relua un 4xx orbește. Referința pentru creare enumeră 400 și 425; un conflict nu garantează 409. După un 5xx la scriere, verifică dacă modificarea s-a aplicat deja.

Ce cod ai primit?

  1. 429

    Așteaptă în limita stabilită

    Folosește durata reset și oprește-te după câteva încercări.

  2. 5xx după scriere

    Verifică rezultatul

    Serverul putea scrie înainte de eroare.

  3. 400

    Corectează cererea

    De obicei cererea este greșită.

  4. Conflict de identificatori

    Citește și reconciliază ID-urile

    API-ul nu promite un cod exact.

Testare fără a trimite e-mailuri

Adaugă antetul X-Sib-Sandbox cu valoarea drop la o trimitere tranzacțională. Brevo validează cererea, returnează 201 cu un messageId, nu livrează nimic și nu scrie niciun jurnal de e-mail.

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>" }'

Înțelege ce dovedește și ce nu dovedește asta. Modul sandbox validează doar formatul cererii. Nu spune nimic despre autentificarea expeditorului, randarea șabloanelor sau livrabilitate. Ține un cont Brevo separat pentru testarea integrării a orice atinge contacte sau date CRM, pentru că modul sandbox acoperă trimiterea, nu restul API-ului.

Înainte de sincronizarea contactelor

  • Alege un ID sursă stabil pentru ext_id și păstrează ID-ul Brevo returnat.
  • Verifică atributele înainte de scriere. Brevo poate ignora câmpuri necunoscute sau cu tip greșit; recitește un contact de test.
  • Folosește o listă explicită și o dovadă sigură a consimțământului. Omite blocările și dezabonările.
  • Numără separat înregistrările acceptate, aplicate, omise și eșuate. Un 202 pentru loturi ori obiecte arată inițial doar acceptarea.
  • Folosește webhook-uri marketing ca semnale și reconciliază starea curentă. Autentifică, deduplică și limitează replay-ul.
  • Urmărește antetele de rată și oprește-te după câteva încercări.

Tajo se concentrează pe sincronizarea datelor comerciale cu Brevo. Dacă construiești singur acest strat, ghidul conectorilor Brevo compară opțiunile și erorile.

Întrebări Frecvente

Care este URL-ul de bază al Brevo API?

Toate apelurile REST către Brevo merg la https://api.brevo.com/v3/. Versiunea face parte din cale, iar v3 este generația curentă, așa că un endpoint precum trimiterea tranzacțională are calea completă https://api.brevo.com/v3/smtp/email.

Cum te autentifici la Brevo API?

Trimite cheia într-un antet HTTP numit api-key. Brevo nu folosește un antet Authorization sau Bearer pentru cheile API standard. Cheile se generează în setările contului, în secțiunea SMTP and API, pe fila API keys, iar valoarea este afișată o singură dată.

Care sunt limitele de rată ale Brevo API?

Limitele sunt per endpoint și per nivel de limită de rată. Pe nivelul general, pe care îl primește orice plan, endpointul de trimitere tranzacțională permite 1.000 de cereri pe secundă, endpointurile de contacte permit 10 pe secundă, iar endpointurile fără o limită proprie sunt plafonate la 100 de cereri pe oră. Planurile Professional și Enterprise pot folosi nivelul advanced, iar Enterprise nivelul extended. Depășirea unei limite returnează 429.

Are Brevo SDK-uri oficiale?

Da. Brevo publică clienți pentru Node.js, Python, PHP, Java, C#, Go și Ruby în organizația GitHub getbrevo. Pachetul Node este @getbrevo/brevo pe npm, iar pachetul Python este brevo-python pe PyPI.

Cum testez Brevo API fără să trimit e-mailuri reale?

Adaugă antetul X-Sib-Sandbox cu valoarea drop la o trimitere tranzacțională. Brevo validează cererea, returnează 201 cu un messageId, nu trimite nimic și nu scrie niciun jurnal de e-mail. Verifică doar formatul cererii, nu livrabilitatea.

Ce evenimente webhook acceptă Brevo?

Webhook-urile tranzacționale acoperă livrări, respingeri și dezabonări. Cele de marketing includ contactUpdated și contactDeleted. Pentru intrare, Brevo documentează inboundEmailProcessed.

Cum protejezi o dezabonare la actualizarea unui contact?

Folosește un ID sursă stabil și atribute declarate. Nu seta emailBlacklisted la false în actualizări obișnuite. Verifică persoana și sursa consimțământului înainte de a o adăuga la o listă de marketing.

Este suficient un webhook pentru sincronizare în ambele sensuri?

Nu. Autentifică receptorul, elimină livrările duplicate și reconciliază evenimentele pierdute sau sosite în altă ordine cu o sursă de încredere. Webhook-ul anunță schimbarea, nu dovedește concordanța.

Solicită acces anticipat

Introduceți prenumele și adresa de e-mail profesională. Vă vom trimite un link pentru a confirma cererea de acces la Tajo.

Obține Brevo