Skip to main content
Compliance-minded workflowsNo long-term contractsHuman support when you need it

Incoming Message Processing Guide

Understand how incoming messages are processed and routed.

Overview

When a new SMS message arrives at your campaign phone number, the system processes it through a series of steps to determine the appropriate response. This guide explains each step of the process and how the system differentiates between EchoWord messages and standard messages.


1. Message Receipt & Initial Processing

When the sending partner receives an incoming message, the webhook is triggered with the following data:

FieldDescription
FromSender's phone number
ToRecipient phone number (your campaign number)
BodyMessage content
MessageSidUnique message identifier
NumMediaNumber of media attachments
NumSegmentsNumber of SMS segments

Step 1.1: The system parses the raw webhook data and extracts all message parameters.

Step 1.2: The message body is normalized to uppercase and trimmed for consistent matching.

Step 1.3: The system validates that both From and To phone numbers are in E.164 format (e.g., +12345678901).


2. Global Phone Number Detection

Step 2.1: The system checks if the recipient phone number (To field) matches the configured global phone number.

Step 2.2: If it's a global phone number:

  • Validates both From and To phone numbers are in E.164 format
  • If validation fails, logs an error and skips global processing
  • If validation passes, proceeds to Global EchoWord Processing (see Section 3)

Step 2.3: If it's not a global phone number, proceeds to Campaign Lookup (see Section 4).


3. Global EchoWord Processing

If the message is sent to a global phone number:

Step 3.1: The system fetches all global EchoWords (EchoWords with type: 'global').

Step 3.2: It searches for a matching global EchoWord where the code matches the message body.

Step 3.3: If a match is found:

  • Retrieves the campaign using the global EchoWord's campaignId
  • Upserts the contact for the sender:
    • Uses upsertSingleContact to create or update the contact
    • Requires: phone number, brandId, and createdBy (from campaign)
    • If createdBy is missing, logs an error and skips contact creation
    • Logs success or failure of the upsert operation
  • Saves an opt-in record for the sender
  • Sends the campaign's optinMessage as the response (or default message if not configured)
  • Processing ends (no further routing)

Step 3.4: If no match is found:

  • Sends default response: "Message received. Thank you."
  • Processing ends

Note: Global phone numbers skip the normal campaign lookup process and handle EchoWords directly.


4. Campaign Lookup

For non-global phone numbers:

Step 4.1: The system looks up the campaign associated with the recipient phone number (To field).

Step 4.2: If a campaign is found, the system retrieves:

  • Campaign configuration
  • Brand information
  • Phone number details
  • Campaign creator (createdBy)

Step 4.3: If no campaign is found:

  • System proceeds to error handling
  • Sends error message: "This number is not configured for messaging. Please contact support."

5. Reply Record Creation

Step 5.1: The incoming message is saved to the replies table with:

  • Message content
  • Sender and recipient phone numbers
  • Timestamp
  • Campaign creator (if available)

Step 5.2: A unique reply ID is generated for tracking.


6. Message Routing Decision

The system now determines which processing path to take based on the message content:

Path A: Standard Keywords (START, STOP, HELP, YES)

Path B: EchoWord Match

Path C: Autoresponder Fallback (for non-keyword messages)


Path A: Standard Keyword Processing

If the message contains standard compliance keywords, the system processes them immediately:

START Keyword

Step A.1: System saves an opt-in record for the sender.

Step A.2: Sends the campaign's opt-in message (or default message if not configured).

Step A.3: No further processing occurs.

YES Keyword

Step A.1: System saves an opt-in record for the sender.

Step A.2: Sends a confirmation message: "Thanks for confirming!"

Step A.3: No further processing occurs.

STOP Keyword

Step A.1: System saves an opt-out record for the sender.

Step A.2: Sends the campaign's opt-out message (or default message if not configured).

Step A.3: No further processing occurs.

HELP Keyword

Step A.1: Sends the campaign's help message (or default message if not configured).

Step A.2: No further processing occurs.


Path B: EchoWord Processing

If the message doesn't match standard keywords, the system checks for EchoWord matches:

Step B.1: Fetch Available EchoWords

The system retrieves:

  • Campaign EchoWords (campaign-specific, not global)

Step B.2: Fetch Campaign Phone Numbers

Step B.2.1: The system fetches all phone numbers for the campaign that are:

  • Not deleted (deletedAt IS NULL)
  • Not archived (archivedAt IS NULL)

Step B.2.2: Extracts phone number IDs into an array for validation.

Step B.3: EchoWord Matching Process

EchoWord Matching:

  • Checks if message body matches any EchoWord code
  • Phone number validation:
    • If EchoWord has a phoneNumberId, it must match the incoming phone number ID
    • If EchoWord has no phoneNumberId, the incoming phone number ID must be in the list of all campaign phone number IDs
  • First valid match wins

Note: EchoWords validate against all campaign phone numbers, not just the primary/default phone number.

Step B.4: Match Found - Process Actions

If a matching EchoWord is found:

Step B.4.1: Check if EchoWord is paused

  • If paused, skip all actions
  • If active, continue processing

Step B.4.2: Check expiration date/time

  • If expirationDate is set, compare with current time
  • If expirationTime is set, combine with expiration date
  • If expired, skip all actions
  • If not expired, continue processing

Step B.4.3: Get or Create Contact

  • Search for existing contact by phone number and brand
  • If not found, create new contact with:
    • Phone number
    • Brand ID
    • Campaign creator as createdBy (required)
  • Store contact ID for subsequent actions

