MCP Server

Connect AI clients to BYOMailer through the Model Context Protocol. An assistant can pull your newsletter and sequence stats and content, and help you compose a newsletter — preview the audience, save a draft and send yourself a test. It can never send a campaign to your audience: drafts are only sent after you review and schedule them yourself.

Endpoint & Authentication

The server is served over streamable HTTP at https://byomailer.com/mcp and is authenticated with the same API tokens used by the REST API. Generate a token in your account settings and send it as a bearer token on every request.

Transport

Streamable HTTP. Point any MCP-compatible client at /mcp with an Authorization header.

Bearer Token

Use a personal API token: Authorization: Bearer YOUR_API_TOKEN. Requests are rate limited.

No surprise sends

The assistant can read your campaigns and create drafts, but it can never send to your audience — drafts only go out after you review and schedule them yourself.

Connect a Client

Command-line clients

If your client has a CLI, register the server in one command. For Claude Code:

Claude Code

claude mcp add byomailer \
  --transport http https://byomailer.com/mcp \
  --header "Authorization: Bearer YOUR_API_TOKEN"

For the Codex CLI and other tools that accept a streamable-HTTP server with custom headers:

Codex CLI

codex mcp add byomailer \
  --transport http \
  --url https://byomailer.com/mcp \
  --header "Authorization: Bearer YOUR_API_TOKEN"

Any client that speaks streamable HTTP and lets you set an Authorization header will work — point it at https://byomailer.com/mcp with Bearer YOUR_API_TOKEN. Run the client's mcp list equivalent afterwards to confirm the tools are discovered.

Config-file clients

For clients configured by JSON (Claude Desktop, Cursor and similar), add BYOMailer to the mcpServers block:

mcp.json

{
  "mcpServers": {
    "byomailer": {
      "type": "http",
      "url": "https://byomailer.com/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_TOKEN"
      }
    }
  }
}

Calling a Tool

Clients invoke tools with a standard MCP tools/call request. The name is the tool name below and arguments matches its input schema. Most clients build this request for you — you just describe what you want.

tools/call

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "newsletter-stats",
    "arguments": { "newsletter_id": 42 }
  }
}

Tools

Thirty-three tools. Start with a list tool to discover ids, then read stats or content — use view-newsletter-filters, calculate-newsletter-contacts, create-newsletter, update-newsletter and send-newsletter-test-mail to compose and revise a draft newsletter, or create-sequence, create-sequence-step, update-sequence-step and send-sequence-step-test-mail to draft, revise and preview a drip campaign. create-tag adds a tag for labelling contacts. find-contact, create-contact, add-contact-to-list, add-tags-to-contact and remove-contact-from-list add people to lists and tags. list-email-identities, email-identity-details, create-email-identity, refresh-email-identity-status and update-email-identity-tracking manage the sender identities (verified sending domains) in your own AWS SES. list-automations, automation-details, view-automation-options, create-automation and update-automation manage automations. New automations are always paused, and only the dashboard can turn them on.

list-newsletters

List the account's newsletters so you can find an id to read stats or content for.

Arguments

statusstring

Filter by status: draft, scheduled, queued, ab_testing, sent or failed.

searchstring

Case-insensitive match against title and subject.

limitinteger

Max rows to return, 1-100 (default 25).

Returns

newslettersarray

Matching newsletters, newest first.

idinteger

Newsletter id.

titlestring

Internal title.

statusstring

Current status.

subjectstring|null

Subject of the primary message.

sent_atstring|null

ISO 8601 send time.

countinteger

Number of rows returned.

Example result

{
  "newsletters": [
    {
      "id": 42,
      "title": "June product update",
      "status": "sent",
      "subject": "What's new this month",
      "sent_at": "2026-06-01T09:00:00+00:00"
    }
  ],
  "count": 1
}
newsletter-stats

Delivery and engagement metrics for one newsletter. Includes A/B variant metrics when A/B testing is enabled.

Arguments

newsletter_idinteger
required

The newsletter to read stats for.

Returns

idinteger

Newsletter id.

titlestring

Internal title.

statusstring

Current status.

sent_atstring|null

ISO 8601 send time.

metricsobject

Aggregate engagement metrics.

totalinteger

Recipients reached.

sentinteger

Messages handed to SES.

deliveredinteger

Confirmed delivered.

pendinginteger

Not yet sent.

openedinteger

Opened at least once.

bouncedinteger

Hard or soft bounces.

unsubscribedinteger

Unsubscribed from this mail.

complainedinteger

Marked as spam.

delivery_ratefloat|null

delivered / sent as a percentage.

open_ratefloat|null

opened / sent as a percentage.

unsubscribe_ratefloat|null

unsubscribed / sent as a percentage.

ab_metricsobject|null

Per-variant open/click metrics (a and b) when A/B testing is on, otherwise null.

Example result

{
  "id": 42,
  "title": "June product update",
  "status": "sent",
  "sent_at": "2026-06-01T09:00:00+00:00",
  "metrics": {
    "total": 1240,
    "sent": 1240,
    "delivered": 1228,
    "pending": 0,
    "opened": 612,
    "bounced": 12,
    "unsubscribed": 4,
    "complained": 0,
    "delivery_rate": 99,
    "open_rate": 49.4,
    "unsubscribe_rate": 0.3
  },
  "ab_metrics": null
}
newsletter-content

Full subject, sender and body of one newsletter, plus the B variant content when A/B testing is enabled.

