Use case

Channel selection for consented messaging

See which messaging apps an opted-in customer's number uses, such as WhatsApp, Telegram, Viber, iMessage or RCS, and send on a channel that arrives.

Last updated

SMS, messaging apps, social, voice and e-mail channels connect to the MobileValidate reachability engine, which returns reachable, not reachable or unknown.
Reachability across SMS, messaging apps, voice, social and e-mail.

Channel selection means sending each message a customer expects on a channel that will reach them. One lookup shows whether an opted-in customer's number has a WhatsApp or Telegram account; a bulk job adds Viber, iMessage and RCS. Route updates, reminders and passcodes accordingly, and fall back to SMS when no account exists. Only for consenting customers.

Why does channel choice matter?

A message sent on a channel the customer doesn't use is wasted. It either fails or waits unread. Messaging habits vary a lot by country. WhatsApp is the default in many markets. Viber is common in parts of Eastern Europe and Southeast Asia. LINE dominates in Japan and Taiwan, and Zalo in Vietnam. iPhone users can receive iMessage. Many Android phones, and iPhones since Apple added RCS support, can receive RCS messages. Our guide to choosing a messaging channel by country goes market by market.

Knowing which channels exist for a number helps you:

  • send passcodes on a channel that will arrive, with SMS as a fallback
  • use a channel that supports what the message needs, such as rich media, buttons or read receipts
  • avoid paying for SMS when the customer asked to be contacted on a cheaper app they use

How does the workflow look?

Channel data changes slowly, so you don't need to check before every message. A typical setup:

  1. When a customer opts in and chooses which channels they accept, run a real-time lookup for the real-time channels (whatsapp, telegram).
  2. Run a bulk job over your opted-in customer base with checks: ["whatsapp", "telegram", "viber", "imessage", "rcs"] to include the bulk-only channels (real-time Viber checks are paused for now, so Viber runs in bulk jobs only).
  3. Store the result and its checked_at against each customer in your CRM.
  4. When sending, pick from the channels the customer consented to and that show registered: true, and fall back to SMS.
  5. Refresh on a schedule, for example monthly, or when a delivery fails.

For a code version of steps 3 and 4, see the choose-channel recipe.

Which checks answer which question?

CheckWhat it answersWhen to run itLink
whatsapp / whatsapp.businessIs there a WhatsApp account? Is it a business account?At opt-in; monthly refreshWhatsApp, WhatsApp Business
telegramIs the number registered on Telegram?At opt-in, in the markets where you use itTelegram
viber, line, zalo (bulk only)Is the number registered on this app?Bulk refresh, in the markets where you use themViber, LINE, Zalo
imessage (bulk only)Can the number receive iMessage?Bulk refreshiMessage
rcs (bulk only)Can the number receive RCS, and on which handset platform?Bulk refreshRCS
carrierIs the number mobile, so SMS is a valid fallback?Once per numberCarrier lookup

What should you do with each result?

Result for a consented channelSuggested routing
registered: trueEligible. Send on this channel if the customer prefers it
registered: falseDon't use this channel for this number
registered: null (unknown)Keep the previous routing or fall back to SMS; check again later
RCS registered: true with device_osEligible for RCS. Use device_os to preview the message on the right handset platform
No channel trueUse SMS or voice

How do you choose when several channels work?

A lookup often returns more than one registered: true. The check tells you what is possible; the choice is yours. A simple order that works for most teams:

  1. The customer's stated preference. If they picked a channel at opt-in, use it while it stays registered.
  2. What the message needs. A passcode needs speed and a reliable fallback. A delivery photo or a document needs rich media. A payment reminder may need a read receipt. Rule out channels that can't carry the message.
  3. Cost per message for the destination country, including any per-conversation or template fees the platform charges.
  4. Past engagement. If a customer never reads one channel, stop using it for them, even if the account exists.

Record why a channel was chosen. When a customer asks why they got a message on an app, "you chose it on 2026-09-02 and it was registered on our last check" is a good answer. For support replies and service notices rather than campaigns, see customer support channel routing.

How much does it cost?

Each channel is a separate check, billed only when conclusive. You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). Checking five channels on one number can bill up to five checks, so check only the channels you can actually send on. Bulk jobs cost less per check than real-time lookups for most channels and are the natural fit for refreshing a customer base. See pricing for current rates.

Run POST /v1/jobs/estimate first to see the maximum cost, and pass it as max_cost when you create the job. Numbers checked recently for the same service come free from your account's cache.

What does a request look like?

A bulk job with five channels, three of them bulk only for now:

curl https://api.mobilevalidate.com/v1/jobs \
  -H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
  -H "Content-Type: application/json" \
  -d '{"numbers":["+447700900001","+447700900002"],"checks":["whatsapp","telegram","viber","imessage","rcs"]}'

