Mudamos o site para Português (Brasil) para você.View in English
Docs

Canais de mensagens

Conecte Telegram, SMS, WhatsApp, Messenger e Instagram e veja o que cada canal pode e não pode fazer.

Este guia está em inglês. Os guias acompanham o produto de perto e mudam com frequência, por isso mantemos uma única versão precisa em vez de traduções desatualizadas.

Customers can write in from Telegram, SMS, WhatsApp, Messenger and Instagram. Every conversation lands in the shared inbox, and agents reply from the same composer. You connect your own accounts with each provider.

Telegram

Setup

  1. In Telegram, talk to @BotFather: send /newbot and pick a name and a username ending in bot.
  2. Copy the bot token (123456789:AA…).
  3. In IsTyping, go to Settings → Channels → Connect Telegram, paste the token and click Connect. IsTyping then:
    • calls getMe;
    • calls setWebhook with a per-connection secret path and a random secret_token, and allowed_updates = message, edited_message, my_chat_member;
    • checks the X-Telegram-Bot-Api-Secret-Token header on every update (constant-time comparison).
  4. Share https://t.me/<bot username> with customers.
    • Add ?start=<payload> (letters, digits, _ or -, up to 64 characters) to learn where a customer came from.
    • The payload is stored on the visitor (data.telegram_start) and shown in the details panel.

What the adapter supports

Chats

  • Private chats only. Group, supergroup and channel updates, and messages from other bots, are acknowledged and ignored.

Inbound

  • Text, photos (the largest size within 20 MB), documents, voice notes (stored as audio/ogg audio files), audio, video and video notes. Files are downloaded with getFile plus the file URL.
  • Stickers, locations, venues, contact cards, polls and dice become readable text, for example [Sticker 😀] or 📍 Location: 51.50070, -0.12460.
  • A contact card the user shares of themselves (contact.user_id == from.id) gives the identity a provider-asserted phone number. Anyone else’s contact card does not.

Outbound

  • Text is sent as plain text, with no parse_mode, so nothing can be read as markup and nothing needs escaping. Text over 4096 characters is split.
  • Images are uploaded as photos (multipart, up to 10 MB). Other files are uploaded as documents (our upload limit of 10 MB applies).
  • Operator typing sends sendChatAction typing, throttled to once every 4 seconds.

Edits and deletes

  • An operator edit of a delivered text message calls editMessageText. A delete calls deleteMessage, which Telegram only allows for messages under 48 hours old.
  • The outcome is shown under the message, for example “Edited here and on Telegram.”
  • An edited_message from the customer is appended as a new message, “✏️ Edited an earlier message: …”. The messages feature only exposes edits through its own operator and visitor routes, so a provider edit never rewrites what operators already read.

Blocking and errors

  • my_chat_member with status kicked marks “blocked the bot”. Writing again clears it.
  • Sending: 429 is retried after retry_after. 5xx and network errors are retried with backoff.
  • 403 is permanent and marks the bot as blocked. 401 and 404 mean the token was revoked; the connection shows “Needs attention”.

Not possible on Telegram

  • Bots cannot start conversations; this is Telegram’s rule, and an operator start is refused with cannot_initiate.
  • Telegram has no delivery or read receipts, so “Sent to Telegram” is the final state.
  • Inline keyboards (chatbot buttons) are not used in this version.

Limits to expect

  • About 1 message per second per chat, about 30 per second per bot overall, 20 per minute in groups.
  • Bot downloads up to 20 MB; uploads up to 10 MB for photos and 50 MB for other files.
  • Telegram keeps undelivered updates for up to 24 hours and retries a failing webhook “a reasonable amount” of times (the schedule is undocumented).

SMS (Twilio)

