curl --request POST \
--url https://api-{dc}.moengage.com/v3/custom-segments \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'MOE-APPKEY: <moe-appkey>' \
--data '
{
"name": "active-users-segment",
"included_filters": {
"filter_operator": "and",
"filters": [
{
"filter_type": "user_attributes",
"name": "status",
"data_type": "string",
"category": "Lifecycle",
"operator": "in",
"negate": false,
"case_sensitive": false,
"value": [
"active"
]
}
]
}
}
'{
"data": {
"name": "segment name",
"id": "segment id",
"created_time": "2022-12-20T06:21:44.112000",
"updated_time": "2022-12-20T06:21:44.160000",
"type": "ELASTIC_SEARCH",
"source": "API",
"description": "Subscription Status 19Dec_7 is active (case insensitive) AND Has executed Email Sent atleast 1 time in-between Jan 05, 2021 and Jan 08, 2021",
"included_filters": {
"filter_operator": "and",
"filters": [
{
"filter_type": "user_attributes",
"name": "Subscription Status 19Dec_7",
"data_type": "string",
"operator": "in",
"value": [
"active"
],
"negate": false,
"case_sensitive": false
},
{
"filter_type": "actions",
"attributes": {
"filter_operator": "and",
"filters": []
},
"executed": true,
"primary_time_range": {
"type": "between",
"value": "2023-02-15T00:00:00.000Z",
"value1": "2023-02-24T23:59:59.999Z",
"value_type": "absolute",
"period_unit": "days"
},
"action_name": "MOE_EMAIL_SENT",
"execution": {
"count": 1,
"type": "atleast"
}
}
]
}
},
"response_id": "cNjnTEJw",
"type": "custom_segment"
}Create Filter Segment
This API creates a new segment based on a set of filter conditions.
curl --request POST \
--url https://api-{dc}.moengage.com/v3/custom-segments \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'MOE-APPKEY: <moe-appkey>' \
--data '
{
"name": "active-users-segment",
"included_filters": {
"filter_operator": "and",
"filters": [
{
"filter_type": "user_attributes",
"name": "status",
"data_type": "string",
"category": "Lifecycle",
"operator": "in",
"negate": false,
"case_sensitive": false,
"value": [
"active"
]
}
]
}
}
'{
"data": {
"name": "segment name",
"id": "segment id",
"created_time": "2022-12-20T06:21:44.112000",
"updated_time": "2022-12-20T06:21:44.160000",
"type": "ELASTIC_SEARCH",
"source": "API",
"description": "Subscription Status 19Dec_7 is active (case insensitive) AND Has executed Email Sent atleast 1 time in-between Jan 05, 2021 and Jan 08, 2021",
"included_filters": {
"filter_operator": "and",
"filters": [
{
"filter_type": "user_attributes",
"name": "Subscription Status 19Dec_7",
"data_type": "string",
"operator": "in",
"value": [
"active"
],
"negate": false,
"case_sensitive": false
},
{
"filter_type": "actions",
"attributes": {
"filter_operator": "and",
"filters": []
},
"executed": true,
"primary_time_range": {
"type": "between",
"value": "2023-02-15T00:00:00.000Z",
"value1": "2023-02-24T23:59:59.999Z",
"value_type": "absolute",
"period_unit": "days"
},
"action_name": "MOE_EMAIL_SENT",
"execution": {
"count": 1,
"type": "atleast"
}
}
]
}
},
"response_id": "cNjnTEJw",
"type": "custom_segment"
}Generate Request from Dashboard
To simplify payload generation, MoEngage provides a tool in the dashboard where you can configure filters and export the payload.- Log in to the MoEngage dashboard.
- Click Test & Debug at the lower left in the side panel.
- Click Segment Payload.
- Specify the segment name and configure the required filters.
- Click Generate Payload.
Rate Limit
The rate limit is 50 requests/minute, 200 requests/hour, and 1000 requests/day.Payload Reference
Top-Level Structure
Every segment request is a tree of filters underincluded_filters and an optional excluded_filters root.
{
"name": "my-segment",
"included_filters": {
"filter_operator": "and",
"filters": []
},
"excluded_filters": {
"filter_operator": "and",
"filters": []
}
}
filter_operator at every level accepts "and" or "or". Groups can nest to arbitrary depth using nested_filters.
Filter Types
filter_type | Purpose |
|---|---|
user_attributes | Filter by a user profile attribute |
actions | Filter by an event the user has or has not performed |
psychographic_event | Filter by affinity/behavioral patterns over an event |
custom_segments | Reference a saved segment by ID |
nested_filters | AND/OR group container for combining other filters |
User Property Filter (filter_type: "user_attributes")
Required Fields
| Field | Type | Notes |
|---|---|---|
filter_type | string | Always "user_attributes" |
name | string | Attribute name, for example last_purchase_date |
data_type | string | See data type table below |
category | string | The attribute group the attribute belongs to (for example, "Tracked Custom Attribute"). Always include this key. |
operator | string | Allowed set varies by data_type; omit for geopoint, object, array_object |
negate | boolean | true inverts the filter; omitted for object and array_object |
value | varies | Shape depends on operator; absent for exists and today |
project_name. See Portfolio Workspaces under the User Behavior filter for the values it takes.
Supported Data Types
data_type | Allowed operators | Extra fields |
|---|---|---|
string | in, is, contains, startsWith, endsWith, containsInTheFollowing, startsWithInTheFollowing, endsWithInTheFollowing, exists | case_sensitive |
double | in, lessThan, greaterThan, between, exists | value1 when operator is between |
bool | is, exists | — |
datetime | on, between, before, after, inTheLast, inTheNext, today, is, in, exists | value_type, value1 for between, extract_type for date-part filters |
geopoint | (implicit around — no operator) | value (latitude), value1 (longitude), radius; carries negate but no operator |
array_string | in, contains, startsWith, endsWith, is, exists | case_sensitive, array_filter_type (any_of or all_of) |
array_double | in, lessThan, greaterThan, between, exists | array_filter_type (any_of or all_of); value1 for between |
object | N/A | filter_operator, filters[] (recursive); no operator, negate, or value |
array_object | N/A | filter_operator, filters[] (recursive); no operator, negate, or value |
containsSpaces or is_empty operator at the payload level. Send the equivalent operator and value instead:
| Dashboard option | operator | value |
|---|---|---|
| Contains spaces | contains | " " (a single space) |
| Is empty | is | "" (an empty string) |
negate: true to express “does not contain spaces” or “is not empty”.
value shape by operator:
- Array:
in(string, double, array types);containsInTheFollowing,startsWithInTheFollowing,endsWithInTheFollowing(string);contains,startsWith,endsWith(array_string);in(datetime with time/day/month extract types) - Scalar:
is(bool, datetime, and the string/array_string cases in the table above),on,before,after,lessThan,greaterThan,inTheLast,inTheNext - Absent:
exists,today
exists cleans up: When operator is exists, value, value1, and value_type are removed from the payload.
Datetime value_type and extract_type
Set value_type to:
"absolute"—valueis an ISO 8601 date string, for example"2024-01-15T00:00:00.000Z""relative_past"—valueis an integer number of days/hours/months ago"relative_future"—valueis an integer number of days/hours/months in the future (used with theafterandinTheNextoperators)
extract_type to filter on a specific part of the date. Omit it to match on the full date:
"time_of_the_day"— hour (0–23)"day_of_the_week"— weekday (0–6)"day_of_the_month"— day (1–31)"month_of_the_year"— month (1–12)"date_month_of_the_year"— month and day as anMM-DDstring, for example"06-15"
Cross-Attribute Comparison (Dynamic Values)
To compare a user attribute against another user attribute rather than a literal, setis_dynamic_value: true, set dynamic_attribute_type to the base type of the referenced attribute, and use a template string in value:
| Source | value template |
|---|---|
| User attribute | "{{MoeUserAttribute['<attr_name>']}}" |
dynamic_attribute_type uses the base element type: array_string → "string", array_double → "double". For datetime, value_type is forced to "absolute".
Cross-attribute comparison is not available for:
objectandarray_objectattributes.doubleandarray_doubleattributes whenoperatorisbetween.
{
"name": "order_value",
"data_type": "double",
"filter_type": "user_attributes",
"operator": "greaterThan",
"negate": false,
"value": "{{MoeUserAttribute['lifetime_value']}}",
"is_dynamic_value": true,
"dynamic_attribute_type": "double"
}
User Behavior Filter (filter_type: "actions")
Required Fields
| Field | Type | Notes |
|---|---|---|
filter_type | string | Always "actions" |
action_name | string | The internal event name |
project_name | string | Optional; portfolio (multi-project) workspaces only. See Portfolio Workspaces below. |
executed | boolean | true = has performed; false = has NOT performed |
execution | object | Frequency condition |
primary_time_range | object | Time window for the event |
attributes | object | Event attribute sub-filters; always include, even when empty |
{
"filter_type": "actions",
"action_name": "purchase",
"executed": true,
"execution": { "type": "atleast", "count": 1 },
"primary_time_range": {
"type": "inTheLast",
"value": 30,
"value_type": "relative_past",
"period_unit": "days"
},
"attributes": { "filter_operator": "and", "filters": [] }
}
Execution (Frequency)
execution.type | Meaning | count required |
|---|---|---|
atleast | At least N times (default for executed: true) | Yes |
exactly | Exactly N times | Yes |
atmost | At most N times | Yes |
firstTime | For the first time only | No — omit count |
lastTime | For the last time only | No — omit count |
executed: false, execution is { "type": "exactly", "count": 0 }.
Primary Time Range
primary_time_range stores five keys: type, value, value1 (only for between), value_type, and period_unit. The payload accepts five type values:
type | value shape | Needs value1 | value_type |
|---|---|---|---|
inTheLast | Integer count of period_unit | No | relative_past (locked) |
between | Start value: ISO date or integer count | Yes (end value) | absolute or relative_past |
on | ISO date or integer count | No | absolute or relative_past |
before | ISO date or integer count | No | absolute or relative_past |
after | ISO 8601 date | No | absolute (locked) |
period_unit accepts hours, days, weeks, or months, and applies to inTheLast.
The dashboard also offers calendar windows such as Today and This week. These are not payload type values — each maps onto type: "on" with a specific value and period_unit:
| Dashboard option | Payload |
|---|---|
| Today | { "type": "on", "value": 0, "value_type": "relative_past", "period_unit": "days" } |
| Yesterday | { "type": "on", "value": 1, "value_type": "relative_past", "period_unit": "days" } |
| This week | { "type": "on", "value": 0, "value_type": "relative_past", "period_unit": "weeks" } |
| Last week | { "type": "on", "value": 1, "value_type": "relative_past", "period_unit": "weeks" } |
| This month | { "type": "on", "value": 0, "value_type": "relative_past", "period_unit": "months" } |
| Last month | { "type": "on", "value": 1, "value_type": "relative_past", "period_unit": "months" } |
value → YYYY-MM-DDT00:00:00.000Z; value1 → YYYY-MM-DDT23:59:59.999Z. For between, value1 must be greater than value.
days (and days1) instead of value and period_unit. A response for one of those segments returns that form. Send value, value_type, and period_unit when you create or update a segment through the API.Event Attribute Sub-Filters
Use theattributes block to narrow which event occurrences count — for example, a purchase event where product_category is "electronics".
Inner filters follow the same shape as User Property filters, with two differences:
filter_typeis"action_attributes"instead of"user_attributes".categoryis"default".
filter_type when it echoes these filters back in a response, so send it on the request even though a GET on the segment will not show it.
Inner filters start directly from filter_operator and filters — do not add included_filters or excluded_filters inside the attributes block.
"attributes": {
"filter_operator": "and",
"filters": [
{
"name": "currency",
"data_type": "string",
"category": "default",
"filter_type": "action_attributes",
"operator": "is",
"negate": false,
"case_sensitive": false,
"value": "USD"
}
]
}
Aggregation (sum / avg / min / max / median)
Addaggregation_attributes to compare an aggregate of a numeric event attribute against a threshold. The block holds exactly one filter.
Aggregation is only available when executed: true, execution.type is not firstTime or lastTime, and primary_time_range.type is not before or after.
| Key | Values |
|---|---|
attribute_name | The numeric event attribute to aggregate |
data_type | double |
aggregation_type | sum, avg, min, max, median |
operator | is, between, lessThan, greaterThan |
negate | true inverts the comparison (“is not equal to”, “is not between”) |
value | The numeric threshold; add value1 when operator is between |
comparator | Omit for a plain aggregate. Set to change or percentageChange to compare against an earlier window |
base_time_range | Required when comparator is set; omit otherwise |
"aggregation_attributes": {
"filter_operator": "and",
"filters": [
{
"attribute_name": "revenue",
"data_type": "double",
"aggregation_type": "sum",
"operator": "greaterThan",
"negate": false,
"value": 1000,
"is_dynamic_value": false
}
]
}
comparator is change or percentageChange, add base_time_range to define the window to compare against:
| Base window | base_time_range |
|---|---|
| Previous period | { "type": "previousPeriod" } |
| Fixed date range | { "type": "between", "value": "<start ISO>", "value1": "<end ISO>" } |
{
"attribute_name": "revenue",
"data_type": "double",
"aggregation_type": "sum",
"operator": "greaterThan",
"negate": false,
"value": 25,
"is_dynamic_value": false,
"comparator": "percentageChange",
"base_time_range": {
"type": "between",
"value": "2024-01-01T00:00:00.000Z",
"value1": "2024-01-31T23:59:59.999Z"
}
}
Portfolio (Multi-Project) Workspaces
In workspaces with more than one project, addproject_name to scope a filter to a specific project. Both User Behavior and User Property filters accept the key. Omit it in single-project workspaces.
Set project_name to the name of the project you want to scope to. "moe_portfolio" is one of the available values and targets all projects.
User Affinity Filter (filter_type: "psychographic_event")
Targets users based on behavioral affinity over an event. primary_time_range and psychographic_attributes are required.
Psychographic attribute filters support only the string and double data types, use category values such as "Event Attributes", and carry no filter_type key. The primary_time_range object also uses a different shape from User Behavior filters: relative windows use days (and days1) instead of value/value1, and absolute windows use from and to ISO 8601 dates, along with type and value_type.
Time-Based Affinity Filters
Four affinity filters target the time at which the event happens rather than an event attribute. Each uses the attribute namemoe_user_datetime, category "Time Attributes", data_type "double", and an extract_type:
extract_type | Meaning | Value range |
|---|---|---|
time_of_the_day | Hour of the day | 0–23 |
day_of_the_week | Day of the week | 0–6 |
day_of_the_month | Day of the month | 1–31 |
month_of_the_year | Month of the year | 1–12 |
value follows the operator: a scalar for is, an array for in, and value plus value1 for between.
"psychographic_attributes": {
"filter_operator": "and",
"filters": [
{ "name": "moe_user_datetime", "data_type": "double", "category": "Time Attributes",
"operator": "is", "negate": false, "value": 9, "extract_type": "time_of_the_day" },
{ "name": "moe_user_datetime", "data_type": "double", "category": "Time Attributes",
"operator": "in", "negate": false, "value": [0, 6], "extract_type": "day_of_the_week" },
{ "name": "moe_user_datetime", "data_type": "double", "category": "Time Attributes",
"operator": "between", "negate": false, "value": 1, "value1": 31,
"extract_type": "day_of_the_month" }
]
}
operator_type | Extra field | Meaning |
|---|---|---|
predominant | — | User most frequently exhibits this affinity |
minimum | percent_of_times (1–100) | Affinity is present at least N% of the time |
top | percent_of_users (1–100) | User is in the top N% by this affinity metric |
bottom | percent_of_users (1–100) | User is in the bottom N% by this affinity metric |
Custom Segment Filter (filter_type: "custom_segments")
References a saved segment by ID. The backend resolves the segment by id; name is a display label only.
{ "filter_type": "custom_segments", "id": "5c93982f573bb92004975a36", "name": "High-value customers" }
Nested Filters (filter_type: "nested_filters")
Use nested_filters inside included_filters or excluded_filters to create complex boolean logic (for example, (A AND B) OR (C AND D)). Groups can nest to arbitrary depth.
{
"filter_type": "nested_filters",
"filter_operator": "or",
"filters": [
{ "filter_type": "user_attributes", ... },
{ "filter_type": "actions", ... }
]
}
Authorizations
Authentication is done via Basic Auth. This requires a base64-encoded string of your credentials in the format 'username:password'.
- Username: Use your MoEngage workspace ID (also known as the App ID). You can find it in the MoEngage dashboard at Settings > Account > APIs > Workspace ID (earlier app id).
- Password: Use your API Key, which you can find within the Data tile.
For more information on authentication and getting your credentials, refer here.
Headers
This is the Workspace ID of your MoEngage account that must be passed with the request. You can find it in the MoEngage dashboard at Settings > Account > APIs > Workspace ID (earlier app id).
You can send MOE-DBNAME with your database name instead of this header. The request must include one of the two.
Your MoEngage database name. Send this as an alternative to MOE-APPKEY when you identify the
workspace by database name. Omit it when MOE-APPKEY is already present.
Body
The filter definition for the new segment.
Request schema for creating a filter-based segment.
A unique name for the segment.
The filter criteria for users to include in the segment. Users matching these filters are added to the segment.
Show child attributes
Show child attributes
Optional. The filter criteria for users to exclude. Users matching these filters are removed from the
included set even if they satisfy included_filters.
Show child attributes
Show child attributes
Response
Segment created successfully. Returns the newly created segment details including its unique ID, filter definition, and metadata.