Skip to main content

Introduction

Connected Sources is MoEngage’s flexible webhook integration framework that allows you to stream real-time data from any external platform directly into MoEngage. Integrate CRMs, e-commerce platforms, marketing tools, or custom applications with a standardized approach.

How It Works

Connect any external system using three simple steps:

Webhook POST

Your system sends JSON payload to MoEngage endpoint

Transform

Mapper extracts and validates data

Import

Data flows into events & profiles

Key Capabilities

  • Real-Time Events: Stream user actions as they happen
  • Profile Sync: Update user attributes automatically
  • Bulk Processing: Handle batches in a single call
  • Flexible Mapping: Transform complex JSON structures
  • Date Merging: Combine separate date/time fields
  • Dynamic Attrs: Auto-import custom fields

Use Cases

  • 📝 Lead Capture: Stream form submissions from Unbounce, Typeform, and HubSpot for instant follow-ups
  • 💳 Payment Events: Track subscriptions from Stripe, Chargebee (created, failed, expiring)
  • 🎫 Support Tickets: Monitor Zendesk/Intercom interactions for satisfaction tracking
  • 🛒 E-commerce: Capture orders, carts, and views from custom platforms
  • 🛠️ Custom Apps: Send events from proprietary systems without native SDKs

🚀 Build Your Integration

Follow these five steps to go from sample payload to live data flowing into MoEngage.
  1. Prepare: Prerequisites & Payloads
  2. Create: Build Your Mapper
  3. Submit: Send to MoEngage
  4. Configure: Add Webhook URL
  5. Test: Verify Data Flow

Prepare: Prerequisites & Sample Payloads

Before building your mapper, make sure you have everything ready.
You will need:
  • Webhook capability in your system (HTTP POST)
  • Authentication support (Basic Auth or custom headers)
  • Valid JSON webhook payloads
  • 2-3 sample payloads from your system
  • MoEngage credentials (Workspace ID, Data API Key from Settings → APIs)
⚡ Rate LimitsRecommended maximum: 200 requests/secondFor higher throughput, contact your Solutions Engineering team with: expected volume, use case description, peak/average patterns, and data center location.
💡 Validate early: Paste your sample payloads into JSONLint to confirm they are valid JSON before proceeding.

Create: Build Your Mapper Configuration

The mapper is a JSON configuration that tells MoEngage how to transform your incoming webhook data into events or user profiles. This is the core of your integration.

📋 Choose Your Mapping Type

Two sync types available:
  • mapping_type: "events" - Track events AND create/update user profiles
  • mapping_type: "users" - Create/Update user profiles ONLY (no events)
{
  "partner_name": "integration_name",
  "mapping_type": "events",
  "mappings": {
    "customer_id": "$.user_id",
    "event_name": "$.event_type",
    "user_time": "$.timestamp",
    "platform": "web",
    "app_version": "1.0.0",
    "attr": {
      "custom_field": "$.field_name"
    },
    "user_attributes": {
      "u_em": "$.email"
    }
  },
  "batching": false,
  "payload_validations": {}
}

Field Requirements by Mapping Type

FieldFor “events”For “users”
customer_idRequired - Unique user identifierRequired - Unique user identifier
event_nameRequired - Event nameNot used
user_timeRequired - Event timestampNot used
platformRequired - “web”, “android”, “ios”, “api”Not used
app_versionRequired - Static version stringNot used
user_attributesOptional - Update user profileOptional - Update user profile
attrOptional - Event attributesNot used

📍 JSONPath Quick Reference

Use JSONPath expressions to map fields from your payload to MoEngage fields. Here’s how to read them:
PayloadJSONPathResult
{"email": "[email protected]"}$.email[email protected]
{"user":{"email": "[email protected]"}}$.user.email[email protected]
{"items": [{"name": "A"}]}$.items[0].nameA
{"events": [{"id": 1}, {"id": 2}]}$.events[*].idIterates all (batching)

📌 Complete Field Reference

FieldTypeDescription
partner_nameStringUnique lowercase identifier (e.g., “typeform”)
mapping_typeString”events” OR “users”
customer_idJSONPath🔑 Path to unique user ID (email, phone, custom ID) - links events to profiles
event_nameJSONPath/StringEvent name path or static string. Required for “events” type only
user_timeJSONPath/“#MERGE”Timestamp path (epoch ms preferred) or “#MERGE” for split date/time. Required for “events” only
platformString”web”, “android”, “ios”, or “api”. Required for “events” type only
app_versionStringVersion string (default: “1.0.0”). Required for “events” type only
user_attributesObjectUser profile attributes: u_em (email), u_fn (first name), u_ln (last name), u_mb (mobile)
attrObjectEvent attributes (key-value pairs). Optional for “events” only
batchingBooleantrue for array payloads, false for single events

📋 Starter Template

