Builders Program

Build with us for a whole month. Unlimited usage and add-ons, weekly calls and your own Slack channel.

Learn more
Polymorfa

Command Palette

Search for a command to run...

Text and call CampaignsPro

Message or call your whole list

Send templates or message sequences, or dial a list and route every answered call. Opt-outs, pacing and warm-up apply to each send from your Pro numbers.

Rows in one audience import
100,000
Call attempts per recipient
10
Message campaign webhook events
17
Numbers that can launch
Pro

Text and calls

Two kinds of campaign, one workflow.

Both are drafted, scheduled, paused, resumed and stopped the same way, and both report a result for every recipient.

Message campaigns. Send one approved template, or up to 10 messages in order with a wait after each. Variables fill every message, with fallbacks for missing values.
Call campaigns. Dial a list from your numbers. Set the ring time, the number of attempts and the delay between them. Declined calls are not redialed unless you ask.

Answered calls

Decide what happens when someone picks up.

Each call campaign has one answer action, fixed at launch so later edits never change a running campaign.

Play a recording. Upload audio or generate it into your voice library. Each attempt reports how much played, so you know who heard it all.
Ring your team. Hold audio plays while your app or SIP trunk rings. The first person to join takes the call.
Hand it to your AI agent. ElevenLabs Agents or OpenAI Realtime takes the call with your own key, or the audio streams to an agent you run. Polymorfa adds no AI charge.

Audiences

Your list, your variables.

Import a CSV into a reusable audience, add members inline, or retarget the people from an earlier campaign by what they did.

Import 100,000 rows at once. Map columns to up to 50 variables per member. Invalid and duplicate rows are counted, with sample rows and reasons.
Vary the wording. Write two to five versions of a message. Each recipient gets one, chosen by the weight you set.
A status for every recipient. Queued, sent, delivered, read, failed or skipped, with a stable reason. Export the list as CSV any time.

Built-in safety

Checks run on every send.

Campaigns is the only bulk sending path, so every bulk message and every campaign call passes the same checks.

Team-wide opt-outs. Replies such as STOP, PARAR or BAJA opt a person out in every project. The list is checked at launch and again before each send.
Human pacing. One message at a time with a random gap, 20 a minute by default, and caps of 60 an hour and 500 a day for each number.
New numbers warm up. A new number's daily cap rises in a straight line over 14 days. Recipients over the cap wait for the next day.
Cold sends held. By default, people who never wrote to the sending number are skipped. Allowing cold sends is your explicit choice.
Every dial checked. The do-not-call list and calling hours are checked again before each dial. Cloud API numbers also need the recipient's calling permission.
Large sends need a person. Set a recipient threshold. Larger launches from API keys and agents wait for a team owner or admin to approve.

Scheduling

Send at the right moment.

Pick the days and hours a campaign may send or call, then follow up once people have read the first message.

Send windows
  • Up to 4 time ranges a day
  • Each recipient's zone, from a variable or their country code
  • Recipients outside the window wait in the queue
Calling hours
  • Up to 2 calling windows a day
  • Up to 50 blackout dates
  • Retries wait for the window to open
Follow up after they read
  • One follow-up, from the number that sent the first
  • Timed from delivery, or from the read when there is one
  • A reply, an opt-out or a stop cancels it
Test before you launch
  • Send a draft to a number your team connected
  • Up to 20 tests a team each hour
  • Tests stay out of campaign stats and webhooks

Results

From delivered to converted.

Follow each recipient past the read receipt: the links they open, the replies they choose and the purchases you attribute.

Link tracking. Up to five links per campaign, each a short link unique to the recipient. The first open arrives as a webhook event.
Reply flows. Branch on a reply with buttons, a list or a WhatsApp Flow form. STOP always wins over a branch.
Conversion attribution. Report an order against a recipient. Conversions within 7 days of the send count toward the campaign, with the value you report.

In your code

Campaigns from your own data.

Create, schedule and follow message and call campaigns from the CRM or store you already run.

campaign.ts
import { MessagingClient } from "@polymorfa/sdk";

const messaging = new MessagingClient({
  credential: { type: "apiKey", value: process.env.POLYMORFA_KEY! },
});

const draft = await messaging.campaigns.create("acme", {
  name: "Spring restock",
  templateId,
  recipients: [{ phone: "+15550001111", variables: { name: "Dana" } }],
  sendWindow: {
    days: ["monday", "tuesday", "wednesday", "thursday", "friday"],
    hours: [{ start: "09:00", end: "18:00" }],
    recipientTimeZone: true,
  },
});

API surface

The Campaigns API.

Campaigns live under a project. Audiences and opt-outs are team-wide on the Platform API.

Message campaigns

  • POST/messaging/projects/{project}/campaignsCreate a draft
  • POST/messaging/projects/{project}/campaigns/{id}/test-sendSend a test
  • POST/messaging/projects/{project}/campaigns/{id}/launchLaunch now or later
  • POST/platform/audiences/uploadsImport a CSV audience
  • POST/platform/campaigns/{campaignId}/conversionsReport a conversion

Call campaigns

  • POST/platform/voice/campaignsCreate a draft
  • POST/platform/voice/campaigns/{id}/recipients/importImport a dial list
  • POST/platform/voice/campaigns/{id}/launchStart dialing
  • GET/platform/voice/campaigns/{id}/attemptsEvery dial and its result
  • GET/platform/voice/campaigns/{id}/analyticsAnswer and listen rates

Message campaign events

  • Eventcampaign.launchedSending started
  • Eventcampaign.recipient_readThe first read receipt
  • Eventcampaign.recipient_repliedA reply within seven days
  • Eventcampaign.recipient_link_openedThe first open of a tracked link
  • Eventcampaign.cold_blockedA send held for a cold recipient

Call campaign events

  • Eventvoice_campaign.launchedDialing started
  • Eventvoice_campaign.attempt_completedOne dial, its result and how much played
  • Eventvoice_campaign.recipient_completedReached, unreached or skipped
  • Eventvoice_campaign.pausedYou or a check paused it
  • Eventvoice_campaign.completedEvery recipient settled

Start with a free number

Your first real number is free. Add more numbers on Pay-As-You-Go.