Arguments

newsletter_idinteger
required

The newsletter to read content for.

Returns

idinteger

Newsletter id.

titlestring

Internal title.

statusstring

Current status.

subjectstring|null

Subject line.

preview_textstring|null

Inbox preheader.

from_emailstring|null

Sender email.

from_namestring|null

Sender name.

html_contentstring|null

Rendered HTML body.

text_contentstring|null

Plain-text body.

content_variablesobject

Default values for template variables.

ab_test_enabledboolean

Whether A/B testing is on.

subject_b / preview_text_b / html_content_bstring|null

B variant content when A/B testing is enabled.

Example result

{
  "id": 42,
  "title": "June product update",
  "status": "sent",
  "subject": "What's new this month",
  "preview_text": "Read receipts, faster sends, and more",
  "from_email": "[email protected]",
  "from_name": "Acme",
  "html_content": "<p>Hi {{ name }}, here is what shipped…</p>",
  "text_content": "Hi {{ name }}, here is what shipped…",
  "content_variables": {
    "name": "there"
  },
  "ab_test_enabled": false,
  "subject_b": null,
  "preview_text_b": null,
  "html_content_b": null
}
view-newsletter-filters

Describe the audience targeting filters available to your account: the filter schema (categories, operators, modes) plus the concrete tags, lists, topics, attribute keys, countries, timezones and newsletters you can reference. Use it before building a filters array for calculate-newsletter-contacts or create-newsletter.

Returns

schemaobject

Allowed categories, operators, modes and windows.

availableobject

Your account's tags, lists, topics, attributes, countries, timezones and newsletters.

Example result

{
  "schema": {
    "categories": [
      "attributes",
      "tags",
      "lists",
      "topics",
      "date",
      "engagement",
      "location"
    ],
    "modes": [
      "all",
      "any",
      "none"
    ],
    "engagement_operators": [
      "opened",
      "clicked",
      "received",
      "not_opened",
      "not_clicked",
      "not_received"
    ]
  },
  "available": {
    "tags": [
      "vip",
      "beta"
    ],
    "lists": [
      {
        "id": 3,
        "name": "Subscribers"
      }
    ],
    "topics": [
      {
        "id": 7,
        "name": "Product updates"
      }
    ],
    "attributes": [
      "plan",
      "country"
    ],
    "countries": [
      "US",
      "GB"
    ],
    "timezones": [
      "America/New_York"
    ],
    "newsletters": [
      {
        "id": 42,
        "title": "June product update"
      }
    ]
  }
}
calculate-newsletter-contacts

Count how many contacts a set of audience filters would reach, without creating or sending anything. Pass the same filters you would use with create-newsletter; omit them to count every active (non-unsubscribed) contact.

Arguments

filtersarray

Targeting filters (max 20). Same shape as create-newsletter. Omit to count all active contacts.

Returns

countinteger

Contacts that match the filters.

applied_filtersarray

The sanitized filters that were actually applied.

Example result

{
  "count": 318,
  "applied_filters": [
    {
      "connector": "and",
      "category": "tags",
      "mode": "any",
      "values": [
        "vip"
      ]
    }
  ]
}
create-newsletter

Create a draft newsletter. Drafts are never sent automatically — you review, edit and schedule them yourself in the dashboard. Optionally attach a sender identity, template and audience filters.

Arguments

titlestring

Internal title. Defaults to "Untitled newsletter".

subjectstring

Email subject line. Supports {{ variables }}.

preview_textstring

Inbox preheader text.

html_contentstring

HTML body. Plain-text is derived automatically.

email_identity_idinteger

Verified sender identity id. Required before the draft can be scheduled or test-mailed.

email_template_idinteger

Optional template id to wrap the content.

filtersarray

Audience targeting filters (max 20). Omit to target every active contact.

Returns

idinteger

New newsletter id.

titlestring

Internal title.

statusstring

Always "draft".

messagestring

Human-readable confirmation.

Example result

{
  "id": 57,
  "title": "June product update",
  "status": "draft",
  "message": "Draft newsletter #57 created."
}
update-newsletter

Update an existing draft newsletter. Only newsletters still in "draft" status can be edited — once a newsletter is scheduled or sent it is locked. The status never changes: edited newsletters stay drafts. Only the fields you pass are changed; omitted fields keep their current values.

Arguments

newsletter_idinteger
required

The draft newsletter to update. Find ids with list-newsletters.

titlestring

Internal title.

subjectstring

Email subject line. Supports {{ variables }}.

preview_textstring

Inbox preheader text.

html_contentstring

HTML body. Plain-text is derived automatically.

email_identity_idinteger

Verified sender identity id. Required before the draft can be scheduled or test-mailed.

email_template_idinteger

Optional template id to wrap the content.

filtersarray

Audience targeting filters (max 20). Omit to leave the audience unchanged.

Returns

idinteger

Newsletter id.

titlestring

Internal title.

statusstring

Always "draft".

messagestring

Human-readable confirmation.

Example result

{
  "id": 57,
  "title": "June product update (v2)",
  "status": "draft",
  "message": "Draft newsletter #57 updated."
}
send-newsletter-test-mail

Send a one-off test copy of a newsletter to your own email address so you can preview it. The newsletter must already have a sender identity attached. Does not send to the newsletter audience.

Arguments

newsletter_idinteger
required

The newsletter to send a test copy of.

Returns

messagestring

Confirmation message.

