Skip to main content

Brevo ExecModule

Overview

BrevoModule connects ValkyrAI workflows to Brevo API v3 through the native map I/O ExecModule ABI. It discovers account, contact, list, sender, and campaign state; performs bounded contact mutations; sends transactional messages; creates draft email campaigns; and guards customer-visible campaign delivery.

The connector follows the useful contact, email, and sender patterns in n8n's Brevo node while keeping credentials in IntegrationAccount, routing only to the fixed Brevo API origin, bounding inputs and responses, retrying only reads, and requiring explicit confirmation before contact deletion or campaign sending.

Usage

  1. Create a dedicated Brevo API key or private OAuth app with only the required contacts, campaigns, sender, and transactional-email permissions.
  2. Store the API key or current OAuth access token in the encrypted IntegrationAccount.apiKey SecureField.
  3. Set the IntegrationAccount status to READY and bind it through ExecModuleConfig.authConfig.integrationAccount.
  4. Choose authMode: api_key for standard Brevo keys or oauth_bearer for a current access token.
  5. Use discovery operations to confirm visible lists, verified senders, contacts, and campaign IDs before mutations.
  6. Reconcile Brevo after any ambiguous write timeout; the module never automatically repeats mutations.

Workflow payloads cannot supply credentials, authorization headers, or an arbitrary provider URL.

Inputs

NameTypeRequirementDefaultConstraints
operationstringRequiredNoneOne of the fourteen operations below.
contactIdentifierstringContact get/update/deleteNoneEmail, numeric ID, or external identifier; at most 320 characters and no path delimiters.
emailstringCreate/upsertNoneValid email, at most 320 characters.
attributesobject or JSONOptional contact mutationNoneAt most 100 safe, non-credential-like keys.
listIdsinteger array or JSONOptional create/upsert/updateNone1–50 positive list IDs.
unlinkListIdsinteger array or JSONOptional updateNone1–50 positive list IDs.
emailBlacklistedbooleanOptional updateNoneUpdates marketing-email blacklist state.
smsBlacklistedbooleanOptional updateNoneUpdates SMS blacklist state.
senderobject or JSONTransactional emailNoneVerified sender name and email.
recipientsarray or JSONTransactional emailNone1–99 objects containing email and optional name.
subjectstringInline transactional emailNoneRequired without templateId; at most 998 characters.
textContentstringInline transactional emailNoneAt least one of text or HTML; at most 200,000 characters.
htmlContentstringInline transactional emailNoneAt least one of HTML or text; at most 200,000 characters.
templateIdintegerTemplate transactional emailNonePositive Brevo transactional-template ID.
paramsobject or JSONOptional template dataNoneAt most 100 safe keys.
tagsstring array or JSONOptional transactional tagsNone1–50 values, each at most 128 characters.
campaignIdinteger stringCampaign get/sendNonePositive integer.
campaignobject or JSONCreate campaignNoneAt most 50 allowlisted fields and 256 KiB.
queryobject or JSONList operationsNoneAt most 12 operation-specific scalar filters.
offsetintegerOptional lists00–1,000,000.
limitintegerOptional lists1001–500 emitted items.
confirmDeletebooleandelete_contactfalseMust be exactly true.
confirmSendbooleansend_campaignfalseMust be exactly true.

create_campaign accepts only Brevo email-campaign fields including name, subject, sender, type, recipients, one supported content source, scheduling, A/B-test, warmup, header/footer, reply, tag, and UTM fields. It requires name, sender, recipients, and one of htmlContent, htmlUrl, or templateId.

Outputs

NameTypeWhen presentDescription
statusstringAlwayssuccess or error.
operationstringAlwaysNormalized operation name.
resourcestringAfter validationBrevo resource family.
attemptsintegerAlwaysProvider attempts consumed.
httpStatusintegerProvider respondedLast HTTP status.
dataobjectSingle-resource or action successProvider response normalized into the native output shape.
items / countarray / integerList successBounded resources and emitted count.
hasMorebooleanList successWhether another bounded offset may exist.
nextOffsetintegerAnother page may existNext provider offset.
requestIdstringProvider supplies itTrace reference for Brevo support.
errorobjectFailureSafe code, message, and retryable flag.

API keys, OAuth bearer values, and credential-like payload fields are rejected or redacted from failures, outputs, logs, and workflow events.

IntegrationAccount Requirements

SettingRequirement
ProviderBrevo API v3
accountNameHuman-readable automation identity
apiKeyEncrypted SecureField containing an API key or current OAuth access token
statusExactly READY
API-key permissionsContact/list reads and required contact writes; sender reads; campaign reads/writes; transactional email send
OAuth scopesMinimum explicit contacts:read, contacts:write, campaign read/write, and transactional.email:write equivalents needed by selected operations

Brevo API keys use the api-key header. OAuth mode sends Authorization: Bearer. OAuth token refresh remains an IntegrationAccount lifecycle responsibility; the module never accepts refresh tokens in workflow payloads.

Configuration

{
"version": "1.0.0",
"authConfig": {
"authStrategy": 1,
"integrationAccount": "integration-account:brevo-customer-engagement"
},
"retryPolicy": {
"maxAttempts": 3,
"backoffStrategy": "EXPONENTIAL",
"initialDelayMs": 250,
"maxDelayMs": 5000
},
"executionConfig": {"timeoutMs": 30000},
"payloadConfig": {
"parameters": "{\"authMode\":\"api_key\",\"operation\":\"list_contacts\",\"limit\":100}"
}
}

The account reference is symbolic. Persisted workflows bind the generated relationship, never a plaintext credential.

