Brevo
Brevo API integration with managed OAuth. Email marketing, transactional emails, SMS, contacts, and CRM. Use this skill when users want to send emails, manage contacts, create campaigns, or work with
Brevo API integration with managed OAuth. Email marketing, transactional emails, SMS, contacts, and CRM. Use this skill when users want to send emails, manage contacts, create campaigns, or work with
Real data. Real impact.
Emerging
Developers
Per week
Open source
Skills give you superpowers. Install in 30 seconds.
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://gateway.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://gateway.maton.ai/brevo/v3/{resource}
The gateway 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://ctrl.maton.ai.
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.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://ctrl.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://ctrl.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": "b04dd695-d056-433b-baf9-0fb4eb3bde9e", "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://ctrl.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://gateway.maton.ai/brevo/v3/account') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', 'b04dd695-d056-433b-baf9-0fb4eb3bde9e') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If omitted, the gateway uses the default (oldest) active connection.
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://gateway.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 requestsresponse = requests.get( 'https://gateway.maton.ai/brevo/v3/contacts', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'} ) data = response.json() print(data['contacts'])
import os import requestsresponse = requests.post( 'https://gateway.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 requestsheaders = { 'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}', 'Content-Type': 'application/json' }
Create contact
response = requests.post( 'https://gateway.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://ctrl.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
No automatic installation available. Please visit the source repository for installation instructions.
View Installation Instructions1,500+ AI skills, agents & workflows. Install in 30 seconds. Part of the Torly.ai family.
© 2026 Torly.ai. All rights reserved.