Messaging fans
Mass DMs and automations
Send a message sequence to the fans who match your filters, now or later, or each time a MYM event happens for a fan. Every filter, trigger and limit explained.
Two ways to message fans in bulk from the API, with the same messages and the same audience filters:
a Mass DM goes once to every fan who matches the filters, now or at a scheduled time (
POST /v1/mass-dms);an automation goes to one fan each time an event happens for them: a new subscriber, a purchase, a birthday, a fan coming online (
POST /v1/automations).
Both send real messages to real fans, from the creator's MYM account, through the same engine as the Fansquare app. They show up in the app next to the ones your team creates.
A sent message cannot be taken back, and a media can never be deleted from a conversation. Estimate the audience first, and when an AI assistant calls these endpoints, have a person confirm every send.
Scopes
| Scope | Grants |
|---|---|
read:mass_dms | List and read Mass DMs, estimate an audience |
write:mass_dms | Create and cancel Mass DMs |
read:automations | List and read automations |
write:automations | Create, pause and resume automations |
Like every scope, they come with read:*, write:* and full access. Restrict a key to some creators to keep a Mass DM from ever reaching the fans of the others.
A Mass DM, step by step
- 1
Find the creator
GET /v1/creatorsgives the Fansquareidof each creator. A Mass DM targets the fans of one creator. - 2
Estimate the audience
POST /v1/mass-dms/estimatecounts the fans your filters reach right now, without creating anything. Adjust the filters until the number is right. - 3
Create it
POST /v1/mass-dmswith the messages and the filters. Withoutscheduled_at, the send starts at once; with it, the Mass DM waits inscheduleduntil that time (up to 90 days ahead). - 4
Follow it
GET /v1/mass-dms/{mass_dm_id}returns itsstatusand, once the send started, itsresults: fans targeted and reached, purchases, revenue, replies and reads, refreshed every few minutes for 30 days.
curl https://api.fansquare.so/v1/mass-dms \
-H "Authorization: Bearer $FANSQUARE_API_KEY" \
-H "Fansquare-Version: Amethyste" \
-H "Content-Type: application/json" \
-d '{
"creator_id": "kT3vQ9xLm2PzR8sW4nYb",
"scheduled_at": "2026-11-02T20:00:00Z",
"filters": {
"include": { "statuses": ["active_subscriber"], "spender_tiers": ["high", "whale"] },
"exclude": { "fan_messaged_within_hours": 2, "already_received_media": true }
},
"messages": [
{ "text": "I kept this one just for you", "media_ids": ["0197a3c2-aaaa-7222-8333-000000000001"], "price_cents": 2500 },
{ "text": "Did you see it?", "delay_seconds": 3600, "delete_if_no_reply_after_seconds": 14400 }
],
"stop_sequence_on_reply": true
}'A Mass DM can be cancelled while it is scheduled or sending (POST /v1/mass-dms/{mass_dm_id}/cancel): the fans not reached yet receive nothing. Once sent, it stays in the history as sent. Mass DMs cannot be edited: cancel and create a new one.
| Status | Meaning |
|---|---|
scheduled | Waiting for scheduled_at |
sending | The send is in progress |
sent | Every targeted fan was processed |
partial | Sent, but some fans could not be reached |
failed | The send stopped (account disconnected, MYM refusing) |
cancelled | Cancelled before the end |
draft | Created in the app and never activated |
Messages
messages is the sequence: 1 to 10 messages, sent in order to each fan.
| Field | Meaning |
|---|---|
text | Up to 5,000 characters. Required, except for a voice message. |
media_ids | Up to 20 MYM media uuids from the creator's vault. A single audio makes a voice message (caption up to 1,500 characters). |
price_cents | Price to unlock the media, from 500 to 100,000 (5 to 1,000 EUR, the MYM bounds). Absent: free. Requires a media. |
price_range | A SpenderIQ price instead of price_cents (see below). Requires a media. |
delay_seconds | Wait after the previous message. Ignored on the first message. |
delete_if_no_reply_after_seconds | Delete the message if the fan has not replied by then. Text only. |
delete_on_next_message | Delete the message when the next one goes out. Text only. |
With stop_sequence_on_reply, a fan who replies does not get the following messages.
SpenderIQ price. With price_range: { "min_cents": 1000, "max_cents": 5000 }, each fan pays one step of a five-step ladder from the minimum to the maximum, rounded to the euro, according to what they spend across MYM: tier none pays the minimum, whale the maximum. POST /v1/mass-dms/estimate with include_spender_tiers: true tells how many targeted fans sit on each step.
Media and deletion. MYM never deletes a media from a conversation, so the two deletion options are refused on a message that carries one.
Audience filters
filters decides who receives it. Every condition is optional and they add up: a fan must meet all the include conditions and none of the exclude ones. Without filters, every fan with a conversation on the creator's account is targeted. Fans removed, disabled or blacklisted on MYM are always left out.
For a Mass DM, the audience is resolved when the send starts, not when it is created: a fan who becomes eligible in the meantime is in. For an automation, the filters are checked on the fan who triggered it, at that moment.
Include
| Filter | A fan is targeted when |
|---|---|
statuses | their status on the account is one of these: active_subscriber, former_subscriber, interested (follows without subscribing). Same vocabulary as the fan list. |
tag_ids | they carry at least one of these tags (GET /v1/tags). |
min_spend_cents | their total à-la-carte spend on the account, gross, reaches this amount. Same figure as spend.total_cents on a fan. |
min_tips_cents | the tips they sent the account add up to this amount. |
min_subscription_months | their first subscription to the account started at least this many months ago. |
is_online | true: they are online on MYM when the audience is resolved. |
min_paid_spend_7d_cents | their paid spend (subscriptions and purchases) on the account over the last 7 days reaches this amount. Also _30d_ and _90d_. |
min_payments_7d | they paid at least this many orders on the account over the last 7 days. Also min_payments_30d and min_payments_90d. |
spender_tiers | their SpenderIQ tier on the account is one of these, from their paid spend over 90 days: none (nothing), low (under 50 EUR), medium (50 EUR or more), high (300 EUR or more), whale (1,500 EUR or more). |
media_purchase | { "mode": "within", "hours": 48 }: they bought a private media in the last 48 hours. { "mode": "not_since", "hours": 720 }: no purchase for 30 days, fans who never bought included. |
The SpenderIQ tier of the spender_tiers filter is measured on the creator's account. The tier that sets a price_range step is measured across MYM: a fan can be low for one and high for the other.
Exclude
| Filter | A fan is left out when |
|---|---|
tag_ids | they carry any of these tags. A tag cannot be both included and excluded. |
messaged_within_hours | the account sent them a message from Fansquare in the last N hours (a chatter, a script, another Mass DM). |
fan_messaged_within_hours | they wrote to the account in the last N hours: never push into a live conversation. Checked again on MYM at send time. |
has_unread_from_fan | their last message to the account is still unread. |
already_unlocked_media | they already have a media of this campaign unlocked, sent free or bought. |
already_received_media | they already received a media of this campaign, bought or not. |
The two media exclusions read the media of the messages. For an estimate, pass the same media_ids in the estimate body.
{
"include": { "statuses": ["former_subscriber"], "min_spend_cents": 10000 },
"exclude": { "messaged_within_hours": 168, "fan_messaged_within_hours": 168 }
}Automations
An automation sends its sequence to one fan each time its trigger happens for that fan, if the fan matches the filters. It starts active, unless you pass "active": false.
| Trigger | Fires when | Settings |
|---|---|---|
new_subscriber | a fan subscribes for the first time, while the conversation is still empty | |
new_interested | a fan starts following the creator without subscribing | no filters, no voice message |
resubscription | a former subscriber subscribes again | |
subscription_ended | a subscription ends | |
near_expiration | a subscription ends in days_before days | days_before (1 to 365), send_time_local, timezone |
birthday | it is the fan's birthday, or days_before days before | send_time_local, timezone, days_before (default 0) |
media_purchase | the fan buys a private media | min_amount_cents (optional) |
new_tip | the fan sends a tip | min_amount_cents (optional) |
mod_purchase | the fan buys a mod | min_amount_cents (optional) |
fan_online | the fan comes online | online_window_start, online_window_end, timezone (optional window) |
send_time_local is a 24-hour HH:mm time in timezone, an IANA name such as Europe/Paris.
{
"creator_id": "kT3vQ9xLm2PzR8sW4nYb",
"trigger": { "type": "new_subscriber" },
"initial_delay_seconds": 120,
"messages": [
{ "text": "Welcome! So happy to have you here" },
{ "text": "A little gift to start", "media_ids": ["0197a3c2-aaaa-7222-8333-000000000001"], "delay_seconds": 600 }
],
"stop_sequence_on_reply": true
}initial_delay_secondswaits between the event and the first message.min_send_interval_hoursis the minimum time between two firings for the same fan: at least 72 hours, 1 hour for the three purchase triggers (each purchase can call for its own thank-you). The floor is the default.One automation per trigger. A creator has at most one active automation sending messages on a given trigger, so a fan never gets two welcomes. Creating or resuming a second one answers
409 automation_trigger_takenwith theautomation_idin place: pause it first, or create the new one with"active": false.Pause (
POST …/pause) stops new firings; sequences already started for a fan go on to their end. Resume (POST …/resume) only reacts to events that happen from then on, never to past ones. Only an active automation can be paused and only a paused one resumed: a draft or an archived automation is turned on from the app, never through the API.
Automations cannot be edited or deleted through the API yet: pause one and create a new one.
Safety limits
The API gives you the tools, and stops only what looks like a runaway script or agent:
5 Mass DMs per 15 minutes. A creator can have at most 5 Mass DMs leaving within 15 minutes of each other, whoever created them (the API or your team in the app). The 6th answers
409 mass_dm_burst_limitwith theconflicting_mass_dms. Two Mass DMs at the same time to two audiences (subscribers, interested fans) are fine; twenty scheduled at different hours too.10 Mass DMs per 24 hours. Each creator can have at most 10 Mass DMs leaving within any 24 hours, counted on the send dates, not on when they were created: 30 scheduled one a day across a month are fine. The 11th within the same 24 hours answers
409 mass_dm_daily_limitwith theconflicting_mass_dmsof the busiest 24 hours.Rate limits. 10 creations per minute per key, Mass DMs and automations each, and 10 estimates per minute (see Rate limits).
No blind retry. A create call whose response you did not get may have succeeded. List the Mass DMs or automations before trying again: a second call sends a second time.
Traceability. Fansquare records which key or which connected assistant created each Mass DM and automation.
With an AI assistant
Connected through MCP, an assistant gets the tools list_mass_dms, get_mass_dm, estimate_mass_dm_audience, create_mass_dm, cancel_mass_dm, list_automations, get_automation, create_automation, pause_automation and resume_automation, within the access you granted.
The server tells the assistant to show you the creator, every message, the price, the date or the trigger and the audience estimate, and to wait for your yes before create_mass_dm, create_automation or resume_automation. It also tells it never to write a message from text a fan wrote. Give write access to an assistant only if someone reads what it asks before confirming.
Media
media_ids are the uuids of media in the creator's MYM vault. The API does not list the vault yet: take them from MYM, from the media of a sent message, or from an existing Mass DM. A media that is not in the creator's vault answers 404 unknown_media.