curl --request PATCH \
--url https://api-{dc}.moengage.com/v5/subscription-preferences \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'MOE-APPKEY: <moe-appkey>' \
--data '
{
"user_identifier_type": "email",
"user_identifier_value": "[email protected]",
"channel": "email",
"is_globally_unsubscribed": false,
"categories": {
"promotional": false,
"newsletter": true
},
"event_attributes": {
"source": "preference_center",
"campaign_ref": "spring_sale"
}
}
'Update Subscription Preferences (V5)
Partially updates a user’s subscription preferences. The update is processed asynchronously by a separate worker, under the same SLA already communicated for this API; a successful call returns 202 Accepted, not the updated resource.
categories is a sparse map — only the categories present in the request are changed; any category omitted is left unchanged. is_globally_unsubscribed is required on every call precisely because it has no neutral default: true unsubscribes the user from every category on the channel (and categories is ignored), while false clears any existing global unsubscribe.
curl --request PATCH \
--url https://api-{dc}.moengage.com/v5/subscription-preferences \
--header 'Authorization: Basic <encoded-value>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'MOE-APPKEY: <moe-appkey>' \
--data '
{
"user_identifier_type": "email",
"user_identifier_value": "[email protected]",
"channel": "email",
"is_globally_unsubscribed": false,
"categories": {
"promotional": false,
"newsletter": true
},
"event_attributes": {
"source": "preference_center",
"campaign_ref": "spring_sale"
}
}
'Rate Limit
The rate limit is 100 RPM and 360k per day.Authorizations
Authentication is done via Basic Auth. This requires a base64-encoded string of your credentials in the format 'username:password'.
- Username: Your MoEngage app key.
- Password: Your MoEngage API secret.
Transitional note: This route currently accepts Basic Auth only. Bearer token support (Authorization: Bearer <token>) is planned but not yet active here — Bearer requests return 401 until the APISIX gateway fronts this route.
For more information on authentication and getting your credentials, refer here.
Headers
"application/json"
A UUID v4 you generate per logical update. Reusing a key with the same request body within the retention window returns the original response without reapplying the update. Reusing a key with a different request body returns 409.
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).
Client-supplied trace ID for tracing. Correlates with response_id. Supply this header or request_id in the body; if both are set, they must match.
Body
The identifier of the user to update and the preference changes to apply.
The type of identifier supplied in user_identifier_value.
moe_user_id, uid, email The identifier value. For moe_user_id, accepts either the usr_-prefixed ID or the bare 24-character hex ID.
Required on every call. When true, the user is unsubscribed from all categories on this channel, and categories is ignored. Send false explicitly to clear an existing global unsubscribe — there is no neutral default.
Optional client-supplied request identifier, used for tracing.
"req_5b6d7a8f90c1e2b4d6f8091a2c3e4f56"
Optional. The channel the categories map applies to. Only the email channel is supported at present.
email Optional sparse map of category_name to subscribe state (true = subscribed, false = unsubscribed). Only the categories present here are changed; any category not included is left unchanged.
Show child attributes
Show child attributes
Optional. Up to 5 name/value pairs attached to the subscription-update event this call raises. Any attribute name is accepted (no allowlist). Attribute names must be 50 characters or fewer; values must be 255 characters or fewer.
Show child attributes
Show child attributes
Response
This response is returned when the request has been accepted and queued for asynchronous processing. The update is applied by a separate worker under SLA; this response does not confirm the update has been applied yet — poll Get Subscription Preferences to check the applied state.