sent_tostring

The address the test was sent to (your own).

Example result

{
  "message": "Test email sent to [email protected]",
  "sent_to": "[email protected]"
}
list-sequences

List the account's sequences so you can find an id to read stats or content for.

Arguments

statusstring

Filter by status: draft, live or paused.

searchstring

Case-insensitive match against the sequence name.

limitinteger

Max rows to return, 1-100 (default 25).

Returns

sequencesarray

Matching sequences, live first.

idinteger

Sequence id.

namestring

Sequence name.

statusstring

Current status.

steps_countinteger

Number of steps.

contacts_countinteger

Enrolled contacts.

countinteger

Number of rows returned.

Example result

{
  "sequences": [
    {
      "id": 7,
      "name": "Onboarding",
      "status": "live",
      "steps_count": 4,
      "contacts_count": 318
    }
  ],
  "count": 1
}
create-sequence

Create a draft sequence (automated drip campaign). Sequences are always created as drafts and can never be activated through the MCP API — going live happens in the dashboard. Pass filters to limit which contacts receive the sequence. Add steps with create-sequence-step.

Arguments

namestring
required

Name for the sequence.

filtersarray

Sequence filters in the view-newsletter-filters format. Only contacts who match them receive the sequence. Omit to target every active contact.

Returns

idinteger

New sequence id.

namestring

Sequence name.

statusstring

Always "draft".

filtersarray

The saved sequence filters. Filters that point to lists, tags or topics of another account are removed.

messagestring

Human-readable confirmation.

Example result

{
  "id": 12,
  "name": "Onboarding drip",
  "status": "draft",
  "filters": [
    {
      "connector": "and",
      "category": "tags",
      "mode": "any",
      "values": [
        "vip"
      ]
    }
  ],
  "message": "Draft sequence #12 created. Add steps with create-sequence-step."
}
update-sequence

Update an existing draft sequence. Only draft sequences can be edited — live sequences are locked and the tool returns an error. The status never changes. Only the fields you pass are changed. Filters and a saved segment are exclusive, so passing filters removes a saved segment from the sequence.

Arguments

sequence_idinteger
required

Id of the draft sequence to update. Discover ids with list-sequences.

namestring

New name for the sequence.

filtersarray

Sequence filters in the view-newsletter-filters format. The array replaces the current filters. Pass an empty array to clear them.

Returns

idinteger

Sequence id.

namestring

Sequence name.

statusstring

Always "draft".

filtersarray

The saved sequence filters.

messagestring

Human-readable confirmation.

Example result

{
  "id": 12,
  "name": "Onboarding drip — VIP",
  "status": "draft",
  "filters": [
    {
      "connector": "and",
      "category": "lists",
      "mode": "any",
      "values": [
        3
      ]
    }
  ],
  "message": "Draft sequence #12 updated."
}
create-sequence-step

Add a draft step to an existing sequence. Steps are always created as drafts and can never be activated through the MCP API — make a step live from the dashboard. Set the delay before it sends relative to the previous step.

Arguments

sequence_idinteger
required

The sequence to add the step to.

delay_typestring
required

Unit for the delay: "days" or "hours".

delay_daysinteger
required

Days (max 365) or hours (max 8760) after the previous step. Use 0 to send on enrollment for the first step.

email_identity_idinteger
required

Verified sender identity id to send this step from.

subjectstring

Email subject line. Supports {{ variables }}.

preview_textstring

Inbox preheader text.

html_contentstring

HTML body. Plain-text is derived automatically.

Returns

idinteger

New step id.

sequence_idinteger

Parent sequence id.

statusstring

Always "draft".

messagestring

Human-readable confirmation.

Example result

{
  "id": 48,
  "sequence_id": 12,
  "status": "draft",
  "message": "Draft step #48 added to sequence #12."
}
update-sequence-step

Update an existing draft step. Only draft steps can be edited — live steps are locked and the tool returns an error. The status never changes: edited steps stay drafts. Only the fields you pass are changed; omitted fields keep their current values. Pair delay_type and delay_days to reschedule.

Arguments

sequence_step_idinteger
required

Id of the draft step to update. Discover ids with sequence-content.

delay_typestring

Unit for the delay: "days" or "hours". Required together with delay_days.

delay_daysinteger

Days (max 365) or hours (max 8760) after the previous step. Required together with delay_type.

email_identity_idinteger

Verified sender identity id to send this step from.

email_template_idinteger

Email template id to wrap the content. Pass null to remove the template.

subjectstring

Email subject line. Supports {{ variables }}.

preview_textstring

Inbox preheader text.

html_contentstring

HTML body. Plain-text is derived automatically.

Returns

idinteger

Step id.

sequence_idinteger

Parent sequence id.

statusstring

Always "draft".

messagestring

Human-readable confirmation.

Example result

{
  "id": 48,
  "sequence_id": 12,
  "status": "draft",
  "message": "Draft step #48 updated."
}
sequence-stats

Sequence-level totals and aggregate mail metrics across all steps. For a per-step breakdown use sequence-step-stats.

Arguments

sequence_idinteger
required

The sequence to read stats for.

Returns

idinteger

Sequence id.

namestring

Sequence name.

statusstring

Current status.

statsobject

Sequence-wide contact/unsubscribe/click totals.

contactsinteger

Distinct contacts enrolled.

unsubscribedinteger

Distinct contacts who unsubscribed.

clickedinteger

