Legacy API Field Mapping

How the V2 fields are designed, and how legacy statements/search fields map to Listen API V2.

This page explains how the Listen API V2 fields are designed, and maps every field of the legacy statements/search endpoint to V2. For the migration steps, see Migrating from Legacy API to Listen API V2.

How the V2 fields are designed

V2 does not copy the legacy field list one to one. It follows four design principles; once you know them, most of the mappings below are predictable.

PrincipleLegacy API (V1)Listen API V2
Structured objects instead of flat fields62 top-level fields, plus 24 counters in metadataRelated data grouped into objects: author, source, content, engagementMetrics, location, discussion, context
Human-readable datesMilliseconds since 1970 (1761125400000) or local-time strings (2025-12-01 00:00:00.000 CET)ISO 8601 in UTC (2026-10-20T09:12:15Z), in requests and responses
Enumeration values that mirror the Listen appInternal codes: POSITIVE, st / ar, microblog, m / f / uThe labels you see in the app: Positive, Post / Article, X, Male / Female
Consistent namingMixed names: likes, retweets, createdAtCounters end with Count (likeCount), timestamps end with At (publishedAt, collectedAt)

Structured objects instead of flat fields

The legacy Statement put everything on one level, so author, source, content and metrics fields were mixed together. V2 groups them by what they describe:

  • author: who wrote the mention (ID, name, avatar, gender, follower and fan counts)
  • source: where it was published (platform type, social channel such as a Facebook page, and the mention URL)
  • content: what it says (title, text, language, sentiment, review rating)
  • engagementMetrics: how people reacted (influence score, engagement rate, counters)
  • location: where it comes from (country, region, city, coordinates)
  • discussion and context: the thread it belongs to and its parent

Platform-specific values have their own sub-objects, such as engagementMetrics.sourceMetrics.facebook for reactions. A sub-object that does not apply to a mention is null, instead of adding fields that are empty for most mentions.

The same Facebook post in both APIs (fields shortened):

Legacy API (V1)

{
  "author": "Sarah Johnson",
  "authorId": "1234567890",
  "sex": "f",
  "createdAt": 1761125400000,
  "sentiment": "POSITIVE",
  "group": "facebook",
  "sourceName": "Tech Reviews Hub",
  "metadata": { "likes": 28, "followers": 245 }
}

Listen API V2

{
  "author": {
    "id": "1234567890",
    "name": "Sarah Johnson",
    "gender": "Female",
    "influenceMetrics": { "followerCount": 245 }
  },
  "publishedAt": "2025-10-22T09:30:00Z",
  "content": { "sentiment": "Positive" },
  "source": { "type": "Facebook", "socialChannel": { "name": "Tech Reviews Hub" } },
  "engagementMetrics": { "sourceMetrics": { "common": { "likeCount": 28 } } }
}

Human-readable dates

Every date in V2, in requests and in responses, is an ISO 8601 string in UTC, such as 2026-10-20T09:12:15Z. You can read it in logs and pass it to any date library without knowing a time zone or a timestamp unit.

Enumeration values that mirror the Listen app

Enumeration values use the same names as the Listen app UI: sentiment is Positive, Negative, Neutral or Unspecified; sources are Facebook, X, Reddit and so on. What you see in the app is what you send in filters and get back in responses.

📘

Enumerations can grow

New values may be added to enumerations such as SourceType and MentionType without a major version change. Make sure your integration tolerates values it does not recognize.

Request fields: legacy → V2

V2 groups filters under filters and uses ISO 8601 UTC dates and capitalized enum values.

Legacy fieldV2 equivalentNotes
topicIdprojectId in the pathTopics are now called projects. List them with GET /projects.
threadIddiscussionId in the path of /discussions/{discussionId}/…Thread IDs changed format; take discussion.id from a V2 mention.
from, tofilters.publishedAt.from, .toISO 8601 UTC only (no ms timestamps, no time zone names). to is exclusive.
indexedFrom, indexedTofilters.collectedAt.from, .toNot available on live streams.
sentiment (POSITIVE, …)filters.content.sentiment (Positive, Negative, Neutral, Unspecified)
language (["en"])filters.content.language ([{"code": "en"}])Each code is an object. Dialects (e.g. de-at) are included automatically.
country (["pl"])filters.location.country ([{"code": "pl"}])Each code is an object.
groupfilters.source.typeblog→Blogs, forum→Forums, portal→Websites, facebook→Facebook, instagram→Instagram, microblog→X, video→Video, review→Reviews, tiktok→TikTok, reddit→Reddit. google has no equivalent.
type: arfilters.type: ["Article"]
type: stfilters.type: ["Post", "Comment", "Share", "PrivateMessage"]V2 distinguishes posts from comments. Omit type for everything (legacy all).
textFilterfilters.content.queryListen Query Language: keywords, "phrases", AND/OR/NOT, suffix *. Matches text and title. Max 500 characters.
sort + ordersortTypecreatedAt → PublishedAtAscending/Descending. New: CollectedAt*, InfluenceScoreDescending, EngagementRateDescending, LikeCountDescending, ShareCountDescending, FollowerCountDescending. Sorting by sentiment is gone.
page, rowsStreams: none, use limit to cap the count. Search: cursor query parameter, 25 per page.
withMetadataAlways onEngagement metrics are always in engagementMetrics.
author, domain, sex, continent, region, city, includeIgnoredNo equivalentNarrow the project query instead, or filter on the response fields.

