home / skills / openclaw / skills / brevo

brevo skill

/skills/yujesyoga/brevo

This skill helps you manage Brevo contacts, lists, and emails via the REST API, enabling import, segmentation, and transactional message sends.

npx playbooks add skill openclaw/skills --skill brevo

Review the files below or copy the command above to add this skill to your agents.

Files (2)
SKILL.md
6.5 KB
---
name: brevo
version: 1.0.0
description: Brevo (formerly Sendinblue) email marketing API for managing contacts, lists, sending transactional emails, and campaigns. Use when importing contacts, sending emails, managing subscriptions, or working with email automation.
---

# Brevo Email Marketing API

Manage contacts, send emails, and automate marketing via Brevo's REST API.

## Authentication

```bash
BREVO_KEY=$(cat ~/.config/brevo/api_key)
```

All requests require header: `api-key: $BREVO_KEY`

## Base URL

```
https://api.brevo.com/v3
```

## Common Endpoints

### Contacts

| Action | Method | Endpoint |
|--------|--------|----------|
| Create contact | POST | `/contacts` |
| Get contact | GET | `/contacts/{email}` |
| Update contact | PUT | `/contacts/{email}` |
| Delete contact | DELETE | `/contacts/{email}` |
| List contacts | GET | `/contacts?limit=50&offset=0` |
| Get blacklisted | GET | `/contacts?emailBlacklisted=true` |

### Lists

| Action | Method | Endpoint |
|--------|--------|----------|
| Get all lists | GET | `/contacts/lists` |
| Create list | POST | `/contacts/lists` |
| Get list contacts | GET | `/contacts/lists/{listId}/contacts` |
| Add to list | POST | `/contacts/lists/{listId}/contacts/add` |
| Remove from list | POST | `/contacts/lists/{listId}/contacts/remove` |

### Emails

| Action | Method | Endpoint |
|--------|--------|----------|
| Send transactional | POST | `/smtp/email` |
| Send campaign | POST | `/emailCampaigns` |
| Get templates | GET | `/smtp/templates` |

## Examples

### Create/Update Contact

```bash
curl -X POST "https://api.brevo.com/v3/contacts" \
  -H "api-key: $BREVO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "listIds": [10],
    "updateEnabled": true,
    "attributes": {
      "NOMBRE": "John",
      "APELLIDOS": "Doe"
    }
  }'
```

### Get Contact Info

```bash
curl "https://api.brevo.com/v3/contacts/[email protected]" \
  -H "api-key: $BREVO_KEY"
```

### Update Contact Attributes

```bash
curl -X PUT "https://api.brevo.com/v3/contacts/[email protected]" \
  -H "api-key: $BREVO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "listIds": [10, 15],
    "attributes": {
      "CUSTOM_FIELD": "value"
    }
  }'
```

### Send Transactional Email

```bash
curl -X POST "https://api.brevo.com/v3/smtp/email" \
  -H "api-key: $BREVO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": {"name": "My App", "email": "[email protected]"},
    "to": [{"email": "[email protected]", "name": "John"}],
    "subject": "Welcome!",
    "htmlContent": "<p>Hello {{params.name}}</p>",
    "params": {"name": "John"}
  }'
```

### Send with Template

```bash
curl -X POST "https://api.brevo.com/v3/smtp/email" \
  -H "api-key: $BREVO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": [{"email": "[email protected]"}],
    "templateId": 34,
    "params": {
      "NOMBRE": "John",
      "FECHA": "2026-02-01"
    }
  }'
```

### List All Contact Lists

```bash
curl "https://api.brevo.com/v3/contacts/lists?limit=50" \
  -H "api-key: $BREVO_KEY"
```

### Add Contacts to List (Bulk)

```bash
curl -X POST "https://api.brevo.com/v3/contacts/lists/10/contacts/add" \
  -H "api-key: $BREVO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "emails": ["[email protected]", "[email protected]"]
  }'
```

## Safe Import Pattern

When importing contacts, **always respect unsubscribes**:

```python
import requests

BREVO_KEY = "your-api-key"
HEADERS = {'api-key': BREVO_KEY, 'Content-Type': 'application/json'}
BASE = 'https://api.brevo.com/v3'

def get_blacklisted():
    """Get all unsubscribed/blacklisted emails"""
    blacklisted = set()
    offset = 0
    while True:
        r = requests.get(
            f'{BASE}/contacts?limit=100&offset={offset}&emailBlacklisted=true',
            headers=HEADERS
        )
        contacts = r.json().get('contacts', [])
        if not contacts:
            break
        for c in contacts:
            blacklisted.add(c['email'].lower())
        offset += 100
    return blacklisted

def safe_import(emails, list_id):
    """Import contacts respecting unsubscribes"""
    blacklisted = get_blacklisted()
    
    for email in emails:
        if email.lower() in blacklisted:
            print(f"Skipped (unsubscribed): {email}")
            continue
        
        r = requests.post(f'{BASE}/contacts', headers=HEADERS, json={
            'email': email,
            'listIds': [list_id],
            'updateEnabled': True
        })
        
        if r.status_code in [200, 201, 204]:
            print(f"Imported: {email}")
        else:
            print(f"Error: {email} - {r.text[:50]}")
```