Setup

  1. In the Twilio console, note your Account SID and Auth token (Account → API keys & tokens).
    • The auth token is always required, because Twilio signs webhooks with it.
    • You can also enter an API key SID + secret. REST calls then use the key, which is recommended.
  2. Get an SMS-capable number. In the US, register A2P 10DLC or verify a toll-free number, otherwise carriers filter your messages (error 30007). A Messaging Service (MG…) works too.
  3. In IsTyping, go to Settings → Channels → Connect SMS and enter the SIDs, the token and the sender. Keep “Set the webhook through the Twilio API” on:
    • For a phone number, IsTyping sets the number’s SmsUrl (POST).
    • For a Messaging Service, it sets InboundRequestUrl and StatusCallback. “Use inbound webhook on number” must be off on its numbers.
  4. If you prefer, paste the two URLs shown by hand:
    • Incoming messages: Phone number → Messaging → “A message comes in”, Webhook, HTTP POST.
    • Status callback: sent with every message automatically. For a Messaging Service, also set it as the service’s status callback.

What the adapter supports

Webhook security

  • X-Twilio-Signature is checked exactly as Twilio documents it: HMAC-SHA1 of the full public URL plus every POST parameter, sorted by name, base64-encoded, compared in constant time.
  • Requests with no signature, a wrong signature, a tampered body or extra parameters, or a different URL get 403. An unknown path token gets 404.
  • Replays are de-duplicated on MessageSid.

Inbound

  • Text and MMS media. Media URLs must be on the Twilio API host. They are fetched with Basic auth, and one redirect to Twilio’s short-lived URL is followed without credentials. Size is capped at 5 MB.

Outbound

  • Text up to 1600 characters, which is Twilio’s cap. Longer text is refused, never truncated. The composer shows characters / 1600 · n SMS (GSM-7 160/153, UCS-2 70/67, extension characters count double).
  • MMS images: JPEG, PNG or GIF, up to 5 MB.
  • Each send carries StatusCallback.

Delivery states

  • Status callbacks drive sent → delivered and failed / undelivered. They are never applied backwards, because callbacks can arrive out of order.
  • Common error codes are shown in plain words: 21610 opted out, 21211 invalid number, 21408 geo permissions, 21614 not a mobile number, 30003 unreachable handset, 30004 blocked, 30005 unknown handset, 30006 landline, 30007 carrier filtered, 30008 unknown.

Opt-out

  • STOP, STOPALL, UNSUBSCRIBE, CANCEL, END, QUIT, REVOKE or OPTOUT (and Advanced Opt-Out’s OptOutType=STOP) set “opted out” on the identity and record an event.
  • From then on every reply is refused before calling Twilio, with the reason “The customer opted out (STOP) …”, and the composer is blocked.
  • START, UNSTOP, YES (or OptOutType=START) opt the customer back in.
  • A 21610 from Twilio also sets the flag.
  • HELP and INFO are passed through. Twilio answers them itself for long codes.

Costs and compliance (SMS)

  • Every segment is billed, outbound and inbound. Long or Unicode messages cost more, so watch the counter.
  • Consent. Only message people who agreed to it. Operators can start an SMS conversation only to a contact with a phone number and a recorded consent (Contact → “Text messaging”: who recorded it, when and how). This is audited in channel_audit (and the tenant audit log) and rate-limited (30 per operator per hour, 300 per website per day).
  • Toll-fraud limits (Settings → Channels → “Starting SMS and WhatsApp conversations”, admin+; server-enforced, modules/channels/outbound-policy.ts). A number that never messaged the website is a new number: only admins may record consent for it and start a conversation with it (agents still reply to, and may start with, numbers that wrote in). Operator-started SMS / WhatsApp only go to the destination countries — by default the countries of the website’s own sender numbers (+1 876 is Jamaica, not the US; calling codes without a country such as +881 are never allowed) — refused with country_not_allowed otherwise. At most 20 (configurable, hard maximum 200) operator-started conversations with new numbers per website per 24 h (daily_cap_reached).
  • Honour STOP. Twilio enforces it on long codes and toll-free numbers, and IsTyping refuses to send.
  • Identify your business in first messages and keep HELP answers configured in Twilio.

WhatsApp (Twilio)