Step B.4.4: Process Autoresponder Action

  • If actions.autoresponderId is configured:
    • Fetch autoresponder from database (validated against campaign ID)
    • Send autoresponder message to sender
    • Message is not saved to sent_messages (no associated text message)

Step B.4.5: Process Contact Group Actions

  • If actions.contactGroupIds is configured:
    • For each group ID:
      • Add contact to group (if not already in group)
      • Update contact's contact_group_ids array
    • Log each group addition

Step B.4.6: Default Opt-In Message

  • If no autoresponder is configured:
    • Send campaign's opt-in message (or default)
    • This serves as a fallback response

Step B.4.7: Save Opt-In Record

  • Create opt-in record for the sender
  • Link to the reply record
  • Associate with campaign

Step B.5: No Match Found

If no EchoWord matches:

  • System proceeds to Path C: Autoresponder Fallback

Path C: Autoresponder Fallback

For messages that don't match keywords or EchoWords:

Step C.1: Find Last Sent Message

Step C.1.1: Query sent_messages table for:

  • Last message sent to this phone number
  • From the same campaign
  • Status: sent or delivered
  • Direction: outbound or outbound-api
  • Ordered by most recent first

Step C.2: Check for Autoresponder

Step C.2.1: If a previous message is found:

  • Retrieve the text message details
  • Check if the text has an autoresponderId configured

Step C.2.2: If autoresponder is configured:

  • Fetch autoresponder message from database
  • Send autoresponder message to sender
  • Message is saved to sent_messages with the original text ID

Step C.2.3: If no autoresponder is configured:

  • No response is sent
  • Message is logged but not replied to

7. Response Generation

After processing, the system generates a LaML (Laravel Markup Language) response:

Step 7.1: All messages added during processing are compiled into the response.

Step 7.2: Response is sent back to the sending partner.

Step 7.3: The sending partner delivers the response to the sender.


8. Error Handling

At each step, errors are caught and logged:

Error Handling:

  • Errors in EchoWord processing fall back to default opt-in message
  • Errors in autoresponder processing are logged but don't block the webhook
  • Errors in contact group processing are logged per group
  • All errors include detailed context for debugging (error message, stack trace, relevant IDs)

Key Differences: EchoWord vs Non-EchoWord

AspectEchoWordNon-EchoWord Message
MatchingExact code match requiredNo code matching
Phone ValidationValidates against all campaign phone numbersNo phone validation
ActionsCan trigger autoresponder + contact groupsOnly autoresponder from last text
Contact CreationCreates contact if neededNo contact creation
Opt-InAlways saves opt-in recordNo opt-in record
ExpirationChecks expiration date/timeNo expiration check
Status CheckChecks if EchoWord is pausedNo status check

Processing Flow Diagram

Incoming Message
    ↓
Parse & Normalize
    ↓
Validate E.164 Format
    ↓
    ├─→ Global Phone Number?
    │   ├─→ Yes → Fetch Global EchoWords
    │   │   ├─→ Match Found?
    │   │   │   ├─→ Yes → Get Campaign → Upsert Contact → Save Opt-In → Send OptinMessage → End
    │   │   │   └─→ No → Send "Message received. Thank you." → End
    │   │   └─→ Invalid E.164 → Log Error → End
    │   │
    │   └─→ No → Lookup Campaign by Phone
    │       ├─→ Campaign Found?
    │       │   ├─→ Yes → Save Reply Record
    │       │   │   ├─→ Standard Keyword? → Process Keyword → End
    │       │   │   │
    │       │   │   ├─→ EchoWord Match?
    │       │   │   │   ├─→ Yes → Check Status & Expiration
    │       │   │   │   │   ├─→ Valid → Get/Create Contact
    │       │   │   │   │   │   ├─→ Process Autoresponder
    │       │   │   │   │   │   ├─→ Process Contact Groups
    │       │   │   │   │   │   ├─→ Save Opt-In → End
    │       │   │   │   │   └─→ Invalid → End
    │       │   │   │   │
    │       │   │   │   └─→ No → Find Last Sent Message
    │       │   │   │       ├─→ Has Autoresponder? → Send Autoresponder → End
    │       │   │   │       └─→ No Autoresponder → End (No Response)
    │       │   │   │
    │       │   └─→ No → Send Error Message → End

Summary

The incoming message processing system handles three main scenarios:

  1. Global EchoWords - Messages to global phone numbers that match global EchoWords upsert the contact, save an opt-in record, and respond with the campaign's optinMessage
  2. Standard Keywords (START, STOP, HELP, YES) - Immediate compliance responses
  3. EchoWord Matches - Automated actions with autoresponders and contact groups, validated against all campaign phone numbers
  4. Autoresponder Fallback - Replies to previous text messages with autoresponders

Key Features

  • E.164 Validation: All phone numbers are validated for E.164 format before processing
  • Phone Number Validation: EchoWords validate against all campaign phone numbers (not just primary)
  • Campaign-Specific Autoresponders: Autoresponders are now campaign-specific and validated against campaign ID
  • No Legacy EchoCodes: System only uses EchoWords (legacy EchoCodes removed)

Each path ensures proper compliance, contact management, and user experience while maintaining detailed logging for debugging and audit purposes.

Did you find this article helpful?

Start Sending Today

Launch fast with pay-as-you-go SMS and 250 free credits every month.

No contracts. Low monthly compliance subscription. Keep your costs predictable while you scale.

Claim Your Free Credits