Access the Brevo API with managed OAuth authentication. Send transactional emails, manage contacts and lists, create email campaigns, and work with templates.
# Get account info
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/brevo/v3/account')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
https://api.maton.ai/brevo/v3/{resource}
Maton proxies requests to api.brevo.com and automatically injects your OAuth token.
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Manage your Brevo OAuth connections at https://api.maton.ai.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=brevo&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'brevo'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2026-02-09T19:51:00.932629Z",
"last_updated_time": "2026-02-09T19:51:30.123456Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "brevo",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple Brevo connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/brevo/v3/account')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
GET /brevo/v3/account
Response:
{
"email": "user@example.com",
"firstName": "John",
"lastName": "Doe",
"companyName": "Acme Inc",
"relay": {
"enabled": true,
"data": {
"userName": "user@smtp-brevo.com",
"relay": "smtp-relay.brevo.com",
"port": 587
}
}
}
GET /brevo/v3/contacts
Query Parameters:
limit - Number of results per page (default: 50, max: 500)offset - Index of first result (0-based)modifiedSince - Filter by modification date (ISO 8601)Response:
{
"contacts": [
{
"id": 1,
"email": "contact@example.com",
"emailBlacklisted": false,
"smsBlacklisted": false,
"createdAt": "2026-02-09T20:33:59.705+01:00",
"modifiedAt": "2026-02-09T20:35:19.529+01:00",
"listIds": [2],
"attributes": {
"FIRSTNAME": "John",
"LASTNAME": "Doe"
}
}
],
"count": 1
}
GET /brevo/v3/contacts/{identifier}
The identifier can be email address, phone number, or contact ID.
Query Parameters:
identifierType - Type of identifier: email_id, phone_id, contact_id, ext_idPOST /brevo/v3/contacts
Content-Type: application/json
{
"email": "newcontact@example.com",
"attributes": {
"FIRSTNAME": "Jane",
"LASTNAME": "Smith"
},
"listIds": [2],
"updateEnabled": false
}
Response:
{
"id": 2
}
Set updateEnabled: true to update the contact if it already exists.
PUT /brevo/v3/contacts/{identifier}
Content-Type: application/json
{
"attributes": {
"FIRSTNAME": "Updated",
"LASTNAME": "Name"
}
}
Returns 204 No Content on success.
DELETE /brevo/v3/contacts/{identifier}
Returns 204 No Content on success.
GET /brevo/v3/contacts/{identifier}/campaignStats
GET /brevo/v3/contacts/lists
Response:
{
"lists": [
{
"id": 2,
"name": "Newsletter Subscribers",
"folderId": 1,
"uniqueSubscribers": 150,
"totalBlacklisted": 2,
"totalSubscribers": 148
}
],
"count": 1
}
GET /brevo/v3/contacts/lists/{listId}
POST /brevo/v3/contacts/lists
Content-Type: application/json
{
"name": "New List",
"folderId": 1
}
Response:
{
"id": 3
}
PUT /brevo/v3/contacts/lists/{listId}
Content-Type: application/json
{
"name": "Updated List Name"
}
Returns 204 No Content on success.
DELETE /brevo/v3/contacts/lists/{listId}
Returns 204 No Content on success.
GET /brevo/v3/contacts/lists/{listId}/contacts
POST /brevo/v3/contacts/lists/{listId}/contacts/add
Content-Type: application/json
{
"emails": ["contact1@example.com", "contact2@example.com"]
}
POST /brevo/v3/contacts/lists/{listId}/contacts/remove
Content-Type: application/json
{
"emails": ["contact1@example.com"]
}
GET /brevo/v3/contacts/folders
Response:
{
"folders": [
{
"id": 1,
"name": "Marketing",
"uniqueSubscribers": 500,
"totalSubscribers": 480,
"totalBlacklisted": 20
}
],
"count": 1
}
GET /brevo/v3/contacts/folders/{folderId}
POST /brevo/v3/contacts/folders
Content-Type: application/json
{
"name": "New Folder"
}
Response:
{
"id": 4
}
PUT /brevo/v3/contacts/folders/{folderId}
Content-Type: application/json
{
"name": "Renamed Folder"
}
Returns 204 No Content on success.
DELETE /brevo/v3/contacts/folders/{folderId}
Deletes folder and all lists within it. Returns 204 No Content on success.
GET /brevo/v3/contacts/folders/{folderId}/lists
GET /brevo/v3/contacts/attributes
Response:
{
"attributes": [
{
"name": "FIRSTNAME",
"category": "normal",
"type": "text"
},
{
"name": "LASTNAME",
"category": "normal",
"type": "text"
}
]
}
POST /brevo/v3/contacts/attributes/{category}/{attributeName}
Content-Type: application/json
{
"type": "text"
}
Categories: normal, transactional, category, calculated, global
PUT /brevo/v3/contacts/attributes/{category}/{attributeName}
Content-Type: application/json
{
"value": "new value"
}
DELETE /brevo/v3/contacts/attributes/{category}/{attributeName}
POST /brevo/v3/smtp/email
Content-Type: application/json
{
"sender": {
"name": "John Doe",
"email": "john@example.com"
},
"to": [
{
"email": "recipient@example.com",
"name": "Jane Smith"
}
],
"subject": "Welcome!",
"htmlContent": "<html><body><h1>Hello!</h1><p>Welcome to our service.</p></body></html>"
}
Response:
{
"messageId": "<202602092329.12910305853@smtp-relay.mailin.fr>"
}
Optional Parameters:
cc - Carbon copy recipientsbcc - Blind carbon copy recipientsreplyTo - Reply-to addresstextContent - Plain text versiontemplateId - Use a template instead of htmlContentparams - Template parametersattachment - File attachmentsheaders - Custom headerstags - Email tags for trackingscheduledAt - Schedule for later (ISO 8601)GET /brevo/v3/smtp/emails
Query Parameters:
email - Filter by recipient emailtemplateId - Filter by templatemessageId - Filter by message IDstartDate - Start date (YYYY-MM-DD)endDate - End date (YYYY-MM-DD)limit - Results per pageoffset - Starting indexDELETE /brevo/v3/smtp/email/{identifier}
The identifier can be a messageId or batchId.
GET /brevo/v3/smtp/statistics/events
Query Parameters:
limit - Results per pageoffset - Starting indexstartDate - Start dateendDate - End dateemail - Filter by recipientevent - Filter by event type: delivered, opened, clicked, bounced, etc.GET /brevo/v3/smtp/templates
Response:
{
"count": 1,
"templates": [
{
"id": 1,
"name": "Welcome Email",
"subject": "Welcome {{params.name}}!",
"isActive": true,
"sender": {
"name": "Company",
"email": "noreply@company.com"
},
"htmlContent": "<html>...</html>",
"createdAt": "2026-02-09 23:29:38",
"modifiedAt": "2026-02-09 23:29:38"
}
]
}
GET /brevo/v3/smtp/templates/{templateId}
POST /brevo/v3/smtp/templates
Content-Type: application/json
{
"sender": {
"name": "Company",
"email": "noreply@company.com"
},
"templateName": "Welcome Email",
"subject": "Welcome {{params.name}}!",
"htmlContent": "<html><body><h1>Hello {{params.name}}!</h1></body></html>"
}
Response:
{
"id": 1
}
PUT /brevo/v3/smtp/templates/{templateId}
Content-Type: application/json
{
"templateName": "Updated Template Name",
"subject": "New Subject"
}
Returns 204 No Content on success.
DELETE /brevo/v3/smtp/templates/{templateId}
Returns 204 No Content on success.
POST /brevo/v3/smtp/templates/{templateId}/sendTest
Content-Type: application/json
{
"emailTo": ["test@example.com"]
}
GET /brevo/v3/emailCampaigns
Query Parameters:
type - Filter by type: classic, triggerstatus - Filter by status: draft, sent, archive, queued, suspended, in_processlimit - Results per pageoffset - Starting indexResponse:
{
"count": 1,
"campaigns": [
{
"id": 2,
"name": "Monthly Newsletter",
"subject": "Our March Update",
"type": "classic",
"status": "draft",
"sender": {
"name": "Company",
"email": "news@company.com"
},
"createdAt": "2026-02-09T23:29:39.000Z"
}
]
}
GET /brevo/v3/emailCampaigns/{campaignId}
POST /brevo/v3/emailCampaigns
Content-Type: application/json
{
"name": "March Newsletter",
"subject": "Our March Update",
"sender": {
"name": "Company",
"email": "news@company.com"
},
"htmlContent": "<html><body><h1>March News</h1></body></html>",
"recipients": {
"listIds": [2]
}
}
Response:
{
"id": 2
}
PUT /brevo/v3/emailCampaigns/{campaignId}
Content-Type: application/json
{
"name": "Updated Campaign Name",
"subject": "Updated Subject"
}
Returns 204 No Content on success.
DELETE /brevo/v3/emailCampaigns/{campaignId}
Returns 204 No Content on success.
POST /brevo/v3/emailCampaigns/{campaignId}/sendNow
POST /brevo/v3/emailCampaigns/{campaignId}/sendTest
Content-Type: application/json
{
"emailTo": ["test@example.com"]
}
PUT /brevo/v3/emailCampaigns/{campaignId}/status
Content-Type: application/json
{
"status": "suspended"
}
GET /brevo/v3/senders
Response:
{
"senders": [
{
"id": 1,
"name": "Company",
"email": "noreply@company.com",
"active": true,
"ips": []
}
]
}
GET /brevo/v3/senders/{senderId}
POST /brevo/v3/senders
Content-Type: application/json
{
"name": "Marketing",
"email": "marketing@company.com"
}
PUT /brevo/v3/senders/{senderId}
Content-Type: application/json
{
"name": "Updated Name"
}
DELETE /brevo/v3/senders/{senderId}
GET /brevo/v3/smtp/blockedContacts
DELETE /brevo/v3/smtp/blockedContacts/{email}
GET /brevo/v3/smtp/blockedDomains
POST /brevo/v3/smtp/blockedDomains
Content-Type: application/json
{
"domain": "spam-domain.com"
}
DELETE /brevo/v3/smtp/blockedDomains/{domain}
Brevo uses offset-based pagination:
GET /brevo/v3/contacts?limit=50&offset=0
Parameters:
limit - Number of results per page (varies by endpoint, typically max 500)offset - Starting index (0-based)Response includes count:
{
"contacts": [...],
"count": 150
}
To get the next page, increment offset by limit:
offset=0&limit=50offset=50&limit=50offset=100&limit=50const response = await fetch(
'https://api.maton.ai/brevo/v3/contacts',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
console.log(data.contacts);
import os
import requests
response = requests.get(
'https://api.maton.ai/brevo/v3/contacts',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}
)
data = response.json()
print(data['contacts'])
import os
import requests
response = requests.post(
'https://api.maton.ai/brevo/v3/smtp/email',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'sender': {'name': 'John', 'email': 'john@example.com'},
'to': [{'email': 'recipient@example.com', 'name': 'Jane'}],
'subject': 'Hello!',
'htmlContent': '<html><body><h1>Hi Jane!</h1></body></html>'
}
)
result = response.json()
print(f"Sent! Message ID: {result['messageId']}")
import os
import requests
headers = {
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
}
# Create contact
response = requests.post(
'https://api.maton.ai/brevo/v3/contacts',
headers=headers,
json={
'email': 'newuser@example.com',
'attributes': {'FIRSTNAME': 'New', 'LASTNAME': 'User'},
'listIds': [2]
}
)
contact = response.json()
print(f"Created contact ID: {contact['id']}")
/v3/ prefix in the path{{params.name}} syntaxjq or other commands, environment variables like $MATON_API_KEY may not expand correctly in some shell environments| Status | Meaning |
|---|---|
| -------- | --------- |
| 400 | Missing Brevo connection or bad request |
| 401 | Invalid or missing Maton API key |
| 404 | Resource not found |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Brevo API |
Rate limit headers in response:
x-sib-ratelimit-limit - Request limitx-sib-ratelimit-remaining - Remaining requestsx-sib-ratelimit-reset - Reset timeWhen you receive an "Invalid API key" error, ALWAYS follow these steps before concluding there is an issue:
MATON_API_KEY environment variable is set:echo $MATON_API_KEY
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
共 2 个版本