Distinct contacts who clicked.

mail_metricsobject

Aggregate metrics across every step.

totalinteger

Recipients reached.

sentinteger

Messages handed to SES.

deliveredinteger

Confirmed delivered.

pendinginteger

Not yet sent.

openedinteger

Opened at least once.

bouncedinteger

Hard or soft bounces.

unsubscribedinteger

Unsubscribed from this mail.

complainedinteger

Marked as spam.

delivery_ratefloat|null

delivered / sent as a percentage.

open_ratefloat|null

opened / sent as a percentage.

unsubscribe_ratefloat|null

unsubscribed / sent as a percentage.

Example result

{
  "id": 7,
  "name": "Onboarding",
  "status": "live",
  "stats": {
    "contacts": 318,
    "unsubscribed": 6,
    "clicked": 121
  },
  "mail_metrics": {
    "total": 1180,
    "sent": 1180,
    "delivered": 1170,
    "pending": 0,
    "opened": 540,
    "bounced": 10,
    "unsubscribed": 6,
    "complained": 0,
    "delivery_rate": 99.2,
    "open_rate": 45.8,
    "unsubscribe_rate": 0.5
  }
}
sequence-content

Full content of a sequence and every one of its steps.

Arguments

sequence_idinteger
required

The sequence to read content for.

Returns

idinteger

Sequence id.

namestring

Sequence name.

statusstring

Current status.

contacts_countinteger

Enrolled contacts.

steps_countinteger

Number of steps.

content_variablesobject

Default values for template variables.

stepsarray

Steps in send order.

idinteger

Step id.

delay_daysinteger

Delay before this step.

delay_typestring

Unit of the delay (e.g. days).

statusstring

Step status.

messageobject|null

Step message content.

Example result

{
  "id": 7,
  "name": "Onboarding",
  "status": "live",
  "contacts_count": 318,
  "steps_count": 4,
  "content_variables": {
    "name": "there"
  },
  "steps": [
    {
      "id": 31,
      "delay_days": 0,
      "delay_type": "days",
      "status": "live",
      "message": {
        "id": 88,
        "subject": "Welcome aboard",
        "preview_text": "Glad you are here",
        "html_content": "<p>Hi {{ name }}…</p>",
        "text_content": "Hi {{ name }}…",
        "email_identity_id": 3
      }
    }
  ]
}
send-sequence-step-test-mail

Send a one-off test copy of a single sequence step to your own email address so you can preview it. The step must already have a sender identity attached. Does not send to the sequence audience and does not start or advance the sequence for anyone.

Arguments

sequence_idinteger
required

The sequence the step belongs to.

step_idinteger
required

The step to send a test copy of.

Returns

messagestring

Confirmation message.

sent_tostring

The address the test was sent to (your own).

Example result

{
  "message": "Test email sent to [email protected]",
  "sent_to": "[email protected]"
}
sequence-step-content

Full content of a single sequence step.

Arguments

sequence_idinteger
required

The sequence the step belongs to.

step_idinteger
required

The step to read content for.

Returns

idinteger

Step id.

sequence_idinteger

Parent sequence id.

delay_daysinteger

Delay before this step.

delay_typestring

Unit of the delay (e.g. days).

statusstring

Step status.

messageobject|null

Step message content.

subjectstring

Subject line, may contain {{ variables }}.

preview_textstring|null

Inbox preheader.

html_contentstring

Rendered HTML body.

text_contentstring

Plain-text body.

email_identityobject|null

Sending identity (from name/email).

Example result

{
  "id": 31,
  "sequence_id": 7,
  "delay_days": 0,
  "delay_type": "days",
  "status": "live",
  "message": {
    "id": 88,
    "subject": "Welcome aboard",
    "preview_text": "Glad you are here",
    "html_content": "<p>Hi {{ name }}…</p>",
    "text_content": "Hi {{ name }}…",
    "email_identity": {
      "id": 3,
      "name": "Acme",
      "email": "[email protected]"
    }
  }
}
sequence-step-stats

Delivery and engagement stats for a single sequence step. Contacts are counted in the furthest step they have reached.

Arguments

sequence_idinteger
required

The sequence the step belongs to.

step_idinteger
required

The step to read stats for.

Returns

idinteger

Step id.

sequence_idinteger

Parent sequence id.

subjectstring|null

Step subject.

delay_daysinteger

Delay before this step.

delay_typestring

Unit of the delay (e.g. days).

statusstring

Step status.

statsobject

Contacts/unsubscribed/clicked for this step.

contactsinteger

Distinct contacts enrolled.

unsubscribedinteger

Distinct contacts who unsubscribed.

clickedinteger

Distinct contacts who clicked.

mail_metricsobject

Mail metrics for this step.

totalinteger

Recipients reached.

sentinteger

Messages handed to SES.

deliveredinteger

Confirmed delivered.

pendinginteger

Not yet sent.

openedinteger

Opened at least once.

bouncedinteger

Hard or soft bounces.

unsubscribedinteger

Unsubscribed from this mail.

complainedinteger

Marked as spam.

delivery_ratefloat|null

delivered / sent as a percentage.

open_ratefloat|null

opened / sent as a percentage.

unsubscribe_ratefloat|null

unsubscribed / sent as a percentage.

Example result

