# SMS Marketing Message Checker: STOP & 10DLC (`ultimatemc/sms-marketing-message-checker`) Actor

Check SMS and MMS marketing texts before you send or register a 10DLC campaign: segment count and GSM-7 vs Unicode, STOP opt-out wording, opt-in confirmation elements, public URL shorteners, cannabis/CBD, SHAFT, high-risk finance, phishing-like wording, merge-field errors and 8am-9pm quiet hours.

- **URL**: https://apify.com/ultimatemc/sms-marketing-message-checker.md
- **Developed by:** [Ultimate Foresight Inc](https://apify.com/ultimatemc) (community)
- **Categories:** Marketing, Automation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Check **SMS and MMS marketing texts** before you send them or submit a **10DLC campaign**. The **SMS Marketing Message Checker** counts **GSM-7 or Unicode segments** (and finds the curly quote or dash that doubles your cost), and flags **missing STOP opt-out wording**, **opt-in confirmations without HELP, frequency or "msg & data rates"**, **bit.ly and other public URL shorteners**, **http links**, **no brand name**, **cannabis, CBD, gambling, high-risk loans and SHAFT content**, **phishing-like wording**, **unfilled {{placeholders}}**, **all caps and spam phrases** and **sends outside 8 a.m.-9 p.m.**. Each finding links to the CTIA, Twilio or FCC source. Click **Start** with the prefilled example to see it work.

> This is a pre-send screen against public CTIA guidance, carrier filtering error descriptions and the federal TCPA time window. It doesn't guarantee delivery or campaign approval, and it isn't legal advice on consent, which it can't see. Every row carries this disclaimer.

### What does the SMS Marketing Message Checker do?

- ✅ **Segments and cost**: encoding (GSM-7 or UCS-2), characters, billed segments (160/153 or 70/67), and `segmentsIfFixed` when smart quotes, en dashes or similar characters force Unicode.
- ✅ **Opt-out**: no STOP wording (high for first messages and opt-in confirmations).
- ✅ **Opt-in confirmations**: missing program name, HELP, message frequency or "msg & data rates may apply", as CTIA lists for confirmation messages.
- ✅ **Links**: public URL shorteners (bit.ly, tinyurl and others), `http://` links and many links in one message.
- ✅ **Content carriers restrict**: cannabis and CBD, high-risk lending and debt relief, gambling, SHAFT (sex, hate, alcohol, firearms, tobacco), third-party lead generation and phishing-like account warnings.
- ✅ **Format and timing**: brand not named, unfilled `{{first_name}}` placeholders, mostly caps, spam phrases and marketing sends before 8 a.m. or from 9 p.m. recipient time.
- ✅ Output per message: `riskLevel`, `issueCount`, `categoriesFlagged`, `encoding`, `characters`, `encodedUnits`, `segments`, `nonGsmCharacters`, `issues` (`ruleId`, `category`, `severity`, `quote`, `sourceUrl`, `fixHint`), `checkedAt` and a disclaimer.

### Who is it for?

- **Small businesses and ecommerce stores** writing their own SMS campaigns.
- **Agencies and SMS platform users** checking templates before 10DLC campaign registration.
- **Developers** adding a pre-send check to Twilio, Klaviyo, Attentive or Postscript workflows.
- **Compliance and QA teams** reviewing campaign libraries in bulk.

### How to check SMS marketing messages

1. Click **Start** with the prefilled example (two promos with problems, a weak opt-in confirmation and a good one).
2. Replace it with your messages: plain texts, or objects with `text`, `id`, `messageType` (marketing, optInConfirmation, transactional), `brand` and `sendTime` or `sendHourLocal`.
3. Set **Brand** to check every message names you, and **Send hour** to check the quiet-hours window.
4. Or enter a **Dataset ID** with exported campaign texts; use **Field map** for the text field.
5. Turn on **Only save rows with findings**; you only pay for saved messages.

### Input example

This is the prefilled input:

```json
{
  "messages": [
    {
      "id": "promo-1",
      "text": "FLASH SALE!!! 40% off everything today only – shop now: bit.ly/3xAmPle",
      "brand": "Example Shoes"
    },
    {
      "id": "welcome-1",
      "messageType": "optInConfirmation",
      "brand": "Example Shoes",
      "text": "Example Shoes: Thanks for joining! Reply STOP to cancel."
    },
    {
      "id": "promo-2",
      "text": "Example Shoes: Hi {{first_name}}, your account has been suspended. Verify your account at http://example-shoes-help.com",
      "brand": "Example Shoes"
    },
    {
      "id": "welcome-2",
      "messageType": "optInConfirmation",
      "brand": "Example Shoes",
      "text": "Example Shoes: You're signed up for sale alerts. Up to 4 msgs/mo. Msg & data rates may apply. Reply HELP for help, STOP to cancel."
    }
  ]
}
```

Dataset mode:

```json
{"datasetId": "YOUR_DATASET_ID", "fieldMap": {"text": "body", "id": "campaignId"}, "brand": "Your Brand", "onlyFlagged": true}
```

### Output example

Real output from a run of the prefilled input on 2026-10-30 (long finding lists are shortened here; the run returns all of them):

```json
[
  {
    "itemNo": 1,
    "messageId": "promo-1",
    "text": "FLASH SALE!!! 40% off everything today only – shop now: bit.ly/3xAmPle",
    "messageType": "marketing",
    "encoding": "UCS-2",
    "characters": 70,
    "encodedUnits": 70,
    "segments": 1,
    "nonGsmCharacters": "–",
    "riskLevel": "high",
    "issueCount": 5,
    "categoriesFlagged": [
      "Links",
      "Opt-out",
      "Segments and cost",
      "Sender identification",
      "Spam signals"
    ],
    "issues": [
      {
        "ruleId": "public_url_shortener",
        "category": "Links",
        "severity": "high",
        "quote": "bit.ly/3xAmPle",
        "sourceUrl": "https://www.twilio.com/docs/api/errors/30963",
        "fixHint": "Public URL shorteners (bit.ly, tinyurl, t.co and similar) hide the destination and get campaigns rejected and messages filtered. Use your full domain or a branded short domain you own."
      },
      {
        "ruleId": "missing_opt_out",
        "category": "Opt-out",
        "severity": "medium",
        "quote": null,
        "sourceUrl": "https://api.ctia.org/wp-content/uploads/2023/05/230523-CTIA-Messaging-Principles-and-Best-Practices-FINAL.pdf",
        "fixHint": "No opt-out instructions found. CTIA asks senders to state how and with which words to opt out, using standard STOP wording (e.g., 'Reply STOP to opt out')."
      },
      {
        "...": "3 more findings: brand_not_named 'Example Shoes', unicode_from_punctuation '–', spam_phrases '!!!'"
      }
    ],
    "checkedAt": "2026-10-30T18:52:09+00:00",
    "disclaimer": "Automated text pre-check based on public CTIA Messaging Principles, Twilio/carrier..."
  },
  {
    "itemNo": 2,
    "messageId": "welcome-1",
    "text": "Example Shoes: Thanks for joining! Reply STOP to cancel.",
    "messageType": "optInConfirmation",
    "encoding": "GSM-7",
    "characters": 56,
    "encodedUnits": 56,
    "segments": 1,
    "nonGsmCharacters": null,
    "riskLevel": "medium",
    "issueCount": 3,
    "categoriesFlagged": [
      "Opt-in confirmation"
    ],
    "issues": [
      {
        "ruleId": "optin_missing_help",
        "category": "Opt-in confirmation",
        "severity": "medium",
        "quote": null,
        "sourceUrl": "https://api.ctia.org/wp-content/uploads/2023/05/230523-CTIA-Messaging-Principles-and-Best-Practices-FINAL.pdf",
        "fixHint": "Opt-in confirmations should include customer-care contact info or HELP instructions (CTIA 5.1.2.1)."
      },
      {
        "ruleId": "optin_missing_rates",
        "category": "Opt-in confirmation",
        "severity": "medium",
        "quote": null,
        "sourceUrl": "https://api.ctia.org/wp-content/uploads/2023/05/230523-CTIA-Messaging-Principles-and-Best-Practices-FINAL.pdf",
        "fixHint": "Opt-in confirmations should disclose fees, typically 'Msg & data rates may apply' (CTIA 5.1.2.1)."
      },
      {
        "...": "1 more findings: optin_missing_frequency ''"
      }
    ],
    "checkedAt": "2026-10-30T18:52:09+00:00",
    "disclaimer": "Automated text pre-check based on public CTIA Messaging Principles, Twilio/carrier..."
  },
  {
    "itemNo": 3,
    "messageId": "promo-2",
    "text": "Example Shoes: Hi {{first_name}}, your account has been suspended. Verify your account at http://example-shoes-help.com",
    "messageType": "marketing",
    "encoding": "GSM-7",
    "characters": 119,
    "encodedUnits": 123,
    "segments": 1,
    "nonGsmCharacters": null,
    "riskLevel": "high",
    "issueCount": 4,
    "categoriesFlagged": [
      "Deceptive / phishing-like wording",
      "Format",
      "Links",
      "Opt-out"
    ],
    "issues": [
      {
        "ruleId": "phishing_like",
        "category": "Deceptive / phishing-like wording",
        "severity": "high",
        "quote": "your account has been suspended",
        "sourceUrl": "https://api.ctia.org/wp-content/uploads/2023/05/230523-CTIA-Messaging-Principles-and-Best-Practices-FINAL.pdf",
        "fixHint": "Wording common in phishing (account suspended, verify your account, unusual activity, package held, prize claims) gets messages filtered and CTIA lists deceptive or phishing content as unwanted. Rephrase and make the sender obvious."
      },
      {
        "ruleId": "missing_opt_out",
        "category": "Opt-out",
        "severity": "medium",
        "quote": null,
        "sourceUrl": "https://api.ctia.org/wp-content/uploads/2023/05/230523-CTIA-Messaging-Principles-and-Best-Practices-FINAL.pdf",
        "fixHint": "No opt-out instructions found. CTIA asks senders to state how and with which words to opt out, using standard STOP wording (e.g., 'Reply STOP to opt out')."
      },
      {
        "...": "2 more findings: unfilled_placeholder '{{first_name}}', insecure_link 'http://example-shoes-help.com'"
      }
    ],
    "checkedAt": "2026-10-30T18:52:09+00:00",
    "disclaimer": "Automated text pre-check based on public CTIA Messaging Principles, Twilio/carrier..."
  },
  {
    "itemNo": 4,
    "messageId": "welcome-2",
    "text": "Example Shoes: You're signed up for sale alerts. Up to 4 msgs/mo. Msg & data rates may apply. Reply HELP for help, STOP to cancel.",
    "messageType": "optInConfirmation",
    "encoding": "GSM-7",
    "characters": 130,
    "encodedUnits": 130,
    "segments": 1,
    "nonGsmCharacters": null,
    "riskLevel": "none found",
    "issueCount": 0,
    "categoriesFlagged": [],
    "issues": [],
    "checkedAt": "2026-10-30T18:52:09+00:00",
    "disclaimer": "Automated text pre-check based on public CTIA Messaging Principles, Twilio/carrier..."
  }
]
```

### How much does it cost to check SMS messages?

This Actor uses pay-per-event pricing: **$0.001 per message saved** plus a **$0.00005 start fee per run**, plus small platform usage paid by you (a few hundredths of a cent for small runs). That's about **$0.10 for 100 messages** and **$1 for 1,000 messages** plus usage. With **Only save rows with findings** on, clean messages aren't saved or charged. You can set a maximum cost per run in the run options.

### Use it through the API, integrations or AI agents

- Run it and get results in one call: `https://api.apify.com/v2/acts/ultimatemc~sms-marketing-message-checker/run-sync-get-dataset-items`
- Use it from AI agents through the Apify MCP server: `https://mcp.apify.com?tools=ultimatemc/sms-marketing-message-checker`
- Call it from your sending workflow before each campaign, or connect it to Make, Zapier, n8n or Google Sheets.

### How it works

All checks are deterministic: GSM-7 character tables for encoding and segments, and English text patterns written from the CTIA Messaging Principles and Best Practices (May 2023), Twilio's carrier filtering error pages and messaging policy, and 47 CFR 64.1200, checked on 2026-10-30. No AI, no outside calls and no messages are sent. The risk level is the highest severity found.

Sources:

- [CTIA Messaging Principles and Best Practices (May 2023, PDF)](https://api.ctia.org/wp-content/uploads/2023/05/230523-CTIA-Messaging-Principles-and-Best-Practices-FINAL.pdf)
- [Twilio error 30963 (public URL shortener)](https://www.twilio.com/docs/api/errors/30963)
- [Twilio error 30897 (disallowed content)](https://www.twilio.com/docs/api/errors/30897)
- [Twilio error 30940 (cannabis/CBD content)](https://www.twilio.com/docs/api/errors/30940)
- [Twilio error 30892 (phishing/fraud)](https://www.twilio.com/docs/api/errors/30892)
- [Twilio Messaging Policy](https://www.twilio.com/en-us/legal/messaging-policy)
- [Twilio: GSM-7 encoding](https://www.twilio.com/docs/glossary/what-is-gsm-7-character-encoding)
- [Twilio: SMS character limit](https://www.twilio.com/docs/glossary/what-sms-character-limit)
- [47 CFR 64.1200 (TCPA rules)](https://www.ecfr.gov/current/title-47/chapter-I/subchapter-B/part-64/subpart-L/section-64.1200)

### FAQ

#### Does a clean result mean carriers will deliver my message?

No. Carriers also look at your registration, sending patterns and complaints. A clean result means none of the listed text problems were found.

#### Does it check consent?

No. It can't see how you collected opt-ins. You're responsible for consent under the TCPA and carrier rules.

#### Why is my short message 2 segments?

One character outside GSM-7, like a curly quote or an en dash, switches the whole message to Unicode with a 70-character limit. The output shows those characters and `segmentsIfFixed`.

#### Why are transactional messages not flagged for STOP?

Set `messageType` to transactional; opt-out and quiet-hours checks are skipped for those. Other checks still run.

#### Is it AI?

No. It's a fixed rule set, so results are repeatable and runs cost $0.001 per message.

### Limitations

- English messages and US carrier rules only.
- State quiet-hours laws (some stricter than 8 a.m.-9 p.m.) aren't checked.
- MMS media isn't checked, only the text.
- Guidance as of 2026-10-30; carriers change filtering without notice.

### Other tools by Ultimate Foresight

- [Fair Housing Listing Checker for Real Estate Ads](https://apify.com/ultimatemc/fair-housing-listing-checker): flags rental and sale listing wording that may raise Fair Housing Act issues, with HUD sources and rewrite tips (screening aid only).
- [Ad Copy Policy Checker for Meta, Google & TikTok](https://apify.com/ultimatemc/ad-copy-policy-checker): checks ad text against Facebook, Instagram, Google Ads and TikTok ad policies before you submit.
- [H-1B Visa Sponsor Checker & Score for Job Listings](https://apify.com/ultimatemc/h1b-visa-sponsor-score): adds Department of Labor H-1B sponsorship history and a 0-100 score to company names or job listings.
- [Chain vs Independent Labeler for Google Maps Leads](https://apify.com/ultimatemc/chain-vs-independent-labeler): labels local businesses as chain, franchise or independent.
- [YouTube Monetization Checker for Scripts & Titles](https://apify.com/ultimatemc/youtube-script-monetization-checker): pre-checks titles, descriptions and scripts for wording that leads to limited or no ads.
- [Etsy & eBay Listing Policy & Banned Item Checker](https://apify.com/ultimatemc/etsy-ebay-listing-policy-checker): pre-checks marketplace listings for prohibited items, counterfeit wording and off-platform contact.
- [Job Scam Detector & Trust Score for Job Postings](https://apify.com/ultimatemc/job-posting-trust-score): scores job postings 0-100 for scam and ghost-job signals.
- [SAM.gov Amendment & Opportunity Change Tracker](https://apify.com/ultimatemc/sam-gov-opportunity-change-detector): shows what changed between versions of a SAM.gov notice: deadlines, set-asides, NAICS and attachments.
- [Product Recall Checker for Brands, UPCs & Products](https://apify.com/ultimatemc/product-recall-matcher): matches your brands, products, UPCs or model numbers against CPSC, FDA and NHTSA recalls.
- [App Store & Google Play Listing Policy Checker](https://apify.com/ultimatemc/app-store-listing-policy-checker): pre-checks app names, subtitles and descriptions against Apple and Google Play metadata rules.
- [Company Name Normalizer & Deduplicator for CRM](https://apify.com/ultimatemc/company-name-canonicalizer): cleans company names (Inc, LLC, d/b/a, aliases) and groups duplicates in CRM, lead or vendor lists.
- [FCC Covered List & Section 889 Bulk Screener](https://apify.com/ultimatemc/fcc-covered-list-screener): screens FCC IDs and brand names against the public FCC Covered List, with sources and timestamps (screening aid only).
- [Green Claims Checker: EU Greenwashing Ban & FTC](https://apify.com/ultimatemc/green-claims-checker): flags risky eco-friendly, carbon neutral and recyclable wording under EU, FTC and UK CMA rules.
- [Influencer #ad Disclosure Checker: FTC & ASA](https://apify.com/ultimatemc/influencer-ad-disclosure-checker): flags influencer posts with missing or unclear #ad labels under FTC, ASA/CAP and CMA rules.
- [Job Title to SOC Code Mapper with O\*NET Data](https://apify.com/ultimatemc/job-title-soc-code-mapper): maps job titles to SOC and O\*NET-SOC codes in bulk, with seniority and tech skills found in the posting.
- [Shrinkflation Detector for Grocery Price Data](https://apify.com/ultimatemc/shrinkflation-detector): finds smaller packs at the same or higher price by comparing two runs of a grocery scraper, with unit price before and after.
- [Job Ad Discrimination Checker for Job Posts (US)](https://apify.com/ultimatemc/job-ad-discrimination-checker): flags age, sex, national origin, citizenship and other discriminatory wording in job posts, with EEOC and DOJ sources (screening aid only).
- [Walmart Listing Policy Checker for Titles & Copy](https://apify.com/ultimatemc/walmart-listing-policy-checker): flags promotional phrases, retailer names, URLs, long titles and pesticide or FDA claims in Walmart Marketplace listings, with policy links and fixes.
- [TikTok Shop Listing Policy Checker for Products](https://apify.com/ultimatemc/tiktok-shop-listing-policy-checker): flags off-platform links, dupe wording, weight-loss, disease and FDA claims and title rule breaks in TikTok Shop listings.
- [Supplement & Cosmetic Claims Checker: FDA & FTC](https://apify.com/ultimatemc/supplement-cosmetic-claims-checker): flags disease, drug and 'FDA approved' claims and missing supplement disclaimers in supplement and beauty product copy, with FDA and FTC sources (screening aid only).
- [Rental Listing Scam Checker for Craigslist & FB](https://apify.com/ultimatemc/rental-listing-scam-checker): scores rental listings 0-100 for FTC-listed scam signs like wire or gift card payment, deposit before viewing and rent far below similar listings.
- [GTIN, UPC & EAN Barcode Validator (Check Digit)](https://apify.com/ultimatemc/gtin-barcode-validator): checks UPC, EAN, GTIN-14 and ISBN codes for wrong check digits, lost leading zeros, scientific notation, restricted prefixes and duplicates before a feed upload.
- [Fake Review Checker: Incentivized & Duplicates](https://apify.com/ultimatemc/review-integrity-checker): screens scraped reviews for incentivized or insider wording, copied text, rating bursts and rating/text mismatches named in the FTC 2024 fake-review rule.
- [Facebook Marketplace Listing Policy Checker](https://apify.com/ultimatemc/facebook-marketplace-listing-policy-checker): flags Marketplace listings that may break Meta's Commerce Policies (weapons, vapes, Rx, animals, gift cards, services, counterfeits and more), with policy links.
- [Fake Discount Checker: EU 30-Day Prior Price](https://apify.com/ultimatemc/discount-claim-checker): checks 'was' and strikethrough prices against your own price history for 30-day prior-price, raise-then-discount and wrong-badge issues.
- [Amazon Listing Policy Checker for Titles & Bullets](https://apify.com/ultimatemc/amazon-listing-policy-checker): flags pesticide, FDA and disease claims and Amazon title and bullet rule breaks in bulk, with policy links and fixes.
- [Hidden Fee Checker: Hotel, Rental & Ticket Prices](https://apify.com/ultimatemc/hidden-fee-price-checker): flags headline prices that leave out mandatory resort, service or booking fees under the FTC junk fees rule (16 CFR 464), with sources per finding.
- [EU GPSR Listing Checker for Amazon, eBay & Shops](https://apify.com/ultimatemc/gpsr-listing-checker): checks listings for the EU GPSR Article 19 online-sale details: manufacturer, EU responsible person, product identifier, picture and warnings.
- [Food Allergen Label Checker: US, EU & AU](https://apify.com/ultimatemc/food-allergen-label-checker): compares ingredient lists with the 'Contains' statement for US 9, EU/UK 14 and Australian PEAL allergens and flags gaps and conflicting free-from claims.
- [Toy Choking Hazard Warning Checker (CPSC)](https://apify.com/ultimatemc/toy-choking-warning-checker): flags toy listings missing the CPSC choking-hazard warnings for small parts, balloons, small balls and marbles, with age-grade checks.
- [Textile Fiber Label Checker: Bamboo & Origin](https://apify.com/ultimatemc/textile-fiber-label-checker): flags 'bamboo' claims that should say rayon, fiber percentages that don't add up, mismatched silk or cashmere titles and missing Made in USA/Imported.
- [Prop 65 Warning Checker for Product Listings](https://apify.com/ultimatemc/prop65-warning-checker): flags Prop 65 safe-harbor warnings missing 'WARNING', the P65Warnings.ca.gov link or a chemical name, old short forms, and listed chemicals mentioned with no warning.
- [Unit Price Checker for Grocery & Retail Listings](https://apify.com/ultimatemc/unit-price-checker): parses pack sizes, recomputes the price per kg, litre or item, and flags missing or wrong unit prices in grocery and retail data.
- [Made in USA Claim Checker for Product Listings](https://apify.com/ultimatemc/made-in-usa-claim-checker): flags unqualified 'Made in USA' claims next to imported or foreign-origin details under the FTC rule (16 CFR 323), with sources per finding.
- [Subscription Auto-Renewal Disclosure Checker](https://apify.com/ultimatemc/auto-renewal-disclosure-checker): checks subscription and free-trial offer text for missing renewal, price, billing period and cancellation disclosures under California law and FTC ROSCA.
- [Email CAN-SPAM Checker & Unsubscribe Header Test](https://apify.com/ultimatemc/email-can-spam-checker): pre-checks marketing emails for missing unsubscribe links or postal address, misleading subjects and Google/Yahoo one-click unsubscribe headers.

Found a false positive or a missed problem? Open an issue on the **Issues** tab with the message text, and we'll review the rule.

# Actor input Schema

## `messages` (type: `array`):

Array of message texts, or objects with "text" and optional "id", "messageType" (marketing, optInConfirmation, transactional), "brand", "sendTime" (ISO time in the recipient's time zone) or "sendHourLocal". The prefilled example shows common rejections next to a clean message.

## `messageType` (type: `string`):

Used for messages without their own messageType. Opt-in confirmations are also checked for HELP, frequency and rates wording; transactional messages skip the opt-out and quiet-hours checks.

## `brand` (type: `string`):

If set, each message is checked for this sender name.

## `sendHourLocal` (type: `integer`):

0-23. Marketing messages planned before 8 or from 21 (9 p.m.) are flagged under the federal TCPA time window.

## `isFirstMessage` (type: `boolean`):

Raises a missing opt-out instruction to high severity.

## `datasetId` (type: `string`):

Apify dataset with messages, for example exported campaign texts. Fields text, message, body or content are detected automatically; override them with Field map.

## `fieldMap` (type: `object`):

Override field names; dotted paths work for nested fields. Example: {"text": "body", "id": "campaignId"}.

## `onlyFlagged` (type: `boolean`):

Skip messages with no findings (you are only charged for saved rows).

## `maxItems` (type: `integer`):

Maximum number of messages to check in this run.

## Actor input object example

```json
{
  "messages": [
    {
      "id": "promo-1",
      "text": "FLASH SALE!!! 40% off everything today only – shop now: bit.ly/3xAmPle",
      "brand": "Example Shoes"
    },
    {
      "id": "welcome-1",
      "messageType": "optInConfirmation",
      "brand": "Example Shoes",
      "text": "Example Shoes: Thanks for joining! Reply STOP to cancel."
    },
    {
      "id": "promo-2",
      "text": "Example Shoes: Hi {{first_name}}, your account has been suspended. Verify your account at http://example-shoes-help.com",
      "brand": "Example Shoes"
    },
    {
      "id": "welcome-2",
      "messageType": "optInConfirmation",
      "brand": "Example Shoes",
      "text": "Example Shoes: You're signed up for sale alerts. Up to 4 msgs/mo. Msg & data rates may apply. Reply HELP for help, STOP to cancel."
    }
  ],
  "messageType": "marketing",
  "isFirstMessage": false,
  "onlyFlagged": false,
  "maxItems": 5000
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "messages": [
        {
            "id": "promo-1",
            "text": "FLASH SALE!!! 40% off everything today only – shop now: bit.ly/3xAmPle",
            "brand": "Example Shoes"
        },
        {
            "id": "welcome-1",
            "messageType": "optInConfirmation",
            "brand": "Example Shoes",
            "text": "Example Shoes: Thanks for joining! Reply STOP to cancel."
        },
        {
            "id": "promo-2",
            "text": "Example Shoes: Hi {{first_name}}, your account has been suspended. Verify your account at http://example-shoes-help.com",
            "brand": "Example Shoes"
        },
        {
            "id": "welcome-2",
            "messageType": "optInConfirmation",
            "brand": "Example Shoes",
            "text": "Example Shoes: You're signed up for sale alerts. Up to 4 msgs/mo. Msg & data rates may apply. Reply HELP for help, STOP to cancel."
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ultimatemc/sms-marketing-message-checker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "messages": [
        {
            "id": "promo-1",
            "text": "FLASH SALE!!! 40% off everything today only – shop now: bit.ly/3xAmPle",
            "brand": "Example Shoes",
        },
        {
            "id": "welcome-1",
            "messageType": "optInConfirmation",
            "brand": "Example Shoes",
            "text": "Example Shoes: Thanks for joining! Reply STOP to cancel.",
        },
        {
            "id": "promo-2",
            "text": "Example Shoes: Hi {{first_name}}, your account has been suspended. Verify your account at http://example-shoes-help.com",
            "brand": "Example Shoes",
        },
        {
            "id": "welcome-2",
            "messageType": "optInConfirmation",
            "brand": "Example Shoes",
            "text": "Example Shoes: You're signed up for sale alerts. Up to 4 msgs/mo. Msg & data rates may apply. Reply HELP for help, STOP to cancel.",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("ultimatemc/sms-marketing-message-checker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "messages": [
    {
      "id": "promo-1",
      "text": "FLASH SALE!!! 40% off everything today only – shop now: bit.ly/3xAmPle",
      "brand": "Example Shoes"
    },
    {
      "id": "welcome-1",
      "messageType": "optInConfirmation",
      "brand": "Example Shoes",
      "text": "Example Shoes: Thanks for joining! Reply STOP to cancel."
    },
    {
      "id": "promo-2",
      "text": "Example Shoes: Hi {{first_name}}, your account has been suspended. Verify your account at http://example-shoes-help.com",
      "brand": "Example Shoes"
    },
    {
      "id": "welcome-2",
      "messageType": "optInConfirmation",
      "brand": "Example Shoes",
      "text": "Example Shoes: You'\''re signed up for sale alerts. Up to 4 msgs/mo. Msg & data rates may apply. Reply HELP for help, STOP to cancel."
    }
  ]
}' |
apify call ultimatemc/sms-marketing-message-checker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ultimatemc/sms-marketing-message-checker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/feLHKeXJc1hEwHjQy/builds/PcYNyNSgdcbV9nOxy/openapi.json