Setup

  1. Sandbox (testing). Twilio Console → Messaging → Try WhatsApp.
    • Customers first send join <code> to +1 415 523 8886. Sessions last 3 days, and only joined numbers can be messaged.
    • The sandbox has no custom templates (only Twilio’s pre-approved ones) and sends at most 1 message every 3 seconds.
    • Production: register a WhatsApp Business sender (Meta Business verification, display name approval).
  2. In IsTyping, go to Settings → Channels → Connect WhatsApp and enter the SIDs, the token and the sender number (E.164, without whatsapp:) or a Messaging Service SID.
  3. Paste the Incoming messages URL into the sender’s (or Sandbox’s) “When a message comes in” field. The Twilio API can set it only for Messaging Service senders.
  4. Add your approved templates under the connection.
    • Create them in Twilio’s Content Template Builder and get them approved.
    • Then enter the Content SID (HX…), the approved text with {{1}} placeholders, and a label for each placeholder. IsTyping does not create or approve templates.

What the adapter supports

Reply window

  • The customer-service window is tracked from the customer’s last inbound message.
  • Inside the 24 hours: free-form text and files (JPEG/PNG images, OGG/AMR/AAC/MPEG audio, MP4 video, PDF), up to 5 MB.
  • Outside the window, or before the customer has written: the composer explains that free-form replies are not allowed and offers Send a template.
    • The template is sent as ContentSid plus ContentVariables, with no Body.
    • The inbox shows the rendered text.
    • With no template configured, nothing can be sent, and the composer says so.
  • A free-form message outside the window is refused before calling Twilio. A 63016 from Twilio (if the windows disagree) is shown as the same error.

Other behaviour

  • ProfileName becomes the visitor name. The sender number is carrier/WhatsApp-asserted.
  • Read receipts: read callbacks tick the message as read.
  • An operator edit or delete cannot be applied on WhatsApp. It is noted honestly: “Deleted here; already delivered to the customer (WhatsApp messages cannot be unsent).”
  • Operator-initiated WhatsApp needs a phone number, recorded consent and a template.

Costs and compliance (WhatsApp)

  • Meta charges per conversation or template category (marketing, utility, authentication, service) plus Twilio’s per-message fee.
  • Template-initiated conversations are the expensive kind; replies inside the window are cheap or free, depending on current Meta pricing.
  • Only message users who opted in to WhatsApp messages from you, and use the right template category. Misclassified marketing templates get re-categorised or rejected by Meta.

Messenger and Instagram (Meta)

Facebook Messenger and Instagram Direct come through one Meta app (a “Business” app on developers.facebook.com). The platform admin configures it once; website admins then connect their Facebook Page (and the Instagram professional account linked to it) with “Connect with Facebook”.

meta-service.ts (app settings, Facebook Login, webhook routing, token health, compliance), meta-routes.ts.

  • Dashboard: Platform → Channels (features/channels/meta.tsx → PlatformChannelsPage), Settings → Channels.

Verified only against a fake. No Meta app, Facebook Page or Instagram professional account was available when this was built. It follows Meta’s documentation as read on 2026-11-10 (sources in section 11) and is tested against fake-meta.ts, which is only as faithful as those pages. Do the steps in “Testing for real” before customers rely on it.

5.1 Creating the Meta app (platform admin)

  1. On developers.facebook.com → My Apps → Create app → type Business. Connect it to your business portfolio.

  2. Add these products: Messenger, Instagram (the “Instagram API with Facebook Login” / Messenger API for Instagram setup), Facebook Login for Business (or Facebook Login), Webhooks.

  3. In IsTyping, go to Platform → Channels and enter the App ID and App Secret (App settings → Basic). The secret is stored encrypted and is never shown again. Pick the Graph API version (default v27.0, the current one; versions v21.0–v26.0 are still served).

  4. Paste the values IsTyping shows into the App Dashboard:

    Value Where it goes
    Webhook callback URL https://<host>/api/v1/channels/meta/webhook Webhooks → Page object → Callback URL, and Webhooks → Instagram object → Callback URL (the same URL)
    Verify token (generated by IsTyping; “New verify token” rotates it) Webhooks → Verify token (both objects)
    OAuth redirect URI https://<host>/api/v1/channels/meta/oauth/callback Facebook Login → Settings → Valid OAuth Redirect URIs (exactly; “Strict mode” on)
    Data deletion URL https://<host>/api/v1/channels/meta/data-deletion App settings → Advanced / Data deletion → Data deletion callback URL
    Deauthorize URL https://<host>/api/v1/channels/meta/deauthorize Facebook Login → Settings → Deauthorize callback URL
  5. Webhook fields:

    • Page: IsTyping subscribes each connected Page itself (POST /{page-id}/subscribed_apps with messages, messaging_postbacks, messaging_referrals, message_deliveries, message_reads, message_echoes, message_reactions, message_edits). In the App Dashboard, subscribe the app’s Page object to the same fields.
    • Instagram: tick messages, messaging_postbacks, messaging_seen, messaging_referral, message_reactions by hand. The API cannot set Instagram fields.
  6. Click Test the app. It makes an app-token call (GET /{app-id} with {app-id}|{app-secret}). A wrong ID or secret gets a clear error.

  7. Only tick “This app has been approved for Human Agent” once Meta approved the Human Agent feature (see 5.5).

  8. Until an app is configured, Messenger and Instagram are hidden for every website.