{
  "id": 31,
  "sequence_id": 7,
  "subject": "Welcome aboard",
  "delay_days": 0,
  "delay_type": "days",
  "status": "live",
  "stats": {
    "contacts": 318,
    "unsubscribed": 2,
    "clicked": 80
  },
  "mail_metrics": {
    "total": 318,
    "sent": 318,
    "delivered": 316,
    "pending": 0,
    "opened": 190,
    "bounced": 2,
    "unsubscribed": 2,
    "complained": 0,
    "delivery_rate": 99.4,
    "open_rate": 59.7,
    "unsubscribe_rate": 0.6
  }
}
create-tag

Create a tag for the account. Tags label contacts and build audiences. Tag names are unique per account — creating a name that already exists returns an error.

Arguments

namestring
required

The tag name. Must be unique within the account.

Returns

idinteger

New tag id.

namestring

The tag name.

messagestring

Human-readable confirmation.

Example result

{
  "id": 9,
  "name": "VIP",
  "message": "Tag #9 created."
}
find-contact

Look up one contact by exact email. Returns that person even when they are unsubscribed, or contact null when this account has no such email.

Arguments

emailstring
required

Exact email address to look up in this account.

Returns

contactobject

The contact, or null. When present: id, email, name, unsubscribed_at, tags, and list ids.

Example result

{
  "contact": {
    "id": 42,
    "email": "[email protected]",
    "name": "Ada",
    "unsubscribed_at": null,
    "tags": [
      "VIP"
    ],
    "lists": [
      3
    ]
  }
}
create-contact

Create a contact, or reuse the contact that already has this email. Optional name, tag names, and one list. A new blacklisted email is rejected. Tags are added and never removed. A list that requires opt-in queues the opt-in email.

Arguments

emailstring
required

Email address. Reuses the account contact with this exact email when one exists.

namestring

Optional display name. Omitted leaves the current name unchanged.

tagsarray

Optional tag names to add. Unknown names are created. Existing tags stay. Tag removal is not available.

list_idinteger

Optional mailing list id from view-newsletter-filters.

Returns

idinteger

Contact id.

createdboolean

True when a new contact row was inserted.

emailstring

The contact email.

namestring

The contact name.

tagsarray

Tag names on the contact.

listsarray

Mailing list ids the contact belongs to.

messagestring

Human-readable confirmation.

Example result

{
  "id": 42,
  "email": "[email protected]",
  "name": "Ada",
  "unsubscribed_at": null,
  "tags": [
    "VIP"
  ],
  "lists": [
    3
  ],
  "created": true,
  "message": "Contact #42 created."
}
add-contact-to-list

Add an existing contact to a mailing list without removing their other lists. A list that requires opt-in queues the opt-in email. Tag removal is not available through this API.

Arguments

contact_idinteger
required

Contact id from find-contact.

list_idinteger
required

Mailing list id from view-newsletter-filters.

Returns

idinteger

Contact id.

listsarray

Mailing list ids the contact belongs to.

messagestring

Human-readable confirmation.

Example result

{
  "id": 42,
  "email": "[email protected]",
  "name": "Ada",
  "unsubscribed_at": null,
  "tags": [
    "VIP"
  ],
  "lists": [
    3,
    8
  ],
  "message": "Contact #42 added to list #8."
}
add-tags-to-contact

Add tags to an existing contact by name. Existing tags stay. A name that does not exist yet is created. Removing a tag is not available through this API.

Arguments

contact_idinteger
required

Contact id from find-contact.

tagsarray
required

Tag names to add.

Returns

idinteger

Contact id.

tagsarray

Tag names on the contact.

messagestring

Human-readable confirmation.

Example result

{
  "id": 42,
  "email": "[email protected]",
  "name": "Ada",
  "unsubscribed_at": null,
  "tags": [
    "Customer",
    "VIP"
  ],
  "lists": [
    3
  ],
  "message": "Tags added to contact #42."
}
remove-contact-from-list

Remove a contact from one mailing list. Their other lists stay, and the contact is not deleted.

Arguments

contact_idinteger
required

Contact id from find-contact.

list_idinteger
required

Mailing list id to remove them from.

Returns

idinteger

Contact id.

listsarray

Mailing list ids the contact still belongs to.

messagestring

Human-readable confirmation.

Example result

{
  "id": 42,
  "email": "[email protected]",
  "name": "Ada",
  "unsubscribed_at": null,
  "tags": [
    "VIP"
  ],
  "lists": [
    3
  ],
  "message": "Contact #42 removed from list #8."
}
list-email-identities

List the sender identities (verified sending domains) of the account with their verification status, DKIM and MAIL FROM status and tracking flags. Only identities with identity_status verified can send mail.

Arguments

identity_statusstring

Optional filter: pending, verifying, verified or failed.

searchstring

Optional search against email, name and domain.

limitinteger

Maximum identities to return (1-100, default 25).

Returns

identitiesarray

Identity summaries. Each item carries the fields of email-identity-details minus mail_from_subdomain, region, custom link domain and dns_records.

countinteger

Number of identities returned.

Example result

{
  "identities": [
    {
      "id": 3,
      "email": "[email protected]",
      "name": "Example Team",
      "domain": "example.com",
      "identity_status": "verifying",
      "dkim_status": "PENDING",
      "mail_from_status": "PENDING",
      "open_tracking_enabled": true,
      "click_tracking_enabled": true,
      "verified_at": null,
      "last_status_check_at": "2026-09-19T10:00:00+00:00"
    }
  ],
  "count": 1
}
email-identity-details

