Skip to content

SES v2 ListContacts API — FilteredStatus does not match topic-level OPT_OUT contacts

0

The ListContacts API does not return contacts that have OPT_OUT in their TopicPreferences for a specific topic when using FilteredStatus: OPT_OUT combined with TopicFilter. It only returns contacts where UnsubscribeAll is true.

This contradicts the documented behavior in the SES List Management Guide, which shows FilteredStatus + TopicFilter as the intended way to query contacts by topic subscription status.

Relevant documentation:

  • ListContacts API Reference
  • ListContactsFilter schema (describes FilteredStatus and TopicFilter fields)
  • TopicFilter schema (describes UseDefaultIfPreferenceUnavailable)
  • SES List Management Guide (walkthrough example that shows FilteredStatus + TopicFilter used together to query contacts by topic subscription status)

The Developer Guide walkthrough explicitly demonstrates this usage pattern:

{
"ContactListName": "ExampleContactListName",
    "Filter": {
        "FilteredStatus": "OPT_IN",
        "TopicFilter": {
            "TopicName": "Cycling",
            "UseDefaultIfPreferenceUnavailable": true
        }
    },
    "PageSize": 50
}

Per that guide, this call should return contacts whose effective subscription status for the "Cycling" topic is OPT_IN. By the same logic, FilteredStatus: OPT_OUT with a TopicFilter should return contacts opted out of that topic — but it does not.

STEPS TO REPRODUCE:

Verify List and Topic Setup We have a contact list named ExampleContactList with a topic topic_1.

Verify Contact Preferences A contact exists with an explicit topic-level OPT_OUT preference. Verified via GetContact:

aws sesv2 get-contact --contact-list-name ExampleContactList --email-address "<REDACTED_EMAIL>" --region eu-central-1

Response:

{
    "ContactListName": "ExampleContactList",
    "EmailAddress": "<REDACTED_EMAIL>",
    "TopicPreferences": [
        {
            "TopicName": "topic_1",
            "SubscriptionStatus": "OPT_OUT"
        }
    ],
    "TopicDefaultPreferences": [
        {
            "TopicName": "topic_2",
            "SubscriptionStatus": "OPT_IN"
        },
        {
            "TopicName": "topic_3",
            "SubscriptionStatus": "OPT_IN"
        },
        {
            "TopicName": "topic_4",
            "SubscriptionStatus": "OPT_IN"
        },
        {
            "TopicName": "topic_5",
            "SubscriptionStatus": "OPT_IN"
        },
        {
            "TopicName": "topic_6",
            "SubscriptionStatus": "OPT_IN"
        },
        {
            "TopicName": "topic_7",
            "SubscriptionStatus": "OPT_IN"
        },
        {
            "TopicName": "topic_8",
            "SubscriptionStatus": "OPT_IN"
        }
    ],
    "UnsubscribeAll": false,
    "CreatedTimestamp": "2026-03-25T15:44:37.022000+03:00",
    "LastUpdatedTimestamp": "2026-03-27T16:47:56.368000+03:00"
}

Note: The contact has UnsubscribeAll: false and one explicit OPT_OUT entry in TopicPreferences for topic_1.

Query ListContacts Querying ListContacts with FilteredStatus: OPT_OUT and TopicFilter for that topic returns 0 contacts:

aws sesv2 list-contacts --contact-list-name ExampleContactList --filter '{"FilteredStatus":"OPT_OUT","TopicFilter":{"TopicName":"topic_1","UseDefaultIfPreferenceUnavailable":false}}' --region eu-central-1

Response:

{
    "Contacts": [],
    "NextToken": "[NEXT_TOKEN]"
}

Note: The contact above is not returned despite having an explicit OPT_OUT for topic_1.

EXPECTED BEHAVIOR:

Per the ListContactsFilter documentation and the List Management Guide walkthrough, the contact with TopicPreferences: [{ TopicName: "topic_1", SubscriptionStatus: "OPT_OUT" }] should be returned.

OBSERVED BEHAVIOR:

FilteredStatus: OPT_OUT only matches contacts where UnsubscribeAll: true. Topic-level OPT_OUT entries in TopicPreferences are ignored, making the TopicFilter field effectively non-functional for finding opted-out contacts.

ADDITIONAL OBSERVATION:

Omitting FilteredStatus while providing TopicFilter returns an HTTP 400 error with the message "Invalid FilteredStatus " — meaning the Filter object requires FilteredStatus.

This creates a catch-22: the field is required, but its value does not consider topic-level preferences. There is no API-native way to list contacts opted out of a specific topic. Per the Contact object schema, contacts expose both UnsubscribeAll and TopicPreferences, but FilteredStatus appears to only evaluate UnsubscribeAll.

IMPACT:

We are currently migrating from another provider to SES and need to sync topic-level unsubscribes bidirectionally across ~50,000 contacts and 10 topics. Due to this issue, we cannot use the ListContacts filter to efficiently query per-topic OPT_OUT contacts. We are forced to implement a workaround: fetching the entire contact list via a full paginated scan on every sync run and filtering in our application code by inspecting TopicPreferences entries.

1 Answer
0

Based on the Amazon SES API v2 documentation, I can confirm that the ListContacts API is designed to work with both FilteredStatus and TopicFilter parameters together. The documentation shows that FilteredStatus filters contacts by their subscription status (OPT_IN or OPT_OUT), while TopicFilter allows filtering by a specific topic preference.

The documented example demonstrates using these parameters together to retrieve contacts subscribed to a particular topic. The FilteredStatus parameter specifies whether you want to filter for OPT_IN or OPT_OUT contacts, and when combined with TopicFilter, it should return contacts based on their subscription status for that specific topic.

The TopicFilter includes a UseDefaultIfPreferenceUnavailable parameter that determines whether to use the topic's default preference if a contact doesn't have an explicit preference set. When set to true, the topic default preference will be used for contacts without explicit preferences. When set to false, only contacts with explicitly set preferences are considered for filtering.

Based on the behavior you're describing, where topic-level OPT_OUT preferences in TopicPreferences are not being returned when using FilteredStatus: OPT_OUT with a TopicFilter, this appears to be inconsistent with the documented functionality. The API should evaluate the contact's effective subscription status for the specified topic, which includes both explicit topic preferences and the default subscription status.

For your migration scenario involving bidirectional sync of topic-level unsubscribes, the intended design would allow you to efficiently query contacts by their per-topic subscription status without needing to fetch and filter the entire contact list in your application code. I recommend opening a support case with AWS to investigate this specific behavior, as it may require service team investigation to determine if this is a service limitation or an issue that needs to be addressed.
Sources
Using list management - Amazon Simple Email Service
ListContactsFilter - Amazon Simple Email Service

answered a month ago
EXPERT
reviewed a month ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.