One app-level endpoint. Meta sends every Page’s events for an app to one callback URL. The receiver:

  • checks X-Hub-Signature-256 against the app secret over the raw bytes;
  • routes each entry by its id: the Page id for object page (Messenger), the Instagram account id for object instagram;
  • accepts an entry only if that connection uses the app that signed the body. Entries for unknown or disconnected Pages are acknowledged and dropped. Platform → Channels shows how many, and why.

A website’s own Meta app (optional, owner). Settings → Channels → “Your own Meta app”. Use it when a business must use its own app.

  • The redirect URI and compliance URLs are the same. The webhook callback URL is the app’s OWN: https://<host>/api/v1/channels/meta/webhook/<app config id> (shown in Settings → Channels). The receiver checks exactly that app’s secret over the raw body before it reads anything (security review: an unauthenticated POST costs one HMAC — no parsing, database access or queueing). Its webhooks only count for Pages connected with it, so a tenant’s app can never inject events for another app’s Pages.
  • Deployment note: a website app configured before this change with the shared …/webhook URL must have its callback URL updated in the Meta App Dashboard (the shared URL only accepts the platform app now).
  • The GET handshake on each URL accepts only that app’s verify token.
  • Replay protection: signed signed_request callbacks (data deletion, deauthorize) are accepted once (a hash is kept for their one-hour validity, channel_meta_signed_requests); Meta events older than 29 days are refused; processed inbound queue rows are deleted after 30 days and never-processed ones after 90 (channels-retention job), and an already imported provider message is recognised by channel_messages. Media downloads follow at most 3 redirects, each hop re-checked (a Meta media host whose addresses are public).

5.2 Connecting a Page / an Instagram account (website admin)

Prerequisites

  • Messenger: a Facebook Page, and a Facebook account that can manage the Page’s messages (full control, or the “Messages” task).
  • Instagram: an Instagram professional account (business or creator) linked to that Page. In the Instagram app: Settings → Messages and story replies → Message controls → Connected tools → Allow access to messages.
  • Development mode: while the Meta app is in development mode, only people with a role on the app can log in and message the Page.

Connect with Facebook (Settings → Channels → Connect Messenger / Connect Instagram)

  1. IsTyping creates a single-use login flow. It is bound to the browser (cookie), the operator’s session and the website, and sends the browser to https://www.facebook.com/{version}/dialog/oauth with:
    • client_id;
    • the exact redirect URI built from PUBLIC_URL;
    • a random state;
    • only the permissions of the chosen channel(s).
  2. On the callback, IsTyping checks the state, the cookie and the session. It then exchanges the code for a short-lived user token and that for a long-lived user token, server-side with the app secret.
  3. IsTyping reads /me/permissions and /me/accounts: the Pages with their Page access tokens and linked instagram_business_account.
  4. The admin picks a Page (within 30 minutes). IsTyping then:
    • stores that Page token sealed;
    • subscribes the app to the Page;
    • records the Page id, Instagram id, names and pictures. The pictures are stored as our own files, because Meta’s URLs expire.
  5. The user tokens are never stored: reconnecting means logging in again. Page tokens obtained from a long-lived user token do not expire while the person’s grant stands.
  6. Redirects only ever go to /w/<website>/settings/channels?..., built from the flow’s website id. There is no open redirect.
  7. No PKCE: Meta documents PKCE only for its OIDC login flow (“in testing”, openid scope), not for the Page permission flow.