Show one sender identity in full, including the DNS records (DKIM CNAMEs, MAIL FROM MX/TXT and DMARC TXT) the domain owner must publish, each with a verified flag. Use it to guide someone through DNS setup.

Arguments

email_identity_idinteger
required

The identity id from list-email-identities.

Returns

idinteger

Identity id.

emailstring

Sender email address.

namestring|null

Sender display name.

domainstring

Domain registered in SES.

identity_statusstring

pending, verifying, verified or failed. Only verified identities can send.

dkim_statusstring

PENDING or SUCCESS.

mail_from_statusstring

PENDING or SUCCESS.

open_tracking_enabledboolean

Whether opens are tracked.

click_tracking_enabledboolean

Whether clicks are tracked.

verified_atstring|null

ISO-8601 timestamp of verification.

last_status_check_atstring|null

ISO-8601 timestamp of the last AWS status check.

mail_from_subdomainstring|null

MAIL FROM subdomain, for example mas.example.com.

regionstring

AWS region of the identity.

custom_link_domainstring|null

Custom link domain, when configured.

custom_link_domain_verifiedboolean

Whether the custom link domain is verified.

dns_recordsarray

DNS records to publish: type, name, value, priority, purpose (dkim, mail_from, dmarc) and verified.

Example result

{
  "id": 3,
  "email": "[email protected]",
  "name": "Example Team",
  "domain": "example.com",
  "identity_status": "verifying",
  "dkim_status": "PENDING",
  "mail_from_status": "PENDING",
  "open_tracking_enabled": true,
  "click_tracking_enabled": true,
  "verified_at": null,
  "last_status_check_at": "2026-09-19T10:00:00+00:00",
  "mail_from_subdomain": "mas.example.com",
  "region": "us-east-1",
  "custom_link_domain": null,
  "custom_link_domain_verified": false,
  "dns_records": [
    {
      "type": "CNAME",
      "name": "abc123._domainkey.example.com",
      "value": "abc123.dkim.amazonses.com",
      "priority": null,
      "purpose": "dkim",
      "verified": false
    },
    {
      "type": "MX",
      "name": "mas.example.com",
      "value": "feedback-smtp.us-east-1.amazonses.com",
      "priority": 10,
      "purpose": "mail_from",
      "verified": false
    },
    {
      "type": "TXT",
      "name": "mas.example.com",
      "value": "v=spf1 include:amazonses.com ~all",
      "priority": null,
      "purpose": "mail_from",
      "verified": false
    },
    {
      "type": "TXT",
      "name": "_dmarc.example.com",
      "value": "v=DMARC1; p=none;",
      "priority": null,
      "purpose": "dmarc",
      "verified": false
    }
  ]
}
create-email-identity

Create a sender identity. Registers the email domain in your own AWS SES, sets up a MAIL FROM subdomain and a per-identity configuration set, and returns the DNS records to publish. Requires AWS credentials configured in the dashboard. Set existing_aws_identity to import a domain that is already verified in SES.

Arguments

emailstring
required

Sender email address. Its domain is registered in SES.

namestring

Optional sender display name.

existing_aws_identityboolean

Import a domain that already exists in SES instead of creating it. Default false.

open_tracking_enabledboolean

Track opens. Default true.

click_tracking_enabledboolean

Track clicks. Default true.

mail_from_subdomainstring

Optional lowercase MAIL FROM subdomain. Default mas.<domain>.

Returns

idinteger

Identity id.

emailstring

Sender email address.

namestring|null

Sender display name.

domainstring

Domain registered in SES.

identity_statusstring

pending, verifying, verified or failed. Only verified identities can send.

dkim_statusstring

PENDING or SUCCESS.

mail_from_statusstring

PENDING or SUCCESS.

open_tracking_enabledboolean

Whether opens are tracked.

click_tracking_enabledboolean

Whether clicks are tracked.

verified_atstring|null

ISO-8601 timestamp of verification.

last_status_check_atstring|null

ISO-8601 timestamp of the last AWS status check.

mail_from_subdomainstring|null

MAIL FROM subdomain, for example mas.example.com.

regionstring

AWS region of the identity.

custom_link_domainstring|null

Custom link domain, when configured.

custom_link_domain_verifiedboolean

Whether the custom link domain is verified.

dns_recordsarray

DNS records to publish: type, name, value, priority, purpose (dkim, mail_from, dmarc) and verified.

messagestring

Human-readable confirmation with the next step.

Example result

{
  "id": 3,
  "email": "[email protected]",
  "name": "Example Team",
  "domain": "example.com",
  "identity_status": "pending",
  "dkim_status": "PENDING",
  "mail_from_status": "PENDING",
  "open_tracking_enabled": true,
  "click_tracking_enabled": true,
  "verified_at": null,
  "last_status_check_at": null,
  "mail_from_subdomain": "mas.example.com",
  "region": "us-east-1",
  "custom_link_domain": null,
  "custom_link_domain_verified": false,
  "dns_records": [
    {
      "type": "CNAME",
      "name": "abc123._domainkey.example.com",
      "value": "abc123.dkim.amazonses.com",
      "priority": null,
      "purpose": "dkim",
      "verified": false
    },
    {
      "type": "MX",
      "name": "mas.example.com",
      "value": "feedback-smtp.us-east-1.amazonses.com",
      "priority": 10,
      "purpose": "mail_from",
      "verified": false
    },
    {
      "type": "TXT",
      "name": "mas.example.com",
      "value": "v=spf1 include:amazonses.com ~all",
      "priority": null,
      "purpose": "mail_from",
      "verified": false
    },
    {
      "type": "TXT",
      "name": "_dmarc.example.com",
      "value": "v=DMARC1; p=none;",
      "priority": null,
      "purpose": "dmarc",
      "verified": false
    }
  ],
  "message": "Identity #3 created. Publish the DNS records, then call refresh-email-identity-status."
}
refresh-email-identity-status