Copy this template and replace the JSONPath expressions with paths from your actual payload:
{
  "partner_name": "your_integration_name",
  "mapping_type": "events",
  "mappings": {
    "customer_id": "$.user_id",
    "event_name": "$.event_type",
    "user_time": "$.timestamp",
    "platform": "web",
    "app_version": "1.0.0",
    "attr": {
      "custom_field": "$.field_name"
    },
    "user_attributes": {
      "u_em": "$.email",
      "u_fn": "$.first_name"
    }
  },
  "batching": false,
  "payload_validations": {
    "$.event_type": "string"
  }
}

💡 See It in Action: Real-World Examples

Click each example to see the payload and its corresponding mapper configuration side by side.
Scenario: Lead form sends contact info on submission
{
  "email": "[email protected]",
  "first_name": "John",
  "last_name": "Doe",
  "phone": "+14155551234",
  "form_name": "Contact Us",
  "submitted_at": 1704067200000,
  "utm_source": "google"
}
Key Points: Email as unique ID • Static event name • Epoch timestamp • Updates user profile
Scenario: System sends multiple orders in single webhook
{
  "orders": [
    {
      "order_id": "ORD-001",
      "customer_email": "[email protected]",
      "order_total": 99.99,
      "currency": "USD",
      "order_date": 1704067200000
    },
    {
      "order_id": "ORD-002",
      "customer_email": "[email protected]",
      "order_total": 149.50,
      "currency": "USD",
      "order_date": 1704070800000
    }
  ]
}
✅ Key Points: batching=true for arrays • [*] wildcard iterates • Creates separate event per order
Scenario: Separate date and time fields need combining
{
  "user_email": "[email protected]",
  "event_type": "Webinar Registration",
  "webinar_name": "Product Demo",
  "date_registered": "2024-10-25",
  "time_registered": "14:30:00"
}
✅ Key Points: user_time="#MERGE" signals merging • #MERGE section defines fields • formats specifies pattern
Scenario: CRM sends profile updates without event tracking
{
  "email": "[email protected]",
  "first_name": "Sarah",
  "last_name": "Williams",
  "phone": "+14155559999",
  "subscription_tier": "Premium",
  "account_status": "Active"
}
✅ Key Points: mapping_type="users" • No event created • No event_name/user_time/platform needed
Scenario: Track pre-login behavior, merge after identification
{
  "session_id": "anon_abc123xyz",
  "event": "Product Viewed",
  "product_id": "PROD-001",
  "product_name": "Wireless Headphones",
  "timestamp": 1704067200000
}
🔄 Merging Flow: After login, send event with both customer_id and anon_id. MoEngage auto-merges anonymous history to identified profile.
Pro Tip: Using create_allThe create_all attribute allows you to iterate through all keys within a specified object from your payload. This is highly recommended when dealing with objects whose keys are dynamic, frequently changing, or constantly expanding. Instead of mapping every new field manually, create_all grabs them all at once!
Scenario: Syncing user profiles from a CRM where custom fields are constantly added to a user_attributes object.
{
  "customer_id": "CUST-8890",
  "first_name": "Alex",
  "last_name": "Taylor",
  "email": "[email protected]",
  "phone": "+1234567890",
  "user_attributes": {
    "modified_time": "25-10-2024 14:30:00",
    "lead_score": 85,
    "industry": "Software",
    "lifecycle_stage": "MQL"
  }
}
✅ Key Points: Standard fields are mapped directly (e.g., u_fn) • create_all automatically pulls in lead_score, industry, and lifecycle_stage without explicit mapping.
Scenario: A CRM sends an event where both the user properties and the event details contain dynamic, unpredictable keys.
{
  "customer_id": "CUST-8890",
  "event_name": "Deal Advanced",
  "user_attributes": {
    "account_manager": "Sarah Jenkins",
    "region": "EMEA"
  },
  "event_attributes": {
    "modified_time": "26-10-2024 09:15:00",
    "deal_value": 50000,
    "previous_stage": "Demo",
    "new_stage": "Negotiation"
  }
}
✅ Key Points: create_all works inside both user_attributes and event attr objects simultaneously • Perfect for heavily customized CRM payloads.
Timestamps: Use epoch milliseconds (integer) when possible — no format specification needed! If your payload uses string timestamps, specify the format in the formats section.
Format StringExample
yyyy-MM-dd2024-10-25
yyyy/MM/dd2024/10/25
dd/MM/yyyy25/10/2024
dd-MM-yyyy25-10-2024
yyyy-MM-dd HH:mm:ss2024-10-25 14:30:00
dd-MM-yyyy HH:mm:ss25-10-2024 14:30:00
dd/MM/yyyy HH:mm:ss25/10/2024 14:30:00
yyyy/MM/dd HH:mm:ss2024/10/25 14:30:00
yyyy-MM-dd'T'HH:mm:ssZ2024-10-25T14:30:00+0530
yyyy-MM-dd HH:mm:ss.SSSSSS2024-10-25 14:30:00.123456
yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'2024-10-25T14:30:00.123456Z
Also supported: dd/MM/yyyy and dd-MM-yyyy variants with T, Z, and microsecond suffixes.
🎨 Prefer a visual tool? Use the Visual Mapper Generator to build your JSON configuration with a guided interface.

