Content

Marketing APIs for AI Agents

Reading your audience is safe. Sending to it is not, and there is no unsend endpoint. How to give a marketing agent useful access without letting it email 40,000 people.

Chaitrali Kakde

DevRel Engineer

Use CasesOct 23, 2026

Marketing APIs have a property that makes them unusually dangerous for agents, and it is not technical. There is no unsend. Once a campaign goes out to 40,000 addresses, the only remedy is a second email apologising for the first one, which also goes to 40,000 addresses.

Compare that to almost everything else an agent touches. A bad CRM field gets corrected. A bad Stripe charge gets refunded. A bad send is permanent, public, and in some jurisdictions a compliance incident rather than an embarrassment.

The good news: the useful half of marketing automation is reading, and reading is safe. Here is how to split them.

Draw the line at outbound

Marketing platforms expose roughly three kinds of operation, and they carry wildly different risk.

  • Audience and performance reads. List sizes, segment definitions, open and click rates, campaign history, contact properties. Low risk, high value. Most of what you want from a marketing agent lives here.
  • Internal writes. Creating a draft campaign, updating a contact tag, building a segment, adding a note. Recoverable. Reasonable to allow with light guardrails.
  • Outbound sends. Sending a campaign, triggering a transactional email, firing an SMS, publishing a post. Irreversible and externally visible. Treat these like a wire transfer, not like a database write.

The simplest safe setup is two projects with two credentials: a read-and-draft agent that cannot send anything at all, and a separate narrowly scoped sender that only your own code triggers with a human in the loop. If the first one is compromised or confused, the worst case is a bad draft.

This is the part that worries us most about agents in marketing. Every platform maintains unsubscribes, bounces and suppression lists, and respecting them is a legal requirement under regimes like GDPR and CAN-SPAM, not a nicety.

The danger is an agent that builds a recipient list itself. Ask a model to "email everyone who signed up in the last quarter" and it will happily assemble that list from whatever data it can reach: a CRM export, a spreadsheet, a database query. None of those know who unsubscribed last week. You have now sent marketing email to people who explicitly opted out, using a path that bypassed the platform's own protection.

So: never let the agent construct an audience from raw data. Let it select an existing segment maintained inside the marketing platform, where suppression is applied natively. That one rule prevents most of the compliance exposure here.

Duplicate sends, because most email APIs cannot help you

Here is an awkward fact about this category: idempotency support on email send endpoints is inconsistent at best. We looked at this provider by provider in which email APIs support idempotency keys, and email is the clearest gap in the whole API landscape.

Which means the ambiguous case has no clean answer. Your send request leaves, the connection drops before the response arrives, and nothing in your system knows whether 40,000 emails went out. Retry and you might double-send. Do not retry and you might have sent nothing.

Three things make this manageable. First, writes are only auto-retried when an idempotency key is set, so an unprotected send fails loudly instead of quietly running twice. Second, check before you send: most platforms let you query recent campaign activity, so a read can tell you whether the send already happened. Third, for transactional mail, key on the event, not the attempt, so the same order confirmation cannot go out twice. Background in the complete idempotency guide and the idempotency docs.

Setting up the read-and-draft agent

Works the same whichever platform you use. Swytchcode has integrations for Brevo, HubSpot and others, and any REST API with an OpenAPI spec or Postman collection can be added as a custom provider.

setup.sh
npx swytchcode
swy login
swy init --mode=sandbox

swy get brevo                       # or hubspot, mailchimp, etc.
swy auth connect brevo
swy auth status

# find the reads
swy discover "list contacts in a segment" --project brevo
swy discover "campaign statistics" --project brevo
swy list methods brevo

swy info <canonical_id>
swy add method <canonical_id>       # reads and draft-creation only

# deliberately NOT added: send campaign, send email, delete list
swy audit policy                    # later: see what got blocked

The last comment is the important line. Because the send method was never added, there is no prompt, no injected instruction in a document the agent reads, and no reasoning error that can produce a send. The capability is absent rather than discouraged, which is a different kind of guarantee from a system prompt saying "never send without asking."