Response fields: legacy Statement → V2 Mention

V2 returns a nested Mention object. Timestamps are ISO 8601 UTC strings instead of milliseconds, and empty values are null or absent.

Legacy fieldV2 field
idid (new format). Old ID: deprecatedV1Fields.id
threadIddiscussion.id (new format)
initialAuthordiscussion.author.name
type, isComment, private, isRetweettype: Post, Comment, Article, PrivateMessage, Share (retweets are Share)
createdAt (ms)publishedAt
—collectedAt (when SentiOne found the mention)
titlecontent.title
textcontent.text
languagecontent.language.code (dialects such as de-at become de)
sentiment (POSITIVE, …, UNKNOWN)content.sentiment (Positive, …, Unspecified)
urlsource.mentionUrl
groupsource.type (mapping as in the request table)
sourceName, sourceIdsource.socialChannel.name, .id
author, authorIdauthor.name, author.id
sex (m, f, u)author.gender (Male, Female, Unspecified)
media.avatarauthor.avatar.url
metadata.followers, metadata.fansauthor.influenceMetrics.followerCount, .fanCount
media.images, media.videoattachments[] with type Image / Video / Other
countrylocation.country.code
latitude, longitudelocation.coordinates.latitude, .longitude
—location.region, location.city
influenceScoreengagementMetrics.influenceScore (1–10)
engagementRateengagementMetrics.engagementRate
metadata.likes, shares, comments, viewsengagementMetrics.sourceMetrics.common.likeCount, shareCount, commentCount, viewCount
metadata.reactions.*engagementMetrics.sourceMetrics.facebook.*Count (Facebook only)
metadata.retweets, favouritesengagementMetrics.sourceMetrics.twitter.retweetsCount, favouritesCount (X only)
metadata.digs, burrowsengagementMetrics.sourceMetrics.newsAggregators.digsCount, burrowsCount
parentTextcontext.parent.content.text
parentIdCall GET /mentions/{mentionId}/parent
tagstags
—content.review.rating (review sources)

Fields removed in V2

These legacy fields have no direct V2 field. Where the information is still available, the last column says where to find it.

Legacy fieldWhat it containedIn V2
keywordsA search helper: a merged copy of several other fieldsNot needed. Search with filters.content.query and read the original fields
hostDomain where the mention was publishedDerive it from source.mentionUrl
sourceURLLink to the sourcesource.mentionUrl
imageAuthor's avatar, or the attached image if there was no avatarauthor.avatar and attachments
authorURLLink to the author's profileNo equivalent
hasImageOrVideoWhether the mention has an image or videoCheck attachments for Image or Video items
facebookPageId, youtubeChannelIdID of the Facebook page or YouTube channelsource.socialChannel.id
facebookIds, facebookMessengerThreadIdFacebook IDs in the context; Messenger thread IDNo equivalent. For threads, use discussion.id
socialType, isInstagramStoryPlatform-specific subtype, such as twitterTweet or facebookPhoto; Instagram story flagtype together with source.type
link, description, caption, context, contextTitle, metaTitleDetails of shared or attached content: link, description, caption, page titleNo equivalent. The mention's own title is in content.title
placesPlaces tagged in the post (Foursquare, Instagram, Twitter)No equivalent. Geolocation is in location
recipientsRecipients of the post (Facebook, Wykop)No equivalent
parentCreatedAt and the parent* counters (parentLikes, parentComments, parentFans, parentFollowers, …)Date and metrics of the parent postGET /mentions/{mentionId}/parent returns the full parent mention, including publishedAt and engagementMetrics. Its text is also in context.parent.content.text
metadata.friends, hearts, pluses, uniqueUsersCounters of legacy platforms (Facebook friends, Foursquare and Instagram hearts, Google+ pluses, Instagram unique users)No equivalent. Common counters are in engagementMetrics.sourceMetrics.common
sourceData, sourceLimitationsRaw source-specific data; limits on replying or other actions in the appNo equivalent
isRead, isReplied, isRepliedPriv, isTrashed, ignored, userId, statusWorkflow state from the Listen app: read, replied, trashed, ignored, assigned user, statusNot exposed: V2 returns collected data, not app workflow state. Your own labels are available as tags
isBotWhether the author was detected as a botNo equivalent
isDeleted, isHiddenWhether the mention was deleted or hidden on the source platformNo equivalent

Matching data you already stored

V2 mention IDs differ from legacy statement IDs. To avoid duplicates when you switch, each V2 mention carries deprecatedV1Fields.id, the legacy id of the same mention. Use it once to match V2 records to what you already stored, then key everything on the V2 id.

🚧

deprecatedV1Fields is temporary

It will be removed in a later version. Use it only for the one-time matching, and don't build ongoing logic on it.