Ask AWS SES for the current verification state of an identity and sync it: identity status, DKIM status, MAIL FROM status and the verified flag on each DNS record. Call it after the DNS records are published.

Arguments

email_identity_idinteger
required

The identity id.

Returns

idinteger

Identity id.

emailstring

Sender email address.

namestring|null

Sender display name.

domainstring

Domain registered in SES.

identity_statusstring

pending, verifying, verified or failed. Only verified identities can send.

dkim_statusstring

PENDING or SUCCESS.

mail_from_statusstring

PENDING or SUCCESS.

open_tracking_enabledboolean

Whether opens are tracked.

click_tracking_enabledboolean

Whether clicks are tracked.

verified_atstring|null

ISO-8601 timestamp of verification.

last_status_check_atstring|null

ISO-8601 timestamp of the last AWS status check.

mail_from_subdomainstring|null

MAIL FROM subdomain, for example mas.example.com.

regionstring

AWS region of the identity.

custom_link_domainstring|null

Custom link domain, when configured.

custom_link_domain_verifiedboolean

Whether the custom link domain is verified.

dns_recordsarray

DNS records to publish: type, name, value, priority, purpose (dkim, mail_from, dmarc) and verified.

messagestring

Human-readable status line.

Example result

{
  "id": 3,
  "email": "[email protected]",
  "name": "Example Team",
  "domain": "example.com",
  "identity_status": "verifying",
  "dkim_status": "PENDING",
  "mail_from_status": "PENDING",
  "open_tracking_enabled": true,
  "click_tracking_enabled": true,
  "verified_at": null,
  "last_status_check_at": "2026-09-19T10:00:00+00:00",
  "mail_from_subdomain": "mas.example.com",
  "region": "us-east-1",
  "custom_link_domain": null,
  "custom_link_domain_verified": false,
  "dns_records": [
    {
      "type": "CNAME",
      "name": "abc123._domainkey.example.com",
      "value": "abc123.dkim.amazonses.com",
      "priority": null,
      "purpose": "dkim",
      "verified": false
    },
    {
      "type": "MX",
      "name": "mas.example.com",
      "value": "feedback-smtp.us-east-1.amazonses.com",
      "priority": 10,
      "purpose": "mail_from",
      "verified": false
    },
    {
      "type": "TXT",
      "name": "mas.example.com",
      "value": "v=spf1 include:amazonses.com ~all",
      "priority": null,
      "purpose": "mail_from",
      "verified": false
    },
    {
      "type": "TXT",
      "name": "_dmarc.example.com",
      "value": "v=DMARC1; p=none;",
      "priority": null,
      "purpose": "dmarc",
      "verified": false
    }
  ],
  "message": "Identity #3 is verifying."
}
update-email-identity-tracking

Turn open tracking and click tracking on or off for an identity. Updates the SES configuration set so future mail reports (or stops reporting) opens and clicks.

Arguments

email_identity_idinteger
required

The identity id.

open_tracking_enabledboolean
required

Whether to track opens.

click_tracking_enabledboolean
required

Whether to track clicks.

Returns

idinteger

Identity id.

emailstring

Sender email address.

namestring|null

Sender display name.

domainstring

Domain registered in SES.

identity_statusstring

pending, verifying, verified or failed. Only verified identities can send.

dkim_statusstring

PENDING or SUCCESS.

mail_from_statusstring

PENDING or SUCCESS.

open_tracking_enabledboolean

Whether opens are tracked.

click_tracking_enabledboolean

Whether clicks are tracked.

verified_atstring|null

ISO-8601 timestamp of verification.

last_status_check_atstring|null

ISO-8601 timestamp of the last AWS status check.

messagestring

Human-readable confirmation.

Example result

{
  "id": 3,
  "email": "[email protected]",
  "name": "Example Team",
  "domain": "example.com",
  "identity_status": "verifying",
  "dkim_status": "PENDING",
  "mail_from_status": "PENDING",
  "open_tracking_enabled": true,
  "click_tracking_enabled": false,
  "verified_at": null,
  "last_status_check_at": "2026-09-19T10:00:00+00:00",
  "message": "Tracking updated for identity #3."
}
list-automations

List the automations of the account with their trigger condition, actions and live flag. Condition and action values are raw ids. Use automation-details to see them with names.

Arguments

is_liveboolean

Optional filter: true for live automations, false for paused ones.

searchstring

Optional search against the automation name.

limitinteger

Maximum automations to return (1-100, default 25).

Returns

automationsarray

Automations, newest first. Each item has the fields of automation-details without the resolved names.

countinteger

Number of automations returned.

Example result

{
  "automations": [
    {
      "id": 12,
      "name": "Tag new customers",
      "type": "simple",
      "is_live": false,
      "condition": {
        "type": "contact_added_to_list",
        "value": 8
      },
      "actions": [
        {
          "type": "add_tag",
          "value": 5
        }
      ],
      "created_at": "2026-09-23T10:00:00+00:00",
      "updated_at": "2026-09-23T10:00:00+00:00"
    }
  ],
  "count": 1
}
automation-details

