Introduction
# Brevo
Access the Brevo API with managed OAuth authentication. Send transactional emails, manage contacts and lists, create email campaigns, and work with templates.
## Quick Start
```bash # 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 ```
## Base URL
``` https://gateway.maton.ai/brevo/v3/{resource} ```
The gateway proxies requests to `api.brevo.com` and automatically injects your OAuth token.
## Authentication
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`:
```bash export MATON_API_KEY="YOUR_API_KEY" ```
### Getting Your API Key
1. Sign in or create an account at [maton.ai](https://maton.ai) 2. Go to [maton.ai/settings](https://maton.ai/settings) 3. Copy your API key
## Connection Management
Manage your Brevo OAuth connections at `https://ctrl.maton.ai`.
### List Connections
```bash 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 ```
### Create Connection
```bash 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 ```
### Get Connection
```bash 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:** ```json { "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.
### Delete Connection
```bash 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 ```
### Specifying Connection
If you have multiple Brevo connections, specify which one to use with the `Maton-Connection` header:
```bash 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.
## API Reference
### Account
#### Get Account Info
```bash GET /brevo/v3/account ```
**Response:** ```json { "email": "[email protected]", "firstName": "John", "lastName": "Doe", "companyName": "Acme Inc", "relay": { "enabled": true, "data": { "userName": "[email protected]", "relay": "smtp-relay.brevo.com", "port": 587 } } } ```
### Contacts
#### List Contacts
```bash 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:** ```json { "contacts": [ { "id": 1, "email": "[email protected]", "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 Contact
```bash 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_id`
#### Create Contact
```bash POST /brevo/v3/contacts Content-Type: application/json
{ "email": "[email protected]", "attributes": { "FIRSTNAME": "Jane", "LASTNAME": "Smith" }, "listIds": [2], "updateEnabled": false } ```
**Response:** ```json { "id": 2 } ```
Set `updateEnabled: true` to update the contact if it already exists.
#### Update Contact
```bash PUT /brevo/v3/contacts/{identifier} Content-Type: application/json
{ "attributes": { "FIRSTNAME": "Updated", "LASTNAME": "Name" } } ```
Returns 204 No Content on success.
#### Delete Contact
```bash DELETE /brevo/v3/contacts/{identifier} ```
Returns 204 No Content on success.
#### Get Contact Campaign Stats
```bash GET /brevo/v3/contacts/{identifier}/campaignStats ```
### Lists
#### List All Lists
```bash GET /brevo/v3/contacts/lists ```
**Response:** ```json { "lists": [ { "id": 2, "name": "Newsletter Subscribers", "folderId": 1, "uniqueSubscribers": 150, "totalBlacklisted": 2, "totalSubscribers": 148 } ], "count": 1 } ```
#### Get List
```bash GET /brevo/v3/contacts/lists/{listId} ```
#### Create List
```bash POST /brevo/v3/contacts/lists Content-Type: application/json
{ "name": "New List", "folderId": 1 } ```
**Response:** ```json { "id": 3 } ```
#### Update List
```bash PUT /brevo/v3/contacts/lists/{listId} Content-Type: application/json
{ "name": "Updated List Name" } ```
Returns 204 No Content on success.
#### Delete List
```bash DELETE /brevo/v3/contacts/lists/{listId} ```
Returns 204 No Content on success.
#### Get Contacts in List
```bash GET /brevo/v3/contacts/lists/{listId}/contacts ```
#### Add Contacts to List
```bash POST /brevo/v3/contacts/lists/{listId}/contacts/add Content-Type: application/json
{ "emails": ["[email protected]", "[email protected]"] } ```
#### Remove Contacts from List
```bash POST /brevo/v3/contacts/lists/{listId}/contacts/remove Content-Type: application/json
{ "emails": ["[email protected]"] } ```
### Folders
#### List Folders
```bash GET /brevo/v3/contacts/folders ```
**Response:** ```json { "folders": [ { "id": 1, "name": "Marketing", "uniqueSubscribers": 500, "totalSubscribers": 480, "totalBlacklisted": 20 } ], "count": 1 } ```
#### Get Folder
```bash GET /brevo/v3/contacts/folders/{folderId} ```
#### Create Folder
```bash POST /brevo/v3/contacts/folders Content-Type: application/json
{ "name": "New Folder" } ```
**Response:** ```json { "id": 4 } ```
#### Update Folder
```bash PUT /brevo/v3/contacts/folders/{folderId} Content-Type: application/json
{ "name": "Renamed Folder" } ```
Returns 204 No Content on success.
#### Delete Folder
```bash DELETE /brevo/v3/contacts/folders/{folderId} ```
Deletes folder and all lists within it. Returns 204 No Content on success.
#### Get Lists in Folder
```bash GET /brevo/v3/contacts/folders/{folderId}/lists ```
### Attributes
#### List Attributes
```bash GET /brevo/v3/contacts/attributes ```
**Response:** ```json { "attributes": [ { "name": "FIRSTNAME", "category": "normal", "type": "text" }, { "name": "LASTNAME", "category": "normal", "type": "text" } ] } ```
#### Create Attribute
```bash POST /brevo/v3/contacts/attributes/{category}/{attributeName} Content-Type: application/json
{ "type": "text" } ```
Categories: `normal`, `transactional`, `category`, `calculated`, `global`
#### Update Attribute
```bash PUT /brevo/v3/contacts/attributes/{category}/{attributeName} Content-Type: application/json
{ "value": "new value" } ```
#### Delete Attribute
```bash DELETE /brevo/v3/contacts/attributes/{category}/{attributeName} ```
### Transactional Emails
#### Send Email
```bash POST /brevo/v3/smtp/email Content-Type: application/json
{ "sender": { "name": "John Doe", "email": "[email protected]" }, "to": [ { "email": "[email protected]", "name": "Jane Smith" } ], "subject": "Welcome!", "htmlContent": "<html><body><h1>Hello!</h1><p>Welcome to our service.</p></body></html>" } ```
**Response:** ```json { "messageId": "<[email protected]>" } ```
**Optional Parameters:** - `cc` - Carbon copy recipients - `bcc` - Blind carbon copy recipients - `replyTo` - Reply-to address - `textContent` - Plain text version - `templateId` - Use a template instead of htmlContent - `params` - Template parameters - `attachment` - File attachments - `headers` - Custom headers - `tags` - Email tags for tracking - `scheduledAt` - Schedule for later (ISO 8601)
#### Get Transactional Emails
```bash GET /brevo/v3/smtp/emails ```
**Query Parameters:** - `email` - Filter by recipient email - `templateId` - Filter by template - `messageId` - Filter by message ID - `startDate` - Start date (YYYY-MM-DD) - `endDate` - End date (YYYY-MM-DD) - `limit` - Results per page - `offset` - Starting index
#### Delete Scheduled Email
```bash DELETE /brevo/v3/smtp/email/{identifier} ```
The identifier can be a messageId or batchId.
#### Get Email Statistics
```bash GET /brevo/v3/smtp/statistics/events ```
**Query Parameters:** - `limit` - Results per page - `offset` - Starting index - `startDate` - Start date - `endDate` - End date - `email` - Filter by recipient - `event` - Filter by event type: `delivered`, `opened`, `clicked`, `bounced`, etc.
### Email Templates
#### List Templates
```bash GET /brevo/v3/smtp/templates ```
**Response:** ```json { "count": 1, "templates": [ { "id": 1, "name": "Welcome Email", "subject": "Welcome {{params.name}}!", "isActive": true, "sender": { "name": "Company", "email": "[email protected]" }, "htmlContent": "<html>...</html>", "createdAt": "2026-02-09 23:29:38", "modifiedAt": "2026-02-09 23:29:38" } ] } ```
#### Get Template
```bash GET /brevo/v3/smtp/templates/{templateId} ```
#### Create Template
```bash POST /brevo/v3/smtp/templates Content-Type: application/json
{ "sender": { "name": "Company", "email": "[email protected]" }, "templateName": "Welcome Email", "subject": "Welcome {{params.name}}!", "htmlContent": "<html><body><h1>Hello {{params.name}}!</h1></body></html>" } ```
**Response:** ```json { "id": 1 } ```
#### Update Template
```bash PUT /brevo/v3/smtp/templates/{templateId} Content-Type: application/json
{ "templateName": "Updated Template Name", "subject": "New Subject" } ```
Returns 204 No Content on success.
#### Delete Template
```bash DELETE /brevo/v3/smtp/templates/{templateId} ```
Returns 204 No Content on success.
#### Send Test Email
```bash POST /brevo/v3/smtp/templates/{templateId}/sendTest Content-Type: application/json
{ "emailTo": ["[email protected]"] } ```
### Email Campaigns
#### List Campaigns
```bash GET /brevo/v3/emailCampaigns ```
**Query Parameters:** - `type` - Filter by type: `classic`, `trigger` - `status` - Filter by status: `draft`, `sent`, `archive`, `queued`, `suspended`, `in_process` - `limit` - Results per page - `offset` - Starting index
**Response:** ```json { "count": 1, "campaigns": [ { "id": 2, "name": "Monthly Newsletter", "subject": "Our March Update", "type": "classic", "status": "draft", "sender": { "name": "Company", "email": "[email protected]" }, "createdAt": "2026-02-09T23:29:39.000Z" } ] } ```
#### Get Campaign
```bash GET /brevo/v3/emailCampaigns/{campaignId} ```
#### Create Campaign
```bash POST /brevo/v3/emailCampaigns Content-Type: application/json
{ "name": "March Newsletter", "subject": "Our March Update", "sender": { "name": "Company", "email": "[email protected]" }, "htmlContent": "<html><body><h1>March News</h1></body></html>", "recipients": { "listIds": [2] } } ```
**Response:** ```json { "id": 2 } ```
#### Update Campaign
```bash PUT /brevo/v3/emailCampaigns/{campaignId} Content-Type: application/json
{ "name": "Updated Campaign Name", "subject": "Updated Subject" } ```
Returns 204 No Content on success.
#### Delete Campaign
```bash DELETE /brevo/v3/emailCampaigns/{campaignId} ```
Returns 204 No Content on success.
#### Send Campaign Now
```bash POST /brevo/v3/emailCampaigns/{campaignId}/sendNow ```
#### Send Test Email
```bash POST /brevo/v3/emailCampaigns/{campaignId}/sendTest Content-Type: application/json
{ "emailTo": ["[email protected]"] } ```
#### Update Campaign Status
```bash PUT /brevo/v3/emailCampaigns/{campaignId}/status Content-Type: application/json
{ "status": "suspended" } ```
### Senders
#### List Senders
```bash GET /brevo/v3/senders ```
**Response:** ```json { "senders": [ { "id": 1, "name": "Company", "email": "[email protected]", "active": true, "ips": [] } ] } ```
#### Get Sender
```bash GET /brevo/v3/senders/{senderId} ```
#### Create Sender
```bash POST /brevo/v3/senders Content-Type: application/json
{ "name": "Marketing", "email": "[email protected]" } ```
#### Update Sender
```bash PUT /brevo/v3/senders/{senderId} Content-Type: application/json
{ "name": "Updated Name" } ```
#### Delete Sender
```bash DELETE /brevo/v3/senders/{senderId} ```
### Blocked Contacts
#### List Blocked Contacts
```bash GET /brevo/v3/smtp/blockedContacts ```
#### Unblock Contact
```bash DELETE /brevo/v3/smtp/blockedContacts/{email} ```
### Blocked Domains
#### List Blocked Domains
```bash GET /brevo/v3/smtp/blockedDomains ```
#### Add Blocked Domain
```bash POST /brevo/v3/smtp/blockedDomains Content-Type: application/json
{ "domain": "spam-domain.com" } ```
#### Remove Blocked Domain
```bash DELETE /brevo/v3/smtp/blockedDomains/{domain} ```
## Pagination
Brevo uses offset-based pagination:
```bash 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:** ```json { "contacts": [...], "count": 150 } ```
To get the next page, increment offset by limit: - Page 1: `offset=0&limit=50` - Page 2: `offset=50&limit=50` - Page 3: `offset=100&limit=50`
## Code Examples
### JavaScript
```javascript const 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); ```
### Python
```python import os import requests
response = requests.get( 'https://gateway.maton.ai/brevo/v3/contacts', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'} ) data = response.json() print(data['contacts']) ```
### Python (Send Email)
```python import os import requests
response = 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': '[email protected]'}, 'to': [{'email': '[email protected]', 'name': 'Jane'}], 'subject': 'Hello!', 'htmlContent': '<html><body><h1>Hi Jane!</h1></body></html>' } ) result = response.json() print(f"Sent! Message ID: {result['messageId']}") ```
### Python (Create Contact and Add to List)
```python import os import requests
headers = { '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': '[email protected]', 'attributes': {'FIRSTNAME': 'New', 'LASTNAME': 'User'}, 'listIds': [2] } ) contact = response.json() print(f"Created contact ID: {contact['id']}") ```
## Notes
- All endpoints require the `/v3/` prefix in the path - Attribute names must be in UPPERCASE - Contact identifiers can be email, phone, or ID - Sender email addresses must be verified in Brevo - Template parameters use `{{params.name}}` syntax - PUT and DELETE operations return 204 No Content on success - Rate limits: 300 calls/minute on free plans, higher on paid plans - IMPORTANT: When piping curl output to `jq` or other commands, environment variables like `$MATON_API_KEY` may not expand correctly in some shell environments
## Error Handling
| 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 limit - `x-sib-ratelimit-remaining` - Remaining requests - `x-sib-ratelimit-reset` - Reset time
### Troubleshooting: Invalid API Key
**When you receive an "Invalid API key" error, ALWAYS follow these steps before concluding there is an issue:**
1. Check that the `MATON_API_KEY` environment variable is set:
```bash echo $MATON_API_KEY ```
2. Verify the API key is valid by listing connections:
```bash 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 ```
## Resources
- [Brevo API Overview](https://developers.brevo.com/) - [Brevo API Key Concepts](https://developers.brevo.com/docs/how-it-works) - [Brevo OAuth 2.0](https://developers.brevo.com/docs/integrating-oauth-20-to-your-solution) - [Manage Contacts](https://developers.brevo.com/docs/synchronise-contact-lists) - [Send Transactional Email](https://developers.brevo.com/docs/send-a-transactional-email)