{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-docs/conversation/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"product":"Conversation","type":"markdown"},"seo":{"title":"Webhook routing","siteUrl":"https://developers.sinch.com","llmstxt":{"title":"Sinch Developer Documentation","description":"LLMs.txt containing a map of all the documentation files for Sinch.","sections":[{"title":"Numbers API","description":"The Numbers API enables you to search for, view, and activate numbers. It's considered a precursor to other APIs in the Sinch product family. The numbers API can be used in tandem with any of our APIs that perform messaging or calling.","includeFiles":["docs/numbers/**/*.md","docs/numbers/**/*.yaml"],"excludeFiles":["docs/numbers/index.md"]},{"title":"Conversation API","description":"Send and receive messages globally on many popular channels with ease and confidence when using Sinch's Conversation API. Conversation API is the preferred API for sending mobile messages on SMS and other social channels with Sinch. It is a simple API with unified error messages, consistent request payloads, and common webhook payloads that are channel-agnostic.","includeFiles":["docs/conversation/**/*.md","docs/conversation/**/*.yaml"],"excludeFiles":["docs/conversation/index.md"]},{"title":"Voice API","description":"The Voice API works as a big telephony switch. The Voice API handles incoming phone calls (also known as incoming call “legs”), sets up outgoing phone calls (or outgoing call “legs”), and bridges the two. The incoming call leg may come in over a data connection (from a smartphone or web application using the Sinch SDKs) or through a local phone number (from the PSTN network). Similarly, the outgoing call leg can be over data (to another smartphone or web application using the Sinch SDKs) or the PSTN network.","includeFiles":["docs/voice/**/*.md","docs/voice/**/*.yaml"],"excludeFiles":["docs/voice/index.md"]},{"title":"Verification API","description":"The Verification API is a platform for phone number verification. It consists of the API and different software development kits (the Sinch SDKs) that you integrate with your smartphone or web application and cloud based back-end services. Together they enable SMS, Flashcall, Phone Call and Data verification in your application.","includeFiles":["docs/verification/**/*.md","docs/verification/**/*.yaml"],"excludeFiles":["docs/verification/index.md"]},{"title":"Provisioning API","description":"Provisioning API allows you to programmatically set up your senders, accounts and templates on your favorite messaging platforms on the Conversation API. For now, you can create your first WhatsApp channel through Meta's Embedded sign up, you can configure your first SMS App and configure your webhooks. As development continues, we will be adding the most commonly used channels.","includeFiles":["docs/provisioning-api/**/*.md","docs/provisioning-api/**/*.json"],"excludeFiles":["docs/provisioning-api/index.md"]},{"title":"Elastic SIP Trunking API","description":"With Elastic SIP Trunking you can create and manage your SIP trunks and phone numbers programmatically.","includeFiles":["docs/est/**/*.md","docs/est/**/*.yaml"],"excludeFiles":["docs/est/index.md"]},{"title":"Fax API","description":"Send and receive HIPAA compliant faxes on our modern fax platform using our developer-friendly API.","includeFiles":["docs/fax/**/*.md","docs/fax/**/*.yaml"],"excludeFiles":["docs/fax/index.md"]},{"title":"In-app Voice and Video SDK","description":"The In-app Voice and Video SDK enables you to add voice and video calling capabilities directly into your mobile or web application using the Sinch SDKs.","includeFiles":["docs/in-app-calling/**/*.md"],"excludeFiles":["docs/in-app-calling/index.md"]},{"title":"Number Lookup API","description":"The Number Lookup API is designed to provide in-depth information about phone numbers, helping enterprises enhance their communication strategies and prevent fraud. By identifying the type of phone line (for example, mobile, landline, VoIP) and the associated carrier, the API allows businesses to optimize routing, reduce unnecessary costs, and improve customer engagement.","includeFiles":["docs/number-lookup-api-v2/**/*.md","docs/number-lookup-api-v2/**/*.yaml"],"excludeFiles":["docs/number-lookup-api-v2/index.md"]},{"title":"Functions","description":"Serverless compute for voice and messaging. Deploy your code and Sinch routes live calls and messages to it — no infrastructure to run.","includeFiles":["docs/functions/functions/**/*.md","docs/functions/concepts/**/*.md","docs/functions/reference/**/*.md"],"excludeFiles":["docs/functions/functions/index.md"]},{"title":"CLI","description":"One command line for every Sinch API and the full Functions lifecycle — scaffold, run locally, deploy, and manage.","includeFiles":["docs/functions/cli/**/*.md"],"excludeFiles":["docs/functions/cli/index.md"]}]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"webhook-routing","__idx":0},"children":["Webhook routing"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Webhook routing lets you define fine-grained rules that determine where the Conversation API should deliver specific callbacks. With routing enabled, a single Conversation API app can send different callback types (for example, inbound messages vs. delivery reports) to different URLs based on message content, sender, channel, or status."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This page explains how webhook routing works, how to configure webhook routing, and provides ready-to-use examples."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Open beta"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Webhook routing is currently available for open beta usage. Interfaces and behavior may change before general availability."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["During the open beta, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," matching is only supported for the SMS and MMS channels. For all other channels, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id"]}," field is empty in callbacks, and any routing rule using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," will not match. Support for additional channels may be added in the future."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"important-information","__idx":1},"children":["Important information"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Note the following important pieces of information about webhook routing:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Webhook routing is configured per webhook in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["routing_configuration"]}," field."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Webhook routing currently supports routing for the following triggers:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_INBOUND"]}," (inbound contact messages, also called MO)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_DELIVERY"]}," (delivery reports for app messages, also called DR)"]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["When no rule matches, you can either send the callback to the webhook's default ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["target"]}," or discard it, based on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fallback_behavior"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["You can optionally specify a per-rule HMAC ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["secret"]}," to override the webhook's default secret for signature verification."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["More specific information is provided throughout the rest of this document."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"how-rule-matching-works","__idx":2},"children":["How Rule Matching Works"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["At runtime, the Conversation API evaluates routing rules only for webhooks that both:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Subscribe to the relevant trigger (for example, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_INBOUND"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_DELIVERY"]},"), and"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Have ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["routing_configuration"]}," defined."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For an incoming callback, the ruleset is selected by callback type:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Inbound message (MO)"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["routing_configuration.message_inbound_rules"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Delivery report (DR)"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["routing_configuration.message_delivery_rules"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"rules-and-filter-logic","__idx":3},"children":["Rules and filter logic"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The rule and filtering logic is described below:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Rule Precedence:"]}," Rules are evaluated in the order they are listed. ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Once a rule matches, evaluation stops (first matched rule wins)"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["AND/OR Semantics:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Inbound Rules:"]}," Filters within a rule (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["keyword_filter"]}," AND ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," AND ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel_filter"]},") use ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["AND"]}," logic. All specified filters must match."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Inbound Sender ID Filters:"]}," If multiple IDs are specified in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]},", it uses ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["OR"]}," logic."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Delivery Rules:"]}," Both ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," AND ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel_status_filters"]}," must match."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Delivery Channel/Status Filters:"]}," Any one entry in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel_status_filters"]}," list can match (",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["OR"]}," logic). Within an entry, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel"]}," AND one of the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["statuses"]}," must match (",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["AND"]}," logic)."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Fallback:"]}," If no rules match, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fallback_behavior"]}," determines the outcome: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FALLBACK_TO_DEFAULT"]}," (send to webhook target) or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DISCARD"]}," (drop callback)."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Secrets and HMAC signing"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If a route rule defines a non-blank ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["secret"]},", that secret is used to sign the outbound callback. Otherwise, the webhook's own ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["secret"]}," is used if present. If both the rule-level and webhook-level secrets are empty, callbacks are sent unsigned."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Route-specific secrets take precedence over webhook-level secrets. The receiving endpoint must use the rule-specific secret when validating signatures; using the default webhook secret will fail verification when a route secret exists."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more information on signature verification, see the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/conversation/callbacks#hmac"},"children":["HMAC verification guide"]},". Routed webhook endpoints must verify signatures to ensure the authenticity of the callbacks."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"configuration-reference","__idx":4},"children":["Configuration Reference"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["routing_configuration"]}," contains two optional rule groups:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message_inbound_rules"]}," — Rules for inbound messages (MO)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message_delivery_rules"]}," — Rules for delivery reports (DR)"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"common-fields","__idx":5},"children":["Common Fields"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Below are the fields common to both ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message_inbound_rules"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message_delivery_rules"]},":"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["rules"]}," — ordered list of routing rules. Each rule has:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]}," (required): A descriptive name for the rule."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["target_url"]}," (required): Where to send matching callbacks. We recommend using HTTPS for all webhook routing targets as callback payloads may contain sensitive message data and should be protected in transit."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["match_condition"]}," (required): Fields that must match."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["secret"]}," (optional): Per-rule HMAC secret."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fallback_behavior"]}," — What to do when no rule matches:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FALLBACK_TO_DEFAULT"]}," (default) → Send to webhook ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["target"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DISCARD"]}," → Drop the callback (no outbound call)."]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"inbound-messages-mo--message_inbound_rules","__idx":6},"children":["Inbound Messages (MO) — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message_inbound_rules"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Match condition fields (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["InboundMatchCondition"]},"):"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["keyword_filter"]}," (optional): Case-insensitive match on the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["first word"]}," of extracted message text. Blank/empty means \"match any text\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel_filter"]}," (optional): Restrict to a specific channel; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CHANNEL_UNSPECIFIED"]}," means \"any channel\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," (optional, repeated): OR across entries. Empty means \"any sender\". Note that during the open beta, this only applies to the SMS and MMS channels."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Keyword filtering vs. Consent management"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Keyword filtering in webhook routing is for directing callbacks to specific endpoints and should not be confused with ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Consent management"]},". Consent management is a separate feature for managing user opt-ins and opt-outs. For more details, see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/conversation/consent-management"},"children":["Consent management"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"supported-payloads-for-keyword-matching","__idx":7},"children":["Supported Payloads for Keyword Matching"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Keyword matching is performed by extracting text from the following ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ContactMessage"]}," payload fields:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["text_message.text"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["media_card_message.caption"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fallback_message.raw_message"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["choice_response_message.postback_data"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["product_response_message.text"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["location_message.title"]}," (falls back to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["label"]}," if title is blank)"]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Keyword Match Limitation"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["keyword_filter"]}," only matches the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["first word"]}," of the extracted text. For example, \"Help\" will match, but \"Please help\" will not."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"delivery-reports-dr--message_delivery_rules","__idx":8},"children":["Delivery Reports (DR) — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message_delivery_rules"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Match condition fields (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DeliveryMatchCondition"]},"):"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," (optional, repeated): OR across entries. Empty means \"any sender\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel_status_filters"]}," (optional, repeated): OR across entries. Each entry (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["ChannelStatusFilter"]},") uses:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel"]}," (optional): specific channel; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CHANNEL_UNSPECIFIED"]}," means \"any channel\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["statuses"]}," (optional, repeated): empty means \"any status\"."]}]}]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info","name":"Sender IDs Support"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["During the open beta, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," only supports the SMS and MMS channels. For all other channels, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id"]}," value is empty in callbacks, so rules using this filter will not match for those channels."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"limits-and-validation","__idx":9},"children":["Limits and Validation"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Below are the limitations and validation constraints enforced by the webhook routing functionality:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Max Rules:"]}," Up to 10 rules per ruleset."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Mandatory Fields:"]}," Every rule must have a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["target_url"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["match_condition"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Match Condition:"]}," Must contain at least one non-empty filter."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Lengths:"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["secret"]}," max 1024 chars, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["target_url"]}," max 742 chars."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"examples","__idx":10},"children":["Examples"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The sections below provide copy-and-paste-ready YAML and JSON snippets illustrating common routing patterns."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"single-filters","__idx":11},"children":["Single filters"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The sub-sections below provide simple single-filter example snippets."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"route-all-mo-callbacks","__idx":12},"children":["Route All MO Callbacks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Matches any incoming callback of the respective type. Since the API requires at least one non-empty filter, we use a \"match-all\" value like ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CHANNEL_UNSPECIFIED"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: ROUTE_ALL_MO\n        target_url: https://example.com/mo/all\n        match_condition:\n          channel_filter: CHANNEL_UNSPECIFIED\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," Any inbound message from any channel (WhatsApp, SMS, RCS, etc.)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," Delivery reports (because this is in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message_inbound_rules"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Directs all incoming traffic of a specific type to a dedicated processing service."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"route-sms-messages-only","__idx":13},"children":["Route SMS Messages Only"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Filters callbacks by a specific channel."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: SMS_ONLY\n        target_url: https://example.com/mo/sms\n        match_condition:\n          channel_filter: SMS\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," Any inbound message where the channel is SMS."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," Messages from WhatsApp, Viber, RCS, or any other channel."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Separating logic for legacy channels like SMS from modern IP-based channels."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"match-mo-by-keyword-only","__idx":14},"children":["Match MO by Keyword only"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Routes messages based on the first word of the message text."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: KEYWORD_HELP\n        target_url: https://example.com/mo/help\n        match_condition:\n          keyword_filter: \"help\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," Messages like \"Help\", \"HELP me\", or \"help! please\" (case-insensitive)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," \"Please help\" (the keyword must be the first word), or \"helper\" (exact match on the first word is required)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Directing support-related keywords to a helpdesk system."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"match-dr-by-senderid-only","__idx":15},"children":["Match DR by senderId only"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Filters by the originator identity. This is currently supported for SMS and MMS only."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_delivery_rules:\n    rules:\n      - name: SENDER_SINCH_SD\n        target_url: https://example.com/dr/sinch-sd\n        match_condition:\n          sender_id_filters: [\"SinchSD\"]\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," Any delivery report for messages sent with the \"SinchSD\" sender ID."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," Delivery reports for any other sender ID."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Tracking delivery performance for a specific brand or campaign identified by a unique sender ID."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"combining-multiple-filters","__idx":16},"children":["Combining multiple filters"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The sub-sections below provide more complex rulesets that feature multiple filters."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"match-mo-by-channel--sender-id","__idx":17},"children":["Match MO by Channel + Sender ID"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Combines a channel filter with specific originator identities."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: SMS_SENDER_12345\n        target_url: https://example.com/mo/sms-12345\n        match_condition:\n          channel_filter: SMS\n          sender_id_filters: [\"12345\"]\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," Inbound SMS messages received on short code \"12345\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," Inbound SMS messages to other numbers, or MMS messages to \"12345\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Isolating traffic for a specific short code or long code within your SMS application."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"match-mo-by-channel--keyword","__idx":18},"children":["Match MO by Channel + Keyword"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Routes messages based on both the arrival channel and the starting word."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: WA_START\n        target_url: https://example.com/mo/wa-onboarding\n        match_condition:\n          channel_filter: WHATSAPP\n          keyword_filter: \"start\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," WhatsApp messages that start with the word \"start\" (e.g., \"Start my trial\", \"START\")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," SMS messages starting with \"start\", or WhatsApp messages starting with \"hello\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Triggering different onboarding flows based on the channel the user chose to engage on."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"match-mo-by-keyword--sender-id","__idx":19},"children":["Match MO by Keyword + Sender ID"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Filters by originator identity and a specific keyword."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: SMS_67890_STOP\n        target_url: https://example.com/mo/sms-stop\n        match_condition:\n          keyword_filter: \"stop\"\n          sender_id_filters: [\"67890\"]\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," SMS messages starting with \"stop\" sent to sender ID \"67890\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," Messages with \"stop\" sent to other numbers, or \"JOIN\" sent to \"67890\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Managing opt-outs for specific marketing campaigns where each campaign uses a distinct short code."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"match-mo-using-all-available-filters","__idx":20},"children":["Match MO using all available filters"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Demonstrates the most granular MO routing possible."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: SMS_SENDER_HELP\n        target_url: https://example.com/mo/sms-help-special\n        match_condition:\n          channel_filter: SMS\n          sender_id_filters: [\"12345\"]\n          keyword_filter: \"help\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," Only SMS messages received on \"12345\" that start with the word \"help\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," MMS messages to \"12345\" with \"help\", or SMS messages to \"12345\" with \"support\"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Precise handling of specific customer interactions on a shared or multi-purpose sender identity."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"match-mo-using-channel_unspecified-with-sender-id-filter","__idx":21},"children":["Match MO using CHANNEL_UNSPECIFIED with Sender ID filter"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Using ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CHANNEL_UNSPECIFIED"]}," while filtering by sender ID allows matching across any channel that supports sender identities."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: SENDER_123_ANY_CHANNEL\n        target_url: https://example.com/mo/sender-123\n        match_condition:\n          channel_filter: CHANNEL_UNSPECIFIED\n          sender_id_filters: [\"123\"]\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," Inbound messages from sender \"123\" on any supported channel (currently SMS/MMS)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," Messages from other sender IDs, or messages on channels that do not provide a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id"]}," (like WhatsApp)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Simplified routing for a brand identity that might be reachable via multiple traditional messaging protocols."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"route-dr-by-channel-and-delivery-status","__idx":22},"children":["Route DR by Channel and Delivery Status"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Using OR logic for multiple channel/status combinations in delivery reports."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_delivery_rules:\n    rules:\n      - name: CRITICAL_DR\n        target_url: https://example.com/dr/critical\n        match_condition:\n          channel_status_filters:\n            - channel: WHATSAPP\n              statuses: [FAILED]\n            - channel: SMS\n              statuses: [DELIVERED, FAILED]\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," WhatsApp FAILED reports, OR SMS DELIVERED/FAILED reports."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," WhatsApp DELIVERED or READ reports."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Concentrating all terminal or critical delivery updates in one endpoint."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"rule-combination","__idx":23},"children":["Rule combination"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following examples demonstrate how to combine rules to handle common messaging scenarios."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"priority-routing-rule-precedence","__idx":24},"children":["Priority Routing (Rule Precedence)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This example shows how to prioritize specific traffic (e.g., from a VIP sender) while still having a general catch-all for other SMS traffic."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: VIP_PRIORITY\n        target_url: https://example.com/mo/priority\n        match_condition:\n          sender_id_filters: [\"VIP_SENDER\"]\n      - name: SMS_GENERAL\n        target_url: https://example.com/mo/sms\n        match_condition:\n          channel_filter: SMS\n    fallback_behavior: FALLBACK_TO_DEFAULT\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["A message from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VIP_SENDER"]}," via SMS matches the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["first"]}," rule and goes to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/priority"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["A message from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OTHER_SENDER"]}," (or any other sender that isn't ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VIP_SENDER"]},") via SMS fails the first rule, matches the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["second"]}," rule, and goes to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/sms"]},"."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," A message from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VIP_SENDER"]}," via WhatsApp would fail the first rule (because ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id"]}," is empty for WhatsApp) and fail the second rule (not SMS). It would then use ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fallback_behavior"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Implementing tiered service levels or special handling for high-value originators."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"handling-no-matches-fallback","__idx":25},"children":["Handling no matches (fallback)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When no rules in a ruleset match a callback, the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fallback_behavior"]}," determines if the callback is sent to the default target or discarded."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_delivery_rules:\n    rules:\n      - name: FAILURES_ONLY\n        target_url: https://example.com/dr/errors\n        match_condition:\n          channel_status_filters:\n            - channel: CHANNEL_UNSPECIFIED\n              statuses: [FAILED]\n    fallback_behavior: DISCARD\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Matches:"]}," A delivery report with status ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["FAILED"]}," matches the rule and is sent to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/errors"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Does not match:"]}," A delivery report with status ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DELIVERED"]}," does not match the rule. Because ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["fallback_behavior"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["DISCARD"]},", the callback is dropped and ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["not"]}," sent anywhere."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Why it is useful:"]}," Reducing noise on your main callback endpoint by only receiving the specific events you care about (e.g., errors) and discarding everything else."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"practical-configuration-examples","__idx":26},"children":["Practical configuration examples"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following sections provide examples highlighting contextualized use cases."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"use-case-separate-marketing-and-transactional-traffic","__idx":27},"children":["Use Case: Separate marketing and transactional traffic"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A company uses the same Conversation API App for both marketing (SMS via Short Code) and transactional (WhatsApp) messages. They want to process responses in different backend systems."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"app_id: \"{{APP_ID}}\"\ntarget: \"https://example.com/default\"\ntriggers: [\"MESSAGE_INBOUND\", \"MESSAGE_DELIVERY\"]\nrouting_configuration:\n  message_inbound_rules:\n    rules:\n      - name: MARKETING_SMS_MO\n        target_url: https://marketing-system.example.com/callbacks\n        match_condition:\n          channel_filter: SMS\n          sender_id_filters: [\"67890\"]\n      - name: TRANSACTIONAL_WA_MO\n        target_url: https://transactional-system.example.com/wa-inbound\n        match_condition:\n          channel_filter: WHATSAPP\n  message_delivery_rules:\n    rules:\n      - name: WA_READ_RECEIPTS\n        target_url: https://transactional-system.example.com/wa-dr\n        match_condition:\n          channel_status_filters:\n            - channel: WHATSAPP\n              statuses: [READ]\n    fallback_behavior: DISCARD\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"use-case-secure-routing-with-per-rule-secrets","__idx":28},"children":["Use Case: Secure Routing with Per-Rule Secrets"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You might want to route sensitive callbacks to a highly secure endpoint that uses a different HMAC secret for validation."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"warning","name":"Edit code snippet"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Do not use this code snippet without modifying the example ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["secret"]}," value."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: SECURE_AUTH_FLOW\n        target_url: https://secure.example.com/auth-otp\n        secret: \"highly-secret-hmac-key-123\"\n        match_condition:\n          keyword_filter: \"code\"\n          channel_filter: SMS\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"troubleshooting","__idx":29},"children":["Troubleshooting"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If you encounter any obstacles, review the following troubleshooting tips:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"nothing-is-being-routed","__idx":30},"children":["Nothing is being routed"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If no callbacks are being routed:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure that the corresponding webhook is subscribed to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_INBOUND"]}," and/or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_DELIVERY"]}," triggers."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Check if ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["routing_configuration"]}," is correctly defined in the webhook object."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Ensure your rules are defined correctly."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Consider the example and corresponding scenarios below:"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: SMS_HELP\n        target_url: https://example.com/mo/help\n        match_condition:\n          channel_filter: SMS\n          keyword_filter: \"help\"\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Callback Scenario 1:"]}," The webhook(s) you are trying to route are not subscribed to either the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_INBOUND"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_DELIVERY"]}," triggers.",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Result:"]}," No match. The webhook(s) ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["must"]}," be subscribed to either the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_INBOUND"]}," and/or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["MESSAGE_DELIVERY"]}," triggers."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Callback Scenario 2:"]}," A WhatsApp message with text \"help\".",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Result:"]}," No match. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["channel_filter"]}," is SMS."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Callback Scenario 3:"]}," An SMS message with text \"please help\".",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Result:"]}," No match. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["keyword_filter"]}," matches only the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["first word"]},"."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Callback Scenario 4:"]}," An SMS message with text \"help me\".",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Result:"]}," Match. The first word of the SMS message is \"help\"."]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Reviewing your webhook and rule configuration helps in debugging why messages are falling back to the default target or being discarded."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"a-specific-rule-isnt-matching","__idx":31},"children":["A specific rule isn't matching"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If a specific rule isn't matching:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify rule order. A broad rule earlier in the list might be \"stealing\" the callbacks."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Remember ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["keyword_filter"]}," matches only the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["first word"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["During open beta, ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["sender_id_filters"]}," only works for SMS and MMS."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following example shows how the \"first match wins\" logic works:"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["YAML"]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"routing_configuration:\n  message_inbound_rules:\n    rules:\n      - name: PRIORITY_SENDER\n        target_url: https://example.com/mo/priority\n        match_condition:\n          sender_id_filters: [\"VIP_SENDER\"]\n      - name: GENERAL_SMS\n        target_url: https://example.com/mo/general-sms\n        match_condition:\n          channel_filter: SMS\n    fallback_behavior: FALLBACK_TO_DEFAULT\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Evaluation:"]}]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If a message comes from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["VIP_SENDER"]}," via SMS, it matches the first rule and goes to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/priority"]},". It ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["never"]}," reaches the second rule."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If a message comes from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OTHER_SENDER"]}," via SMS, it fails the first rule, matches the second, and goes to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/general-sms"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["If a message comes from ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["OTHER_SENDER"]}," via WhatsApp, it fails both rules and falls back to the default webhook target."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Rule order is useful when implementing \"special handling\" for certain senders or conditions while having a catch-all for the rest of the channel traffic. Ensure that your ordering is well-defined so that all webhooks are routed correctly."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"payload-not-matching-keyword","__idx":32},"children":["Payload not matching keyword"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Keyword matching is only performed on specific fields (see ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"#supported-payloads-for-keyword-matching"},"children":["the list of supported payloads"]},"). If your message is an Interactive Message or a Contact/Location message without a title, it might not match as expected."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"see-also","__idx":33},"children":["See also"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Callbacks overview and management: ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/conversation/callbacks"},"children":["Conversation API callbacks"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Opt-in/opt-out keyword analysis: ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/conversation/consent-management"},"children":["Consent management"]}]}]}]},"headings":[{"value":"Webhook routing","id":"webhook-routing","depth":1},{"value":"Important information","id":"important-information","depth":2},{"value":"How Rule Matching Works","id":"how-rule-matching-works","depth":2},{"value":"Rules and filter logic","id":"rules-and-filter-logic","depth":3},{"value":"Configuration Reference","id":"configuration-reference","depth":2},{"value":"Common Fields","id":"common-fields","depth":3},{"value":"Inbound Messages (MO) — message_inbound_rules","id":"inbound-messages-mo--message_inbound_rules","depth":3},{"value":"Supported Payloads for Keyword Matching","id":"supported-payloads-for-keyword-matching","depth":4},{"value":"Delivery Reports (DR) — message_delivery_rules","id":"delivery-reports-dr--message_delivery_rules","depth":3},{"value":"Limits and Validation","id":"limits-and-validation","depth":3},{"value":"Examples","id":"examples","depth":2},{"value":"Single filters","id":"single-filters","depth":3},{"value":"Route All MO Callbacks","id":"route-all-mo-callbacks","depth":4},{"value":"Route SMS Messages Only","id":"route-sms-messages-only","depth":4},{"value":"Match MO by Keyword only","id":"match-mo-by-keyword-only","depth":4},{"value":"Match DR by senderId only","id":"match-dr-by-senderid-only","depth":4},{"value":"Combining multiple filters","id":"combining-multiple-filters","depth":3},{"value":"Match MO by Channel + Sender ID","id":"match-mo-by-channel--sender-id","depth":4},{"value":"Match MO by Channel + Keyword","id":"match-mo-by-channel--keyword","depth":4},{"value":"Match MO by Keyword + Sender ID","id":"match-mo-by-keyword--sender-id","depth":4},{"value":"Match MO using all available filters","id":"match-mo-using-all-available-filters","depth":4},{"value":"Match MO using CHANNEL_UNSPECIFIED with Sender ID filter","id":"match-mo-using-channel_unspecified-with-sender-id-filter","depth":4},{"value":"Route DR by Channel and Delivery Status","id":"route-dr-by-channel-and-delivery-status","depth":4},{"value":"Rule combination","id":"rule-combination","depth":3},{"value":"Priority Routing (Rule Precedence)","id":"priority-routing-rule-precedence","depth":4},{"value":"Handling no matches (fallback)","id":"handling-no-matches-fallback","depth":4},{"value":"Practical configuration examples","id":"practical-configuration-examples","depth":2},{"value":"Use Case: Separate marketing and transactional traffic","id":"use-case-separate-marketing-and-transactional-traffic","depth":3},{"value":"Use Case: Secure Routing with Per-Rule Secrets","id":"use-case-secure-routing-with-per-rule-secrets","depth":3},{"value":"Troubleshooting","id":"troubleshooting","depth":2},{"value":"Nothing is being routed","id":"nothing-is-being-routed","depth":3},{"value":"A specific rule isn't matching","id":"a-specific-rule-isnt-matching","depth":3},{"value":"Payload not matching keyword","id":"payload-not-matching-keyword","depth":3},{"value":"See also","id":"see-also","depth":2}],"frontmatter":{"title":"Webhook routing | Conversation API | Sinch","description":"Configure webhook routing rules to send different callbacks to different endpoints based on message content, sender, channel, or delivery status.","redirectFrom":["/docs/conversation/webhook-routing"],"seo":{"title":"Webhook routing"}},"lastModified":"2026-08-20T05:53:49.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/docs/conversation/callbacks/webhook-routing","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}