{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/mentio-dev/json-schema/mentio-dev-mention-schema.json",
  "title": "Mention",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/mentio-dev-api-openapi.json#/components/schemas/Mention",
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Mention id (mm_...): one post matched to one of your keywords. A post matching two keywords has two ids."
    },
    "status": {
      "type": "string",
      "enum": [
        "open",
        "ignored",
        "done"
      ],
      "description": "open: nobody handled it yet. ignored: hidden from the feed and channels by you. done: handled."
    },
    "relevant": {
      "type": "boolean",
      "description": "The classifier scored it at or above the delivery threshold (40)."
    },
    "delivered": {
      "type": "boolean",
      "description": "Reached at least one of your channels."
    },
    "priority": {
      "type": "number",
      "description": "Attention score, one decimal, computed at read time: relevance halved, author reach on a follower ladder (unknown reach counts 8), the strongest intent (buy intent 20 down to praise 5), minus 2 per day of age floored at 20."
    },
    "keyword": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Keyword id (kw_...)."
        },
        "term": {
          "type": "string",
          "description": "The tracked term."
        },
        "group": {
          "$ref": "#/$defs/GroupRef"
        },
        "matchedAs": {
          "type": "string",
          "enum": [
            "phrase",
            "close_words"
          ],
          "description": "phrase: the post holds the term as written. close_words: it holds the term's words close together, in another order or form (kept and billed only because the classifier scored it relevant)."
        },
        "matchedIn": {
          "type": "string",
          "enum": [
            "text",
            "speech"
          ],
          "description": "text: the term is in the post itself (its text, caption, hashtags or review). speech: it is only in what is said in the video (TikTok), whose transcript follows the 🎙 mark in post.text."
        }
      },
      "required": [
        "id",
        "term",
        "group",
        "matchedAs",
        "matchedIn"
      ],
      "description": "The keyword this post matched, the group it is in, and how it matched."
    },
    "post": {
      "type": "object",
      "properties": {
        "platform": {
          "type": "string",
          "enum": [
            "bluesky",
            "hackernews",
            "github",
            "stackoverflow",
            "devto",
            "reddit",
            "x",
            "youtube",
            "news",
            "linkedin",
            "tiktok",
            "instagram",
            "appstore",
            "googleplay",
            "trustpilot",
            "googlemaps",
            "rss"
          ],
          "description": "Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place), rss (RSS and Atom feeds a keyword reads)."
        },
        "kind": {
          "type": "string",
          "enum": [
            "post",
            "comment",
            "repository"
          ],
          "description": "post: a top-level post. comment: an item that answers a post or another comment (a Reddit or Hacker News comment, an X or Bluesky reply, a Stack Overflow answer, a YouTube comment). repository: an event about a GitHub repository naming the keyword (see post.repository)."
        },
        "url": {
          "type": "string",
          "description": "Permalink of the post."
        },
        "text": {
          "type": "string",
          "description": "Title and body, truncated to 8 KB at ingest."
        },
        "title": {
          "type": [
            "string",
            "null"
          ],
          "description": "The post's own title where the platform has one: a Hacker News story, a Reddit thread, a GitHub issue or pull request, a Stack Overflow question, a DEV article, a YouTube video, a news article, a titled review. Null for platforms without titles (X, Bluesky, LinkedIn) and for posts ingested before October 2026."
        },
        "imageUrl": {
          "type": [
            "string",
            "null"
          ],
          "description": "A preview image of the post, when the platform sent one with it: a YouTube thumbnail, a DEV cover, a news article's sharing image, a Bluesky link card or image. Null otherwise."
        },
        "subreddit": {
          "type": [
            "string",
            "null"
          ],
          "description": "The subreddit a Reddit post was written in, without the r/ (SaaS). Null on every other platform."
        },
        "flair": {
          "type": [
            "string",
            "null"
          ],
          "description": "A Reddit post's flair, when its subreddit uses them (Question, Show and Tell). Null otherwise."
        },
        "repository": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "name": {
              "type": "string",
              "description": "The repository, owner/name."
            },
            "event": {
              "type": "string",
              "enum": [
                "new",
                "traction",
                "stars",
                "growth",
                "top"
              ],
              "description": "What happened. new: it was created. traction: under 30 days old, it reached 10 stars. stars: it passed a star milestone. growth: it gained stars fast in a week. top: one of the most starred repositories naming the keyword, brought by a new keyword's look-back."
            },
            "stars": {
              "type": "integer",
              "description": "Its stars when the event was found."
            },
            "weeklyStars": {
              "type": [
                "integer",
                "null"
              ],
              "description": "Stars gained in the 7 days before the event; null when that week is not known yet."
            }
          },
          "required": [
            "name",
            "event",
            "stars",
            "weeklyStars"
          ],
          "description": "A GitHub repository event's facts, on a mention whose kind is repository; null on every other mention. The sentence is post.title."
        },
        "links": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Links the post carries, in the order written, at most 20. Empty for a post with none, and for posts ingested before September 2026."
        },
        "publishedAt": {
          "type": "string",
          "description": "When the post was published."
        },
        "engagement": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "likes": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "reposts": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "replies": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "quotes": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "views": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            },
            "bookmarks": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0
            }
          },
          "required": [
            "likes",
            "reposts",
            "replies",
            "quotes",
            "views",
            "bookmarks"
          ],
          "description": "Engagement counts as the platform reported them when the post was ingested, usually minutes after it was written; a count the platform does not have is null. Null as a whole for platforms that report none and for posts ingested before September 2026. X carries all six."
        },
        "replyTo": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "author": {
              "type": [
                "string",
                "null"
              ],
              "description": "Parent post author as the platform names them."
            },
            "url": {
              "type": [
                "string",
                "null"
              ],
              "description": "Parent post URL."
            },
            "text": {
              "type": [
                "string",
                "null"
              ],
              "description": "Parent post text, when the platform gave it."
            }
          },
          "required": [
            "author",
            "url",
            "text"
          ],
          "description": "The post or comment this one answers; null for top-level posts."
        }
      },
      "required": [
        "platform",
        "kind",
        "url",
        "text",
        "title",
        "imageUrl",
        "subreddit",
        "flair",
        "repository",
        "links",
        "publishedAt",
        "engagement",
        "replyTo"
      ]
    },
    "parentMentionId": {
      "type": [
        "string",
        "null"
      ],
      "description": "For a comment whose parent post or comment is itself one of your mentions: that mention's id (mm_...). Null otherwise."
    },
    "author": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "id": {
          "type": [
            "string",
            "null"
          ],
          "description": "Person id (aut_...) for GET /v1/people/{id}; null when the account is not in the audience yet."
        },
        "name": {
          "type": [
            "string",
            "null"
          ],
          "description": "Display name as the platform reports it."
        },
        "handle": {
          "type": [
            "string",
            "null"
          ],
          "description": "Platform handle derived from the profile URL, formatted as the platform shows it (@name, u/name); null where the platform has none."
        },
        "url": {
          "type": [
            "string",
            "null"
          ],
          "description": "Profile URL."
        },
        "avatarUrl": {
          "type": [
            "string",
            "null"
          ],
          "description": "Profile picture; null where the platform has none."
        },
        "followers": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Follower count as of their newest post; null where the platform has none."
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Your tags on this person: the workspace's, then those the mention's own keyword group gave them (set with groupId on /v1/people), each once."
        }
      },
      "required": [
        "id",
        "name",
        "handle",
        "url",
        "avatarUrl",
        "followers",
        "tags"
      ],
      "description": "Who posted it; null when the platform gave no author at all."
    },
    "review": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "rating": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5,
          "description": "Stars the reviewer gave."
        },
        "ratingMax": {
          "type": "integer",
          "description": "The top of the scale: 5 on both stores."
        },
        "title": {
          "type": [
            "string",
            "null"
          ],
          "description": "The review's headline; null where the store has none (Google Play)."
        },
        "version": {
          "type": [
            "string",
            "null"
          ],
          "description": "The app version the reviewer ran, when the store says."
        },
        "country": {
          "type": [
            "string",
            "null"
          ],
          "description": "The storefront it was read in (App Store, Google Play) or the reviewer's country (Trustpilot), a lowercase two-letter code; null where the platform gives none."
        },
        "verified": {
          "type": [
            "boolean",
            "null"
          ],
          "description": "The platform marks the review as verified (Trustpilot); null where the platform has no such mark."
        },
        "response": {
          "type": [
            "string",
            "null"
          ],
          "description": "The developer's reply as it stood when the review was collected; null for none."
        },
        "responseAt": {
          "type": [
            "string",
            "null"
          ],
          "description": "When the developer replied."
        },
        "app": {
          "type": "object",
          "properties": {
            "platform": {
              "type": "string",
              "enum": [
                "appstore",
                "googleplay",
                "trustpilot",
                "googlemaps"
              ],
              "description": "appstore (Apple App Store), googleplay (Google Play), trustpilot (a company's Trustpilot page) or googlemaps (a place's Google reviews)."
            },
            "id": {
              "type": "string",
              "description": "The store's app id."
            },
            "url": {
              "type": "string",
              "description": "The app's store listing."
            }
          },
          "required": [
            "platform",
            "id",
            "url"
          ],
          "description": "The app reviewed."
        }
      },
      "required": [
        "rating",
        "ratingMax",
        "title",
        "version",
        "country",
        "verified",
        "response",
        "responseAt",
        "app"
      ],
      "description": "An app store review's facts; null for every other post. Its sentiment comes from the stars (4 and 5 positive, 3 neutral, 1 and 2 negative) and it always counts as relevant, since you chose the app."
    },
    "classification": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "relevance": {
          "type": [
            "integer",
            "null"
          ],
          "minimum": 0,
          "maximum": 100,
          "description": "0 to 100; null only when classification failed."
        },
        "sentiment": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "positive",
            "neutral",
            "negative"
          ],
          "description": "Classifier sentiment."
        },
        "intents": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Intent and topic tags: buy_intent, question, complaint, praise, comparison, churn_intent (leaving or replacing the keyword), bug_report, pricing, hiring, event, promotional, testimonial (a customer vouching for it from their own use), industry_insight (analysis or data about the field), launch (a product or feature launch announcement), feedback (a suggestion or request about it)."
        },
        "automated": {
          "type": "boolean",
          "description": "The post reads as machine-made: a bot or app account, a scheduled or templated post, an obvious AI-written summary. A label only: automated mentions stay in the feed, are delivered as usual and are billed like any other match. false while unjudged."
        },
        "language": {
          "type": [
            "string",
            "null"
          ],
          "description": "The language the post is written in, as an ISO 639-1 code (en, es, de); null when unknown, not one of the 20 the classifier names, or classified before languages were recorded."
        },
        "country": {
          "type": [
            "string",
            "null"
          ],
          "description": "Where the author is, as a lowercase ISO 3166-1 alpha-2 code (us, in, de): the classifier's reading of the author's profile location and the post. A best guess, not a fact the platform gave; null when nothing tells, when it is not one of the 60 the classifier names, or when classified before countries were recorded."
        },
        "organization": {
          "type": "boolean",
          "description": "The author is a company, brand or organization account rather than a person: a LinkedIn company page, a GitHub organization, an account that speaks for a business. A label only, like automated. false while unjudged."
        },
        "confidence": {
          "type": [
            "number",
            "null"
          ],
          "minimum": 0,
          "maximum": 1,
          "description": "How sure the classifier is of its relevance verdict, 0 to 1. null when the verdict came without one: the fallback model judged, or the row was scored before confidence was recorded."
        },
        "uncertain": {
          "type": "boolean",
          "description": "The verdict deserves a human look: confidence under 0.4, or the model that wrote the note disagreed with the verdict. A flag for reviewers; it never hides a mention."
        },
        "note": {
          "type": [
            "string",
            "null"
          ],
          "description": "One sentence from the classifier explaining the score."
        },
        "failed": {
          "type": "boolean",
          "description": "true when the model could not score this post; it stays in the feed and is not billed."
        },
        "feedback": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "relevant": {
              "type": [
                "boolean",
                "null"
              ],
              "description": "Your verdict on relevance, or null when you only corrected the sentiment."
            },
            "sentiment": {
              "type": [
                "string",
                "null"
              ],
              "enum": [
                "positive",
                "neutral",
                "negative"
              ],
              "description": "Your corrected sentiment, or null when you only judged relevance."
            },
            "at": {
              "type": "string",
              "description": "When the last verdict was given."
            },
            "original": {
              "type": "object",
              "properties": {
                "relevance": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0,
                  "maximum": 100,
                  "description": "What the classifier scored before your verdict; null if it had not scored it."
                },
                "sentiment": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "positive",
                    "neutral",
                    "negative"
                  ],
                  "description": "The sentiment the classifier gave before your correction."
                }
              },
              "required": [
                "relevance",
                "sentiment"
              ],
              "description": "The classifier values your feedback replaced."
            }
          },
          "required": [
            "relevant",
            "sentiment",
            "at",
            "original"
          ],
          "description": "A person's correction of the verdict, or null. A relevance verdict sets `relevance` to 100 or 0 and `relevant` with it; a corrected sentiment replaces `sentiment`. Every list, filter, digest and report reads the corrected values."
        }
      },
      "required": [
        "relevance",
        "sentiment",
        "intents",
        "automated",
        "language",
        "country",
        "organization",
        "confidence",
        "uncertain",
        "note",
        "failed",
        "feedback"
      ],
      "description": "The classifier verdict, as corrected by your feedback; null while the post is still queued for classification."
    },
    "triage": {
      "type": "object",
      "properties": {
        "assignee": {
          "type": [
            "object",
            "null"
          ],
          "properties": {
            "id": {
              "type": "string"
            },
            "name": {
              "type": [
                "string",
                "null"
              ]
            },
            "email": {
              "type": [
                "string",
                "null"
              ]
            }
          },
          "required": [
            "id",
            "name",
            "email"
          ],
          "description": "Workspace member this mention is assigned to; null when unassigned."
        },
        "snoozedUntil": {
          "type": [
            "string",
            "null"
          ],
          "description": "Until when the mention stays out of the feed; null when not snoozed."
        },
        "note": {
          "type": [
            "string",
            "null"
          ],
          "description": "Internal note; null when none."
        }
      },
      "required": [
        "assignee",
        "snoozedUntil",
        "note"
      ]
    },
    "duplicateOf": {
      "type": [
        "string",
        "null"
      ],
      "description": "Set on a cross-post: the id of the mention this one copies (the same author posting the same text again for the same keyword within three days, like one announcement pasted into five subreddits). A copy is billed like any mention but is listed only under its original and never alerted on its own. null for an original."
    },
    "duplicates": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The copy's mention id (mm_...)."
          },
          "platform": {
            "type": "string",
            "enum": [
              "bluesky",
              "hackernews",
              "github",
              "stackoverflow",
              "devto",
              "reddit",
              "x",
              "youtube",
              "news",
              "linkedin",
              "tiktok",
              "instagram",
              "appstore",
              "googleplay",
              "trustpilot",
              "googlemaps",
              "rss"
            ],
            "description": "Platform: bluesky, hackernews, github, stackoverflow, devto, reddit, x, youtube, news, linkedin, tiktok, instagram, appstore (App Store reviews), googleplay (Google Play reviews), trustpilot (Trustpilot reviews), googlemaps (Google reviews of a place), rss (RSS and Atom feeds a keyword reads)."
          },
          "url": {
            "type": "string",
            "description": "Link to the copy."
          },
          "publishedAt": {
            "type": "string",
            "description": "When the copy was published."
          }
        },
        "required": [
          "id",
          "platform",
          "url",
          "publishedAt"
        ]
      },
      "description": "The cross-posts filed under this mention, oldest first: where else its author posted it. Empty when there are none, and on a copy."
    },
    "stats": {
      "type": "object",
      "properties": {
        "comments": {
          "type": "integer",
          "minimum": 0,
          "description": "Comments of this post delivered to you (GET /v1/mentions/{id}/comments); 0 until its thread is read, and for keywords without comments."
        }
      },
      "required": [
        "comments"
      ],
      "description": "Computed counts."
    },
    "createdAt": {
      "type": "string",
      "description": "When the match was recorded; the default feed order."
    }
  },
  "required": [
    "id",
    "status",
    "relevant",
    "delivered",
    "priority",
    "keyword",
    "post",
    "parentMentionId",
    "author",
    "review",
    "classification",
    "triage",
    "duplicateOf",
    "duplicates",
    "stats",
    "createdAt"
  ],
  "$defs": {
    "GroupRef": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Group id (grp_...)."
        },
        "name": {
          "type": "string",
          "description": "The group's name."
        },
        "externalId": {
          "type": [
            "string",
            "null"
          ],
          "description": "Your own id for the group, or null."
        },
        "isDefault": {
          "type": "boolean",
          "description": "The workspace's default group, where a keyword lands when no group is named."
        }
      },
      "required": [
        "id",
        "name",
        "externalId",
        "isDefault"
      ],
      "description": "The group the keyword belongs to."
    }
  }
}