Show one automation. Each list, tag or sequence id in the condition and the actions comes with its name, or null when the item no longer exists.

Arguments

automation_idinteger
required

The automation id from list-automations.

Returns

idinteger

Automation id.

namestring

Automation name.

typestring

simple or multistep.

is_liveboolean

Whether the automation runs on contacts now.

conditionobject

The trigger: type and value (list, tag or sequence id), or attribute, operator and value for attribute_changed. Has a name for a list, tag or sequence.

actionsarray

The actions, in order: type and value (tag, list or sequence id), with a name.

created_atstring|null

ISO-8601 creation time.

updated_atstring|null

ISO-8601 time of the last change.

Example result

{
  "id": 12,
  "name": "Tag new customers",
  "type": "simple",
  "is_live": false,
  "condition": {
    "type": "contact_added_to_list",
    "value": 8,
    "name": "Customers"
  },
  "actions": [
    {
      "type": "add_tag",
      "value": 5,
      "name": "VIP"
    }
  ],
  "created_at": "2026-09-23T10:00:00+00:00",
  "updated_at": "2026-09-23T10:00:00+00:00"
}
view-automation-options

Describe the building blocks of an automation: the condition types, the action types, and the lists, tags, sequences and contact attributes that a condition or an action can use. An add_sequence action accepts only live sequences.

Returns

condition_typesarray

Each trigger type with a description of the value it needs.

action_typesarray

Each action type with a description of the value it needs.

availableobject

lists, tags and sequences (id and name, sequences also have status) and attributes (names).

Example result

{
  "condition_types": [
    {
      "type": "contact_added_to_list",
      "description": "A contact is added to the list. value = list id."
    }
  ],
  "action_types": [
    {
      "type": "add_tag",
      "description": "Add the tag to the contact. value = tag id."
    }
  ],
  "available": {
    "lists": [
      {
        "id": 8,
        "name": "Customers"
      }
    ],
    "tags": [
      {
        "id": 5,
        "name": "VIP"
      }
    ],
    "sequences": [
      {
        "id": 3,
        "name": "Onboarding",
        "status": "live"
      }
    ],
    "attributes": [
      "plan"
    ]
  }
}
create-automation

Create an automation: when the condition happens to a contact, the actions run on that contact. Automations are always created paused. Turn them on from the dashboard, because the MCP server cannot turn an automation on.

Arguments

namestring
required

Automation name.

typestring

simple (default) or multistep.

conditionobject
required

The trigger: type (contact_added_to_list, removed_from_list, tag_added, removed_tag, added_to_sequence, sequence_finished or attribute_changed) and value (the id). For attribute_changed, send attribute and operator (changed_to with a value, or changed).

actionsarray
required

One or more actions: type (add_tag, remove_tag, add_list, remove_list or add_sequence) and value (the id). add_sequence needs a live sequence.

Returns

idinteger

Automation id.

namestring

Automation name.

typestring

simple or multistep.

is_liveboolean

Whether the automation runs on contacts now.

created_atstring|null

ISO-8601 creation time.

updated_atstring|null

ISO-8601 time of the last change.

conditionobject

The saved trigger.

actionsarray

The saved actions.

messagestring

Human-readable confirmation.

Example result

{
  "id": 12,
  "name": "Tag new customers",
  "type": "simple",
  "is_live": false,
  "condition": {
    "type": "contact_added_to_list",
    "value": 8
  },
  "actions": [
    {
      "type": "add_tag",
      "value": 5
    }
  ],
  "created_at": "2026-09-23T10:00:00+00:00",
  "updated_at": "2026-09-23T10:00:00+00:00",
  "message": "Paused automation #12 created. Turn it on from the BYOMailer dashboard."
}
update-automation

Update a paused automation. A live automation returns an error until you pause it in the dashboard. Only the fields that you send change. A condition replaces the full condition, and an actions array replaces all actions. The live flag does not change.

Arguments

automation_idinteger
required

The id of the paused automation.

namestring

Automation name.

typestring

simple (default) or multistep.

conditionobject

The trigger: type (contact_added_to_list, removed_from_list, tag_added, removed_tag, added_to_sequence, sequence_finished or attribute_changed) and value (the id). For attribute_changed, send attribute and operator (changed_to with a value, or changed).

actionsarray

One or more actions: type (add_tag, remove_tag, add_list, remove_list or add_sequence) and value (the id). add_sequence needs a live sequence.

Returns

idinteger

Automation id.

namestring

Automation name.

typestring

simple or multistep.

is_liveboolean

Whether the automation runs on contacts now.

created_atstring|null

ISO-8601 creation time.

updated_atstring|null

ISO-8601 time of the last change.

conditionobject

The saved trigger.

actionsarray

The saved actions.

messagestring

Human-readable confirmation.

Example result

{
  "id": 12,
  "name": "Tag new customers as VIP",
  "type": "simple",
  "is_live": false,
  "condition": {
    "type": "contact_added_to_list",
    "value": 8
  },
  "actions": [
    {
      "type": "add_tag",
      "value": 5
    }
  ],
  "created_at": "2026-09-23T10:00:00+00:00",
  "updated_at": "2026-09-23T10:00:00+00:00",
  "message": "Paused automation #12 updated."
}
BYOMailer

© 2026 All rights reserved.