Login failures are shown in plain words:

  • the user cancelled or declined;
  • the user manages no Pages;
  • a forged or replayed state, or another browser;
  • the user was signed out meanwhile;
  • the exchange failed (wrong secret or redirect URI).

Picking a Page

  • Missing permissions are listed in the picker.
  • A Page without a linked Instagram account cannot connect Instagram.
  • One Page → one website: a Page (or its Instagram account) already connected to another website on this install is refused.
  • Connecting a Page that is already connected here reconnects it (new token, status back to active).

Paste a Page access token (developers)

  • Useful in development mode with the Graph API Explorer. IsTyping checks the token with debug_token: it must be valid, for this app, of type PAGE, carry the channel’s scopes, and not expire within a day.

Disconnect

  • Deletes the token and unsubscribes the app from the Page, using the app token so it works with a dead Page token.
  • When Messenger and Instagram of one Page are both connected, removing one keeps the subscription.

Token health

  • What marks a connection “needs reconnect”:
    • error 190 on any call;
    • debug_token saying invalid (a job checks every connection every 12 hours);
    • the Deauthorize callback.
  • The connection card then shows a “Needs reconnect” banner with Reconnect with Facebook.
  • Replies are refused before calling Meta, so there is no retry loop on a dead token. Incoming messages still arrive, because webhooks do not depend on the Page token.

5.3 What the adapters support

Identities and display

  • One visitor per (website, kind, page-scoped id): PSID for Messenger, IGSID for Instagram. verified: false.
  • Name, @username and picture come from the profile API:
    • Messenger: GET /{psid}?fields=first_name,last_name,profile_pic, which needs the “Business Asset User Profile Access” feature;
    • Instagram: GET /{igsid}?fields=name,username,profile_pic, which needs the person’s consent (they messaged you).
  • Profiles are refreshed after 7 days. A refusal is remembered for a day and the visitor becomes “Messenger user 1234”.
  • Meta gives no email or phone, so identities are never linked to a contact automatically. Operators can link one by hand.
  • The details panel shows “Messenger · <Page>” / “Instagram · @handle”. It shows a profile link only if the API returns one (the profile APIs used here do not).

Inbound

  • Text, images, video, audio, files (stored; at most 25 MB from Meta and our upload limit).
  • Quick replies (text plus “(quick reply)”).
  • Postbacks (“🔘 Tapped “Get started””).
  • Referrals (m.me ?ref= and ads): “🔗 Came from a link (ref …)”, stored as the “Came from” value.
  • Edits are appended as “✏️ Edited an earlier message: …”. They never rewrite what operators read.
  • Reactions (and their removal) become timeline events, not unread messages.
  • Instagram stories:
    • Story replies and mentions: the story media is downloaded at once (the CDN URL expires) and stored.
    • When it is already gone: “(the story is no longer available)” / “Attachment not stored … the link expired”.
  • Shares and reels become “🔗 Shared a post / reel”. Unsupported types become a placeholder.
  • Instagram unsend (is_deleted): the stored message is tombstoned through the messages feature’s delete semantics. Operators see “Message deleted” plus an event. An unsend processed before the message itself means the message is never shown.
  • Messenger documents no unsend webhook.
  • standby (another app owns the thread), handover and opt-in events are ignored safely.

Echoes (is_echo: messages the Page itself sent)

  • Ours are dropped: echoes carrying our app id, or a message id we stored.
  • Messages sent from the Page’s own inbox / Meta Business Suite / another tool appear once as an operator message by “Sent from Meta inbox”. They are never sent again.

Receipts

  • Messenger message_deliveries (mids or watermark) → delivered.
  • message_reads (watermark) and Instagram messaging_seen (read.mid) → read; the message reads as read.

