Skip to content

Channels

Thirteen channels behind one subscriber model. Each is configured per app; you connect your own provider accounts and pay providers directly at cost — WingBlaze never marks up carrier or provider fees.

ChannelDevice tokenSetup
Mobile push (FCM)FCM registration tokenUpload the Firebase service-account JSON (Setup step or POST /apps/:id/credentials/fcm)
Mobile push (APNs)APNs device tokenUpload the .p8 key + key/team id + bundle topic
Web pushPush subscriptionAutomatic — VAPID keys are generated with the app
EmailEmail addressVerified SES sender (PATCH /apps/:id/settingsemailFrom)

SMS outcomes and STOP. Twilio accepts a message long before the handset has it. Every SMS the platform sends asks Twilio for a signed delivery-status callback (/webhooks/twilio/sms-status, authenticated with an HMAC of the send's context under your auth token, nothing to configure on your side): a later undelivered / failed becomes a bounced event on the campaign and device (once per message, however often Twilio repeats it), and a number that cannot receive SMS (invalid, not a mobile, unknown handset, landline) loses its device row; a switched-off handset or a carrier filter is a bounce and nothing more. Every consequence keys on the device the callback was signed for, never on the number in the body. A number on Twilio's STOP list is refused at send time (21610): the device is disabled and the number is suppressed on the phone identity — SMS, voice, WhatsApp, RCS and KakaoTalk alike. STOP replies arrive through the incoming-message webhook: point your Twilio number's messaging webhook at https://api.wingblaze.net/webhooks/twilio/sms-inbound/<appId> (POST). Requests are verified with X-Twilio-Signature against your auth token; a STOP / UNSUBSCRIBE / CANCEL / END / QUIT reply suppresses the number on the phone identity (the send gate then silences it on voice, WhatsApp, RCS and KakaoTalk too) and disables its SMS device rows, exactly like a WhatsApp STOP; a START / UNSTOP / YES reply lifts the suppression again (device rows stay disabled until the app registers the number). The webhook answers empty TwiML, so nothing is auto-replied from here; on US and Canadian numbers Twilio's own carrier-mandated STOP confirmation still goes out. Without that webhook, a STOP is only discovered when the next send is refused with 21610, which now suppresses the number too.

Email engagement. Marketing email (campaigns and journeys) carries a signed open pixel and tracked links: every http(s) link in the body and every action button is rewritten to https://api.wingblaze.net/c/<token>, which records the click and redirects to the destination signed into the token (a link can only lead where the platform put it in that email), and a 1×1 image at /o/<token> records the open. Opens and clicks land as opened / clicked events with the campaign, device and variant attached, so email feeds campaign stats, A/B winners, cross-channel fallback, the engagement heatmap and journey goals exactly like push. One open per send and one click per link per send are recorded, however often a mail client re-renders, for 30 days after the send. Transactional mail is never tracked. Turn it off per app under Settings → Send policies (PATCH /settings {"emailTracking": false}) if your privacy policy forbids it; body links then stay plain, and mail already sent stops recording too (links keep working). An erased subscriber's mail records nothing. Some mail providers prefetch images and links on the reader's behalf (Apple Mail Privacy Protection, corporate link scanners), which registers as an open or a click before anyone reads the message — treat email open rates as an upper bound, as everywhere in the industry. Action buttons with http(s) URLs render as CTA buttons in the email; app-scheme buttons are left out of mail. | SMS | E.164 phone number | Your own Twilio account (POST /apps/:id/credentials/twilio) — carrier fees bill to you directly, never marked up. Delivery outcomes and STOP replies come back through two webhooks (below) | | WhatsApp | E.164 phone number | Your WABA credentials (POST /apps/:id/credentials/whatsapp) | | Telegram | Chat id via your bot | Bot token (POST /apps/:id/credentials/telegram) — works in campaigns, transactional sends and journeys | | RCS | E.164 phone number | RBM agent service account + agent id (POST /apps/:id/credentials/rcs) | | LINE | LINE userId via your Official Account | Channel access token (POST /apps/:id/credentials/line) | | Zalo | Zalo user id via your Official Account | OA access token (POST /apps/:id/credentials/zalo). Zalo tokens expire after 25 hours — send refreshToken, appId and secretKey alongside it and we renew it for you before it lapses; send the access token alone and you are back to re-uploading daily | | Viber | Viber user id via your bot | Bot auth token + sender name (POST /apps/:id/credentials/viber) | | Kakao | E.164 / KR phone number | Your BSP account {apiKey, apiSecret, pfId} (POST /apps/:id/credentials/kakao) | | Voice | E.164 phone number | Rides the same Twilio credentials as SMS (POST /apps/:id/credentials/twilio). Transactional lane only — a voice call is never a marketing blast, so campaign sends on this channel are suppressed |

Southeast/East-Asia channel map

Pick the rail your market actually uses: WhatsApp for Indonesia, Malaysia and Singapore; LINE for Thailand; Zalo for Vietnam; Viber alongside Messenger for the Philippines; Kakao for South Korea; Telegram as the low-cost overlay everywhere. All ride your own provider accounts at cost. Zalo note: OA access tokens expire (~25h) — automate the refresh against the credentials endpoint.

Kakao note: sends with data.kakaoTemplateId go as AlimTalk (pre-approved template — the transactional rail); without it they go as FriendTalk (the marketing rail, requires the recipient to have added your Kakao Channel). SMS fallback is always disabled, so a Kakao miss never becomes surprise carrier spend. Suppression-list checks apply by phone number, like SMS.

RCS specifics

Messages send as text with an Open suggested action when the message has a deepLink; messages with an imageUrl upgrade to a standalone rich card. Handsets that aren't RCS-capable prune automatically (like dead push tokens) — target SMS as the fallback. Your RBM agent must be approved by Google and carriers before live sends.

Delivery behavior (all channels)

  • Exactly-once: a per-run send ledger plus worker dedupe means retried jobs never double-send.
  • Dead tokens disable the device and surface as bounced events.
  • WhatsApp taps are clicks: a quick-reply button on a template, a reply button or a list row on an interactive message comes back on the Meta webhook as a reply to the message we sent; it is recorded as a clicked event on that send (campaign, device, subscriber), once per reply however often Meta redelivers it, timestamped when the person tapped, with the button's id and title in meta, and it drives journeys like any click. Sends stay attributable for 30 days; a tap we cannot attribute (a message WingBlaze did not send, or one older than that) is dropped, after a two-minute retry window that covers the moment between a send and its bookkeeping. A tapped Stop / Stop all / Unsubscribe / Opt out button — by its title or by a button id / payload of STOP, UNSUBSCRIBE or OPT_OUT, so a button labelled in any language works — is an opt-out exactly like a typed STOP and is not counted as a click (a tapped Cancel, End or Quit is a decline, not a consent withdrawal — those words only opt out when typed as the whole reply).
  • Terminal failures: a send that still cannot go out on the queue's last retry is recorded as failed with the reason (provider throttling, provider error, timeout, transport error, platform rate limit) and listed under Insights → Delivery failures; the chunk dead-letters for an operator redrive, and a redrive that lands it marks the failure recovered. See Insights.
  • Frequency caps & quiet hours (per app, subscriber-local) suppress campaign sends — never transactional ones.
  • Webhooks: HMAC-signed delivery events to your endpoint, plus the integrations catalog.

Teknokrat Niaga Sdn Bhd · No. 28-1, Jalan SP 5/2, BSP Business Center, 42610 Bandar Saujana Putra, Selangor, Malaysia · +60 3-5614 3169 · Enquiries: info@teknoniaga.com