Connected Sources

🔗 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 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, 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, 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
1

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 Limits

Recommended maximum: 200 requests/second

For 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.

2

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)
Events MapperUsers Mapper
{
  "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

Field For "events" For "users"
customer_id Required - Unique user identifier Required - Unique user identifier
event_name Required - Event name Not used
user_time Required - Event timestamp Not used
platform Required - "web", "android", "ios", "api" Not used
app_version Required - Static version string Not used
user_attributes Optional - Update user profile Optional - Update user profile
attr Optional - Event attributes Not used

📍 JSONPath Quick Reference

Use JSONPath expressions to map fields from your payload to MoEngage fields. Here's how to read them:

Payload JSONPath Result
{"email": "user@example.com"} $.email user@example.com
{"user":{"email": "test@ex.com"}} $.user.email test@ex.com
{"items": [{"name": "A"}]} $.items[0].name A
{"events": [{"id": 1}, {"id": 2}]} $.events[*].id Iterates all (batching)

📌 Complete Field Reference

Field Type Description
partner_name String Unique lowercase identifier (e.g., "typeform")
mapping_type String "events" OR "users"
customer_id JSONPath 🔑 Path to unique user ID (email, phone, custom ID) - links events to profiles
event_name JSONPath/String Event name path or static string. Required for "events" type only
user_time JSONPath/"#MERGE" Timestamp path (epoch ms preferred) or "#MERGE" for split date/time. Required for "events" only
platform String "web", "android", "ios", or "api". Required for "events" type only
app_version String Version string (default: "1.0.0"). Required for "events" type only
user_attributes Object User profile attributes: u_em (email), u_fn (first name), u_ln (last name), u_mb (mobile)
attr Object Event attributes (key-value pairs). Optional for "events" only
batching Boolean true for array payloads, false for single events

📋 Starter Template

Copy this template and replace the JSONPath expressions with paths from your actual payload:

Template
{
  "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.

arrow_drop_down📝 Example 1: Simple Form Submission

Scenario: Lead form sends contact info on submission

PayloadMapper Config
{
  "email": "john@example.com",
  "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

arrow_drop_down🛒 Example 2: Bulk E-commerce Orders

Scenario: System sends multiple orders in single webhook

PayloadMapper Config
{
  "orders": [
    {
      "order_id": "ORD-001",
      "customer_email": "alice@ex.com",
      "order_total": 99.99,
      "currency": "USD",
      "order_date": 1704067200000
    },
    {
      "order_id": "ORD-002",
      "customer_email": "bob@ex.com",
      "order_total": 149.50,
      "currency": "USD",
      "order_date": 1704070800000
    }
  ]
}

✅ Key Points: batching=true for arrays • [*] wildcard iterates • Creates separate event per order

arrow_drop_down📅 Example 3: Merging Date & Time

Scenario: Separate date and time fields need combining

PayloadMapper Config
{
  "user_email": "user@example.com",
  "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

arrow_drop_down👤 Example 4: User Profile Sync Only

Scenario: CRM sends profile updates without event tracking

PayloadMapper Config
{
  "email": "sarah@example.com",
  "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

arrow_drop_down🔒 Example 5: Anonymous User Tracking

Scenario: Track pre-login behavior, merge after identification

PayloadMapper Config
{
  "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.

arrow_drop_down🔄 Example 6: Dynamic User Properties (create_all)

💡 Pro Tip: Using create_all
The 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.

PayloadMapper Config
{
  "customer_id": "CUST-8890",
  "first_name": "Alex",
  "last_name": "Taylor",
  "email": "alex.t@example.com",
  "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.

arrow_drop_down🔀 Example 7: Dynamic Event Attributes (create_all)

Scenario: A CRM sends an event where both the user properties and the event details contain dynamic, unpredictable keys.

PayloadMapper Config
{
  "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.

arrow_drop_down📅 Supported Date Formats Reference
Format String Example
yyyy-MM-dd 2024-10-25
yyyy/MM/dd 2024/10/25
dd/MM/yyyy 25/10/2024
dd-MM-yyyy 25-10-2024
yyyy-MM-dd HH:mm:ss 2024-10-25 14:30:00
dd-MM-yyyy HH:mm:ss 25-10-2024 14:30:00
dd/MM/yyyy HH:mm:ss 25/10/2024 14:30:00
yyyy/MM/dd HH:mm:ss 2024/10/25 14:30:00
yyyy-MM-dd'T'HH:mm:ssZ 2024-10-25T14:30:00+0530
yyyy-MM-dd HH:mm:ss.SSSSSS 2024-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.

3

Submit: Send Your Mapper to MoEngage

Once your mapper JSON is ready, email support@moengage.com with:

  • Completed mapper JSON (attached)
  • Sample webhook payload(s)
  • Integration details: partner name, Workspace ID, Data Center, use case
4

Configure: Add the Webhook URL

MoEngage will provide you 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>
5

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:

 

arrow_drop_down✅ 200 OK - Successful Submission

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.

arrow_drop_down❌ 400 Bad Request - Missing Required Field

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.

arrow_drop_down❌ 400 Bad Request - Invalid Payload Structure

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.

arrow_drop_down❌ 401 Unauthorized - Authentication Failed

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.

arrow_drop_down❓ Other Errors - Contact SE

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

arrow_drop_down Can I send both user attributes and events together?

Yes. Include both user_attributes and attr in your mapper. Profile updates and event creation happen simultaneously.

arrow_drop_down What if customer_id doesn't exist?

A new profile is created automatically. If customer_id already exists, the event associates with the existing profile.

arrow_drop_down Can I update the mapper after deployment?

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.

arrow_drop_down What are the payload size limits?

Maximum 1MB recommended. For bulk requests, batch 100-500 events per call for optimal performance.

arrow_drop_down How do I handle nested arrays?

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 support@moengage.com with:
    • Mapper JSON (attached)
    • Sample webhook payload
    • Request ID from response
    • Issue description
  • 🎨 Mapper Help: Share your payload & requirements - our team will assist

Previous

Next

Was this article helpful?
0 out of 1 found this helpful

How can we improve this article?