Outbound

  • Text: Messenger “less than 2000 characters”; Instagram 1000 bytes (UTF-8). Longer text is split into several messages.
  • Messenger files are uploaded with the Attachment Upload API (multipart filedata, then attachment_id). Meta never fetches our URL.
  • Instagram files (JPEG/PNG images, MP4 video, AAC/MP4/MPEG/WAV audio, PDF) are sent by URL: our public-but-unguessable /files/<website>/<key>/<name> URL.
    • Meta’s fetcher must reach it over public HTTPS with a valid certificate and the right Content-Type.
    • A CDN bot challenge (Cloudflare “Bot Fight”, JS challenge) in front of /files/* makes these sends fail with 100/2018008 “could not download the file”.
  • Images over 8 MB are refused (Meta’s image limit).
  • Typing: the composer’s typing hook sends typing_on, preceded once per new customer message by mark_seen. mark_seen is also sent before a reply. Opening a conversation alone does not mark it seen (there is no read hook in the framework).
  • Operator edits and deletes cannot be applied on Meta; this is noted under the message (“… cannot be unsent”).

5.4 Messaging windows and tags (as implemented)

Since the customer’s last message Rule Composer
< 24 hours messaging_type: RESPONSE “Messenger window open for 3 h 12 min”
24 hours – 7 days, app approved for Human Agent (platform tick) messaging_type: MESSAGE_TAG, tag: HUMAN_AGENT amber panel: “your reply goes out with the Human Agent tag … use it only for a person answering a support request”; hint “Human Agent tag · closes in 4 d 2 h”
24 hours – 7 days, not approved nothing is sent blocked: “… the 7-day Human Agent tag is not enabled for this Meta app …”
> 7 days, or the customer never wrote nothing is sent blocked: “… does not allow replies now. The customer has to write again.”
  • Businesses cannot start Messenger / Instagram conversations (cannot_initiate).
  • No other message tags are used. ACCOUNT_UPDATE, CONFIRMED_EVENT_UPDATE and POST_PURCHASE_UPDATE are deprecated (error 100 since 2026-04-27). Sending outside the rules risks the Page’s messaging.
  • The window is checked again before every attempt. A Meta 10/2018278 (if the clocks disagree) is shown as “outside Messenger’s messaging window”.

Errors in plain words

Meta error What operators read Effect
190 “Facebook no longer accepts this connection’s access … Reconnect” needs reconnect, no retries
10/2018278, 10/2534022 outside the messaging window not retried
551 or */1545041 “the customer can’t receive … right now (blocked the Page, restricted messages or deleted their account)” composer blocked until they write again
200/2534041 the Instagram owner turned off “Allow access to messages” connection error
4, 17, 32, 613, 80006 “rate limit — retrying in N s” (from X-Business-Use-Case-Usage) retried
613/2018338 tags flagged as abusive not retried
200 / 10 (others) missing permission (before App Review only app-role users can be messaged) not retried
100/2018001, 100/2534014 the person is not known any more not retried
100/2018008 Meta could not download the file (CDN challenge / not public) not retried
1, 2, 5xx temporary problem retried

5.5 Permissions, App Review and Business Verification

Channel Permissions (Advanced Access)
Messenger pages_show_list, pages_manage_metadata, pages_messaging
Instagram the above + pages_read_engagement, instagram_basic, instagram_manage_messages
Optional business_management (Pages owned by a business portfolio)

Features to request

  • Human Agent, for 7-day replies. It needs App Review and Business Verification.
  • Business Asset User Profile Access, for names and pictures.

Access levels

  • Standard Access (no review) works only for people with a role on the app.
  • Real customers need Advanced Access for each permission. That needs App Review, and Advanced Access needs Business Verification.
  • Meta also requires the app to be Live (published) for webhooks from non-role users.

What the reviewer will test. Record a screencast per permission and give the reviewer a test account:

  1. Login flow (pages_show_list, pages_manage_metadata, instagram_basic, business_management): Settings → Channels → Connect Messenger → Connect with Facebook → the Facebook dialog → back in IsTyping, the Page picker lists the Page (with its Instagram account) → Connect.
  2. Receiving a message (pages_messaging, instagram_manage_messages): send a message to the Page from another Facebook account and a DM to the Instagram account. Show them arriving in the inbox.
  3. Sending a message (pages_messaging, instagram_manage_messages): reply from the inbox. Show the reply in Messenger / Instagram and the delivered/read tick.
  4. Human Agent: a conversation 24 hours – 7 days old. Show the amber “Human Agent tag” notice, and explain that only human support replies use it.
  5. Data deletion: show the callback URL and a confirmation page.