If you do allow sending, the policy to write

Gate on audience size, because the gap between a test send to five colleagues and a blast to the whole list is the entire risk.

policies.json
{
  "id": "no-mass-sends-without-a-human",
  "target": ["<send-campaign canonical_id>"],
  "when": { "field": "recipient_count", "operator": ">", "value": 50 },
  "action": {
    "type": "REQUIRES_APPROVAL",
    "message": "Agent wants to send to more than 50 recipients. This cannot be undone."
  },
  "approval_timeout": "1h"
}

Use whichever argument your provider actually exposes for audience size, which you can check with swy info <canonical_id>. Fifty is deliberately low: small enough that a genuine test still flows, large enough to catch anything resembling a campaign. Held calls go to Slack or Telegram and fail closed, so if your approver is asleep the email does not go out. Setup in the human approval docs, schema in the policy reference.

A second rule worth adding: deny sends entirely outside working hours. Not because the API cares, but because a 3am send means nobody is watching when it goes wrong. Rules live in policies.json in your repo, so loosening one is a reviewed pull request rather than a quiet toggle. That is the policy-as-code argument in a nutshell.

Auth and the scope question

Most marketing platforms hand you an API key or an OAuth app whose scopes are coarse: a key that can read contacts can usually also email them. That is exactly why the allowlist matters more than the scope. The credential may technically permit sending; your project does not include the send method, so it cannot happen. We go deeper on that difference in API access control for AI agents.

Keys are connected once with swy auth connect and stored outside the project, encrypted at rest, then injected when a call runs. No .env file, and nothing for the model to read or leak. Worth caring about here specifically, because a leaked marketing credential lets someone email your entire customer base from your domain.

Rate limits and the polling habit

Marketing APIs are usually generous on reads and stingy on sends, and limits vary enough by provider and plan that the only useful advice is to read your own dashboard. Rate-limit responses get exponential backoff automatically, which covers the usual case.

The thing to design around is that campaign statistics are eventually consistent. Send a campaign and immediately ask for open rates and you will get zeros, which an agent may well report as "the campaign failed." Wait, then poll, and treat an empty stats response as "too early" rather than "no engagement." This is a cousin of the 200 OK but it failed problem: the call succeeded, the data just is not there yet.

From Claude Code or Cursor

The read-and-draft agent is a good MCP citizen: you are writing copy, you want last quarter's open rates, you do not want to leave the editor. Connect it through the MCP server and the allowlist travels with it, so an editor session genuinely cannot send. Setup in the MCP guide, reference in the MCP docs, and skills.md if you want a coding agent to set it up for you.

What you can build

  1. A performance digest. Every Monday, read the last week's campaigns, compare against the trailing average, and write a short note on what moved and a guess at why. Read-only, immediately useful, and the thing most teams actually wanted when they asked for "AI in marketing."
  2. List hygiene reporting. Find contacts with missing fields, hard bounces that are still in active segments, duplicates across lists, and segments that have not been used in a year. Produce the list; let a human act on it.
  3. Campaign drafting from a brief. Take a product update, draft subject lines and body copy in the platform as a draft campaign against an existing segment, and stop there. A human reviews and sends. If you want it multilingual, pair it with DeepL.
  4. Attribution stitching. Join campaign engagement against CRM deal stages to answer which campaign actually preceded a closed deal. Two read-only credentials and a lot of value, with no send permission anywhere in sight.

FAQ

Can an agent safely send transactional email?

More safely than marketing email, because the audience is one person and the trigger is an event rather than a judgement call. Key on the event ID so a retry cannot send twice, and keep the template on your side rather than letting the model write the body of something that goes out automatically.

What if the agent needs to add someone to a list?

That is an internal write and reasonable to allow, with one caveat: adding a contact to a list that has an active automation attached is effectively a send. Check whether your segments trigger journeys before treating list membership as harmless.

How do I prove we respected unsubscribes?

By being able to show that every send targeted a platform-maintained segment rather than an agent-built list. swy audit network gives you the arguments of every call that ran, which is the record that answers it. See how to log every API call an AI agent makes.

More content