Operations

OperationBrevo behaviorSide effect
get_accountReads the authenticated Brevo account and plan state.Read-only; safe retries.
list_contactsLists a bounded contact page with allowlisted sorting/date filters.Read-only; safe retries.
get_contactReads one contact by encoded identifier.Read-only; safe retries.
create_contactCreates one contact with typed email, attributes, and list IDs.Contact mutation; one attempt.
upsert_contactUses Brevo's updateEnabled contact contract.Contact mutation; one attempt.
update_contactUpdates supplied contact attributes, list membership, or blacklist state.Contact mutation; one attempt.
delete_contactDeletes one contact after explicit confirmation.Destructive; one attempt.
list_contact_listsLists visible Brevo contact lists.Read-only; safe retries.
list_sendersLists configured and verified senders, locally capped by limit.Read-only; safe retries.
send_transactional_emailSends one bounded inline or template-based transactional message.Customer-visible delivery; one attempt.
list_campaignsLists a bounded email-campaign page with allowlisted filters.Read-only; safe retries.
get_campaignReads one email campaign and verifies returned identity when supplied.Read-only; safe retries.
create_campaignCreates one bounded email campaign, normally in draft state.Campaign mutation; one attempt.
send_campaignSends an existing campaign immediately after explicit confirmation.Broad customer-visible delivery; one attempt.

Errors

CodeTypical causeRetryableResolution
VALIDATION_ERRORMissing or malformed email/ID, unsupported field/filter, oversized payload, empty update, or missing confirmation.NoCorrect the named input; no unsafe request was sent.
UNSUPPORTED_OPERATIONUnknown operation.NoSelect a documented operation.
INTEGRATION_ACCOUNT_REQUIREDNo bound account.NoBind a Brevo IntegrationAccount.
INTEGRATION_ACCOUNT_NOT_READYAccount status is not READY.NoRepair or reconnect the account.
BREVO_HTTP_400Invalid provider field, value, recipient, content, or campaign state.NoCorrect the bounded provider error.
BREVO_HTTP_401Credential is missing, revoked, expired, or invalid.NoRotate the key or refresh/reconnect OAuth.
BREVO_HTTP_403Account, IP allowlist, plan, or scope denies the action.NoGrant the minimum permission or authorize the runtime IP.
BREVO_HTTP_404Identifier is wrong, deleted, or invisible.NoRe-run discovery under the same account.
BREVO_HTTP_429Endpoint or account rate limit is exhausted.Yes for readsHonor Retry-After and reduce concurrency.
BREVO_HTTP_5xxTransient provider failure.Yes for readsRetry reads; reconcile writes before manual replay.
NETWORK_ERRORTimeout, DNS, TLS, or connectivity failure.Yes for readsVerify connectivity; inspect Brevo before repeating writes.
RESPONSE_TOO_LARGEResponse exceeded 5 MiB.NoLower limit or narrow filters.

Example

Send an onboarding email after an approved workflow confirms consent and sender identity:

{
"operation": "send_transactional_email",
"sender": {"name": "Valkyr Labs", "email": "ops@example.com"},
"recipients": [{"name": "Ada", "email": "ada@example.com"}],
"subject": "Your governed workspace is ready",
"textContent": "Your ValkyrAI workspace is ready for the approved onboarding workflow.",
"params": {"WORKSPACE": "Ada"},
"tags": ["onboarding", "workspace-ready"]
}

Expected result:

{
"status": "success",
"operation": "send_transactional_email",
"resource": "transactional-email",
"attempts": 1,
"httpStatus": 201,
"data": {"messageId": "<provider-message-id>"}
}

Notes

  • Pagination: contacts, contact lists, and campaigns use Brevo limit/offset pagination. The module emits at most 500 items and returns nextOffset only when provider evidence indicates another page. Sender results are locally capped because the sender endpoint is not treated as an offset collection.
  • Rate limits: read operations may retry HTTP 408, 429, 500, 502, 503, and 504 and network failures, honoring numeric Retry-After. Mutations never retry automatically.
  • API limits: request bodies are capped at 256 KiB, provider responses at 5 MiB, recipients at 99, contact-list IDs at 50, and transaction tags at 50. Provider plan and daily-send quotas still apply.
  • Idempotency: upsert_contact uses Brevo's updateEnabled behavior, but every write is sent once because a timeout can follow a committed mutation. Reconcile contacts, campaign state, or message events before replaying.
  • Destructive behavior: delete_contact requires confirmDelete=true. send_campaign requires confirmSend=true because it can notify an entire audience. Bulk contact deletion, campaign deletion, SMS/WhatsApp sending, and webhook deletion are not exposed.
  • External effects: contact changes can enter Brevo automations; transactional messages and campaigns can produce delivery, open, click, bounce, unsubscribe, complaint, and webhook events after the request returns.
  • External verification: deterministic local tests cover both auth modes, fixed routing, encoded contact IDs, request bodies, pagination, retries, mutation non-retry, confirmation guards, redaction, validation, and metadata discovery. Live plan limits, IP allowlists, sender verification, deliverability, OAuth refresh, automations, and tenant-specific contact attributes require separately authorized Brevo credentials and are not exercised in repository tests.
  • Deferred operations: contact imports, attributes, folders, list membership bulk jobs, transactional templates, scheduled campaign updates, webhook management, SMTP statistics, SMS, WhatsApp, conversations, eCommerce, custom objects, and automation triggers are deferred.
  • Functional references: n8n Brevo source, Brevo API overview, Brevo contact API, and Brevo transactional email API.