What Can Go Wrong
A script sends exactly what its code says, while an agent decides what to send from instructions and data that nobody fully controls. That opens risks a script does not have:
A better prompt does not remove any of these. The controls below are limits Lettr enforces, so they hold whatever the agent decides.
How Agents Reach Lettr
Lettr hosts a remote MCP server athttps://app.lettr.com/mcp. It accepts either a Lettr sign-in (OAuth) or a lttr_ API key sent as Authorization: Bearer lttr_.... Each tool maps to the same operation as a REST endpoint.
The two ways of connecting give you very different control:
For an agent you want to restrict, use a key. OAuth gives the assistant everything you can do in the dashboard, so it suits supervised, personal use rather than an autonomous agent.
Give the Agent the Least Access It Needs
Choose a Permission Level
Every key is one of two permission levels, picked when you create it under API Keys:
A Sending only key that calls any other endpoint gets
403 with error_code: insufficient_scope. The level is a preset of scopes, and you cannot pick scopes one by one. See Permissions for the full scope list.
For an agent whose job is to send, such as a support assistant that emails order updates or a workflow that sends a template, use Sending only.
What the Agent Sees through MCP
The server checks the key on every request and hides tools the key has no scope for, so an agent never offers an action it cannot perform. Each tool needs the same scope as its REST endpoint.
Two details matter for safety:
- A tool that declares no scope is unavailable to every key. A new tool cannot reach key-authenticated agents by accident.
list_api_keysandbrowse_api_logsare never available to a key. An agent holding a key cannot list your other keys.
Rehearse With a Sandbox Key
Before an agent touches real recipients, run it on a sandbox key. Create one under API Keys by setting Type to Sandbox. Sandbox keys start withlttr_sandbox_.
A sandbox key behaves like a live key with its email sends contained:
- Recipients are replaced. Every
to,ccandbccaddress becomes the email address of the user who created the key, whatever the agent asked for. - The sender domain is replaced. The
fromdomain becomesdev.uselettr.com, so no verified sending domain is needed. - Most writes are blocked. On REST, a sandbox key can send email and read, but creating, updating or deleting templates, domains, webhooks and similar resources is refused, and so are SMS and WhatsApp sends. On MCP, any tool that needs a
:writescope is unavailable to a sandbox key. - Email sends are isolated. Sandbox email sends use a separate subaccount, do not count toward your sending quota, and do not trigger your webhooks.
POST /events. Over MCP, send_event stays available to a Full access sandbox key, and the event it sends is not redirected, so it can start automations that email real recipients. A Sending only sandbox key does not hold the events:send scope, so send_event is not available to it.
For that reason, rehearse on a sandbox key with Sending only permissions. It holds only the sending scopes, so the agent has the send and schedule tools and nothing that acts on your audience or automations.
To see what the agent sent, open the Events page in the dashboard and turn on the Sandbox toggle. Sandbox events are not shown without it.
Sandbox keys have their own rate limits, separate from your team’s live traffic. See Sandbox API Keys for the figures.
Restrict Where the Key Can Be Used
A key can be limited to specific source addresses. In the Allowed IPs field, enter comma-separated IP addresses or CIDR ranges, for example10.20.30.40, 10.20.30.0/24. Leave it blank to allow any address.
Requests from other addresses are refused with 403 and the message Access denied. Your IP address is not allowed. The same check applies to key-authenticated MCP connections.
This limits the value of a leaked key: for an agent that always runs from a known server or CI runner, a copy of the key does not work from any other address.
Make Retries Safe
When a tool call times out, the model often cannot tell whether the email went out, so agents tend to retry the send. Bothsend_email and send_template_email accept an idempotency_key. Reuse the same value on a retry and Lettr does not send the email a second time. Without it, a retry after a timeout can send the email twice.
The key must be 1 to 255 characters, using letters, digits, periods, underscores and hyphens. Instruct the agent to derive it from the business event, not to generate a fresh one on each attempt:
Keep a Human in the Loop for Risky Actions
Tools that send email, overwrite data or delete it carry the MCP destructive annotation, includingsend_email, send_template_email, cancel_scheduled_email and send_campaign. Clients that support the annotation, such as Claude, can ask you to approve each call before it runs.
Check the recipients, the template and the audience in each prompt before approving it. For an unattended agent there is no prompt, so the key’s permission level and a sandbox rehearsal are the controls that count.
If the agent works across several teams through OAuth, pin the team in the connection URL (https://app.lettr.com/mcp?team=41) so it cannot act on another one. A key is already bound to a single team.
Protect the Key
A key in a client config file is a plain-text password.- Use a separate key per agent, named for its job, so you can revoke one without affecting others.
- Keep config files that hold keys out of version control.
- Revoke a key by deleting it.
- Key-authenticated MCP calls appear in your API logs with the key’s id. Filter by key name under Logs to see what an agent has done.
A Safe Setup, End to End
For an agent that sends order updates:1
Rehearse on a sandbox key
Create a sandbox key with Sending only permissions, named
order-agent-test. Connect the agent, run the real task several times and read the emails in your own inbox (subject, body, merge data, tone). Check the Events page with the Sandbox toggle for anything unexpected.2
Create the live key
Create a Sending only live key named
order-agent-prod, with Allowed IPs set to the server that runs the agent.3
Connect the agent
In Claude Code:
4
Set the sending rules
Tell the agent to use saved templates and to set an
idempotency_key on every send.5
Watch the first live runs
Start with a small, low-stakes workflow and follow it in Logs and Events.
Related Topics
Connect with an API Key
Set up key-based MCP access and see what each key can reach
API Key Permissions
Permission levels, scopes and IP restrictions
Sandbox API Keys
Test email sends without reaching real recipients
Security Best Practices
Protect your API keys, webhooks, and account