5.6 Compliance callbacks

Data deletion (POST /api/v1/channels/meta/data-deletion, form field signed_request)

  1. The signed request is base64url(signature).base64url(payload), HMAC-SHA256 with the app secret. It is verified against the platform app and every website’s own app; a bad signature gets 403.
  2. The payload’s user_id is app-scoped: the Facebook user who removed the app, in practice the Page admin who logged in. IsTyping:
    • removes that id from connections and deletes their Page token, which that user granted (the connections then need a reconnect);
    • erases, through the privacy registry (eraseScope, delete mode), any Messenger / Instagram identity whose id equals it on Pages of that app, across all websites. Customers’ PSIDs/IGSIDs differ from app-scoped ids, so this normally finds nothing; customers ask the business directly.
  3. The answer is { url, confirmation_code }.
  4. GET /api/v1/channels/meta/data-deletion/<code> shows only the status and dates: no ids, names or Pages.

Deauthorize (POST /api/v1/channels/meta/deauthorize)

  • Uses the same signed request. The Pages connected by that user show “needs reconnect”.

5.7 Development-mode testing (app roles)

  1. Keep the app in development mode. Add yourself and testers under App roles. Only they can log in and message.
  2. Configure the app in Platform → Channels and click Test the app.
  3. In the App Dashboard, verify both webhook objects: Meta calls the GET handshake, and the verify token must match.
  4. Connect your test Page in Settings → Channels.
  5. From a tester account, message the Page and DM the Instagram account. Reply from the inbox.
  6. App Dashboard → Webhooks → “Test” sends sample events. They name Page 0 / random ids, so IsTyping acknowledges and drops them (visible in Platform → Channels).

5.8 Common failures

  • Webhook verification fails in the App Dashboard: wrong verify token, wrong PUBLIC_URL, or a CDN challenge on /api/v1/channels/*.
  • Nothing arrives:
    • the Page is not subscribed (connection card → Re-subscribe webhooks);
    • Instagram fields are not ticked in the App Dashboard;
    • “Allow access to messages” is off in Instagram;
    • the app is in development mode and the sender has no role;
    • Meta disabled the webhook after an hour of failures (check the App Dashboard alerts and re-subscribe).
  • “invalid signature” in the log: the App Secret in IsTyping does not belong to the app that sends the webhook.
  • Login says “exchange failed”: wrong App Secret, or the redirect URI in Facebook Login settings is not exactly the one shown.
  • Replies fail with “missing a permission”: before App Review only app-role users can be messaged.
  • Instagram files fail with “could not download the file”: /files/* is behind a bot challenge, or not public HTTPS.
  • A CDN or bot challenge must not sit in front of /api/v1/channels/* (webhook + compliance callbacks), /api/v1/channels/meta/oauth/* (the browser comes back from Facebook) and /files/* (Instagram media, pictures).

Identities, contacts and conversations

Identities

  • One visitor per (website, channel kind, external user id): Telegram user id, the E.164 number for SMS and WhatsApp, the Page-scoped id (PSID / IGSID) for Messenger and Instagram.
  • It has no browser session and verified: false, and the provider’s profile name, username and phone.

Contacts

  • An identity is linked to a Contact only through a phone number the provider asserts: the SMS/WhatsApp sender, or a Telegram contact the user shared of themselves.
  • The link happens only when exactly one contact has that number (digits compared). Otherwise an operator links it by hand in the details panel (“Link to contact…”, audited).
  • Linking never enriches or changes the contact, and never sets the visitor’s email. Unread-reply emails therefore never go to channel customers.

Conversations

  • Identities are never merged into a browser visitor’s chat or an email identity, even with the same phone number.
  • One conversation per identity. It is created pending on the first message and reopened (with a reopened event) when resolved.
  • Conversation.channelConnection says which bot or number the conversation came through, and replies go out through it.
  • If the same person writes to two numbers of the website, the latest one wins.

What the details panel shows

  • The identity: formatted number or @username, and an “Unverified” or “Number from the provider” badge with an explanation.
  • Opt-out and blocked-bot state, the start payload, and the linked contact.