Runs as pasted with the public sandbox key, which answers the test values only. In the SDKs, omit the key to use MOBILEVALIDATE_API_KEY.

The job returns straight away with its id and progress (total: 2, checks_total: 10). Fetch the rows with GET /v1/jobs/{id}/results. Response (excerpt, test mode: the first row of the results page):

JSON
{
  "kind": "phone",
  "input": "+44770*****01",
  "e164": "+447700900001",
  "country": "GB",
  "number_status": "valid",
  "checks": {
    "whatsapp.registered": {"service": "whatsapp.registered", "status": "completed", "registered": true, "attributes": null, "confidence": "high", "confidence_score": 0.99, "checked_at": "2026-09-25T14:28:27.270Z", "cached": false, "age_seconds": 1, "billed": false, "reason": null, "poll_after_ms": null},
    "telegram.registered": {"service": "telegram.registered", "status": "completed", "registered": true, "attributes": null, "confidence": "high", "confidence_score": 0.99, "checked_at": "2026-09-25T14:28:27.270Z", "cached": false, "age_seconds": 1, "billed": false, "reason": null, "poll_after_ms": null},
    "viber.registered": {"service": "viber.registered", "status": "completed", "registered": true, "attributes": null, "confidence": "high", "confidence_score": 0.99, "checked_at": "2026-09-25T14:28:27.270Z", "cached": false, "age_seconds": 1, "billed": false, "reason": null, "poll_after_ms": null},
    "imessage.registered": {"service": "imessage.registered", "status": "completed", "registered": true, "attributes": null, "confidence": "high", "confidence_score": 0.99, "checked_at": "2026-09-25T14:28:27.270Z", "cached": false, "age_seconds": 1, "billed": false, "reason": null, "poll_after_ms": null},
    "rcs.registered": {"service": "rcs.registered", "status": "completed", "registered": true, "attributes": null, "confidence": "high", "confidence_score": 0.99, "checked_at": "2026-09-25T14:28:27.270Z", "cached": false, "age_seconds": 1, "billed": false, "reason": null, "poll_after_ms": null}
  }
}

Stored results show the input masked (+44770*****01). The normalized e164 is returned so you can match rows to your records.

What limits and rules apply?

A job takes up to 50,000 numbers and e-mails and up to 20 checks. The total of rows × checks can't exceed 100,000. Requests that look like sequential number ranges or generated e-mail lists are rejected. Each account also has a daily cap on numbers. Job data is kept for 30 days by default, and you can delete a finished job's data at any time with DELETE /v1/jobs/{id}.

This use case is only for messages to people who agreed to receive them. Don't check number lists to find out who uses an app, and don't start conversations on a channel because an account exists. Messaging platforms require opt-in for business messages; for example, WhatsApp's Business Messaging Policy does. Our acceptable use policy forbids unsolicited bulk messaging. Platform names are used descriptively; MobileValidate isn't affiliated with or endorsed by any messaging platform.

Keep consent per channel and per purpose: agreeing to order updates on an app is not agreeing to promotions there.

What are the common mistakes?

  • Treating registration as permission. An account shows the channel works, nothing more.
  • Checking channels you don't send on. Every channel is a separate charge. Check only the ones in your routing table.
  • Reading unknown as false. Unknown is missing data. Keep the current routing.
  • Never refreshing. Use checked_at and a monthly bulk job to keep routing current.
  • Forgetting the fallback. Always keep SMS or voice available for customers with no app channel.

Frequently asked questions

Does a messenger account mean I may message that person there?

No. An account shows the channel can reach the number. Your right to send depends on the person's consent and the platform's business messaging rules, which usually require opt-in.

Why are iMessage and RCS bulk only?

Those checks are only offered in bulk jobs in our API. Run them in a job ahead of time, for example when a customer signs up or once a month, and store the channel preference in your CRM.

How often should I refresh channel data?

People switch phones and apps, and numbers get reassigned. Refreshing active customers every few weeks, or before a major send, keeps routing current. Each result carries checked_at so you can see its age.

What does the RCS check add?

It reports whether the number can receive RCS messages and, when known, the handset platform in device_os (ios, android or unknown).

Which channel should I pick when several exist?

Use the channel the customer chose. When they allowed several, pick by cost, the features the message needs and the customer's past engagement. The check tells you what is possible, not what they prefer.

What if a channel check returns unknown?

Keep the previous routing or fall back to SMS, and check again later. Unknown means no conclusive answer; it is not a no, and it is never charged.

Can I check whether a WhatsApp number is a business account?

Yes. The WhatsApp Business check answers whether an account exists and whether it is a business account. If you request whatsapp and whatsapp.business together, only the business check runs and you pay for one check.

All articles

Know before you send.

Create a free account: approved automatically, usually within 10–15 minutes.

Free to start: check 20 phone numbers and 10 e-mail addresses for real on your account, plus an unlimited test mode. You pay only for conclusive answers, from $20.