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

One phone number with three channel options; the messaging app where the number is registered is chosen.One phone number with three channel options; the messaging app where the number is registered is chosen.

Channel selection means sending each message a customer expects on a channel that will reach them. One request tells you whether an opted-in customer's number has a WhatsApp, Telegram or Viber account. A bulk job also covers iMessage and RCS. You can route order updates, reminders and passcodes accordingly and fall back to SMS when no account exists. This use case is only for customers who have agreed to hear from you.

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.

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, viber).
  2. Run a bulk job over your opted-in customer base with checks: ["whatsapp", "telegram", "viber", "imessage", "rcs"] to include the bulk-only channels.
  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.

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 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 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.

Example request

A bulk job with five channels, two of them bulk only:

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, and our acceptable use policy forbids unsolicited bulk messaging.

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.

All articles

Know before you send.

Tell us about your use case. We review every request and set you up with test and live keys.