## Contact Attributes

Brevo uses custom attributes for contact data:

```json
{
  "attributes": {
    "NOMBRE": "John",
    "APELLIDOS": "Doe",
    "FECHA_ALTA": "2026-01-15",
    "PLAN": "premium",
    "CUSTOM_FIELD": "any value"
  }
}
```

Create attributes in Brevo dashboard: Contacts → Settings → Contact attributes.

## Response Codes

| Code | Meaning |
|------|---------|
| 200 | Success (GET) |
| 201 | Created (POST) |
| 204 | Success, no content (PUT/DELETE) |
| 400 | Bad request (check payload) |
| 401 | Invalid API key |
| 404 | Contact/resource not found |

## Best Practices

1. **Always check blacklist** before importing contacts
2. **Use `updateEnabled: true`** to update existing contacts instead of failing
3. **Use templates** for consistent transactional emails
4. **Batch operations** when adding many contacts to lists
5. **Store list IDs** in config, not hardcoded
6. **Log imports** for audit trail

## Automations

Brevo automations trigger on:
- Contact added to list
- Contact attribute updated
- Email opened/clicked
- Custom events via API

Trigger automation manually:
```bash
curl -X POST "https://api.brevo.com/v3/contacts/import" \
  -H "api-key: $BREVO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "listIds": [10],
    "emailBlacklist": false,
    "updateExistingContacts": true,
    "emptyContactsAttributes": false,
    "jsonBody": [
      {"email": "[email protected]", "attributes": {"NOMBRE": "John"}}
    ]
  }'
```

## Useful Queries

```bash
# Count contacts in list
curl "https://api.brevo.com/v3/contacts/lists/10" -H "api-key: $BREVO_KEY" | jq '.totalSubscribers'

# Get recent contacts
curl "https://api.brevo.com/v3/contacts?limit=10&sort=desc" -H "api-key: $BREVO_KEY"

# Check if email exists
curl "https://api.brevo.com/v3/contacts/[email protected]" -H "api-key: $BREVO_KEY"

# Get account info
curl "https://api.brevo.com/v3/account" -H "api-key: $BREVO_KEY"
```

Overview

This skill integrates with the Brevo (formerly Sendinblue) Email Marketing API to manage contacts, lists, campaigns, and transactional email delivery. It provides endpoints and examples for importing contacts, sending templated or ad-hoc emails, and triggering automations. Use it to centralize email operations and respect unsubscribe rules when importing or messaging users.

How this skill works

The skill uses Brevo's REST API (base URL https://api.brevo.com/v3) and requires an api-key header for authentication. It supports creating, retrieving, updating, and deleting contacts; managing contact lists; sending transactional emails or campaigns; and querying account or list stats. It includes safe import patterns that fetch blacklisted emails first and skip unsubscribed users.

When to use it

  • Importing large contact lists while ensuring unsubscribes are respected
  • Sending transactional emails (welcome, password reset, receipts) with templates
  • Managing contact lists and bulk adding or removing emails
  • Automating workflows triggered by list changes or contact attribute updates
  • Querying contact or list statistics for reporting and audits

Best practices

  • Always fetch and respect the email blacklist before importing contacts
  • Use updateEnabled: true when creating contacts to update existing records safely
  • Prefer templates for transactional messages to ensure consistency and localization
  • Batch list operations and use pagination for large datasets to avoid rate limits
  • Store list IDs and API keys in configuration or secret storage, not in code
  • Log imports and API responses for auditability and troubleshooting

Example use cases

  • Safe mass import: fetch blacklisted emails, skip unsubscribes, and import remaining contacts into a list
  • Send welcome email: trigger a transactional template when a new user signs up
  • Segmented campaign: create lists by attribute and launch a targeted campaign via the API
  • Automation trigger: add a contact to a list and start a drip workflow based on that event
  • Sync profile updates: update contact attributes via PUT to keep CRM and Brevo in sync

FAQ

How do I authenticate API requests?

Include your API key in the request header as api-key: YOUR_KEY for every request.

How can I avoid emailing unsubscribed users during import?

Query contacts with emailBlacklisted=true to build a blacklist set, then skip those emails during import.