Submit: Send Your Mapper to MoEngage

Once your mapper JSON is ready, email [email protected] with:
  • Completed mapper JSON (attached)
  • Sample webhook payload(s)
  • Integration details: partner name, Workspace ID, Data Center, use case

Configure: Add the Webhook URL

MoEngage will provide you with a unique webhook URL. Add it to your source system with Basic Auth credentials (Workspace ID as username, Data API Key as password). For events: https://api-0X.moengage.com/v1/partner/<partner_name>/events/?configName=<config_name> For users: https://api-0X.moengage.com/v1/partner/<partner_name>/users/?configName=<config_name>

Test: Verify Your Data Flow

Use Postman to send your sample payload to the webhook URL. Verify a 200 OK response, save the request_id, then check MoEngage Dashboard → Analytics → Events (allow 1-2 minutes for processing).

✅ Understanding API Responses

Different response codes indicate different outcomes:
Status: Your request was successfully received and queued for processing.
{
  "request_id": "uhdvtjxa",
  "name": "integration_name",
  "description": "Successfully submitted for processing"
}
Next Steps: Save the request_id. Your data should appear in MoEngage within 1-2 minutes.
Cause: A field defined as mandatory in your mapper is missing from the payload.
{
  "error": {
    "code": "e_9004",
    "message": "Required field 'Request.data.actions.action' is missing in the payload",
    "target": "payload_validation",
    "details": [{ "code": "e_9004", "target": "payload_validation", "message": "Required field 'Request.data.actions.action' is missing in the payload" }]
  }
}
🔧 How to Fix: Verify JSONPath expressions match your payload structure and ensure all required fields are present.
Cause: Your JSON payload is malformed or doesn’t match the expected structure.
{
  "error": {
    "code": "e_9004",
    "message": "The provided payload is invalid",
    "target": "payload_validation",
    "details": [{ "code": "e_9004", "target": "payload_validation", "message": "The provided payload is invalid" }]
  }
}
🔧 How to Fix: Validate JSON using JSONLint and check for missing braces, brackets, or commas.
Cause: Invalid Basic Auth credentials or missing Authorization header.
{
  "status": "fail",
  "error": { "message": "Invalid authorization format. Expected Basic authentication", "type": "Authentication required", "request_id": "70e2fd" }
}
🔧 How to Fix: In Postman, select Basic Auth and enter your Workspace ID as username and Data API Key as password.
If you encounter an error response not covered above, contact MoEngage Solutions Engineering with:
  • Complete error response (JSON)
  • Your mapper configuration (JSON)
  • Sample payload you were testing (JSON)
  • Expected behavior vs actual behavior

🔧 Common Issues

Events not appearing Verify 200 OK response • Check customer_id path • Confirm timestamp format • Wait 2-3 min • Contact MoEngage with request_id 🔀 Wrong attributes Test JSONPath at jsonpath.com • Verify payload structure • Check field name typos (case-sensitive) Timestamp errors Match format string exactly • Use epoch ms when possible • Include timezone for ISO format 📦 Bulk not processing Set batching=true • Use [*] in all paths • Check array location in payload create_all issues Verify path points to object • Ensure key-value pairs • Check nesting (works one level deep)

🛠️ Helpful Tools

✅ JSONLint Validate syntax Visit jsonlint.com → 🗺️ JSONPath Test expressions Visit jsonpath.com → 🪝 Webhook.site Inspect payloads Visit webhook.site → 📮 Postman Test API calls Visit postman.com → ⏰ Epoch Converter Date conversions Visit epochconverter.com → 🎨 Mapper Generator Visual config tool Open Tool →

❓ FAQ

Yes. Include both user_attributes and attr in your mapper. Profile updates and event creation happen simultaneously.
A new profile is created automatically. If customer_id already exists, the event is associated with the existing profile.
Yes. Contact MoEngage with the updated JSON. They’ll deploy a new version with a new config_name. Your old URL continues working with the previous mapper.
Maximum 1MB recommended. For bulk requests, batch 100-500 events per call for optimal performance.
Use JSONPath notation: $.orders[0].items[0].name for specific items or $.orders[*].items[*].name for batching. Complex nesting may require flattening first.

🆘 Support

Need Help?
  • 💬 General Questions: Contact your MoEngage Customer Success Manager
  • 🔧 Technical Support: Email [email protected] with:
    • Mapper JSON (attached)
    • Sample webhook payload
    • Request ID from response
    • Issue description
  • 🎨 Mapper Help: Share your payload & requirements - our team will assist