Opt-in Filters
Opt-in filters are our ready-made filters. You add one to a feed, or a whole set at once, and remove it when you no longer want it.
- They follow our latest definition. An opt-in's condition is ours, and when we change it (a threshold, say), the change applies to every feed that has it, going forward: to new items, and to items already in the feed when they next change.
- You cannot edit them. A
PATCHof an opt-in filter is refused with403OPT_IN_NOT_EDITABLE. To use a different threshold, remove the opt-in and write your own filter with the condition you want. - On the feed, an opt-in is a filter like any other. It is listed with
type: "opt_in"and its current condition, and it counts in the include/exclude rule like your own filters: an opt-in include widens the feed, an opt-in exclude leaves out what it matches.
A new event feed starts with the completeness opt-in.
The catalog
| Key | Feed | Action | Name | Condition | Takes |
|---|---|---|---|---|---|
completeness | event | exclude | Completeness below 0.5 | completeness.score < 0.5 | nothing |
age_restricted | event | exclude | Age restricted | event_labels.age_restricted.confidence >= 0.8 | nothing |
promotional | event | exclude | Promotional | event_labels.promotional.confidence >= 0.95 | nothing |
not_an_occasion | event | exclude | Not an occasion | event_labels.not_an_occasion.confidence >= 0.9 | nothing |
in_area | event | include | In the area | the area part, and relevance.answer = "yes" when given | areaMatch (required), areaRelevance, relevance |
sponsored_or_advertorial | news | exclude | Sponsored or advertorial | news_content_type.sponsored_or_advertorial.significance >= 3 | nothing |
self_promotion | news | exclude | Self-promotion | news_content_type.self_promotion.significance >= 3 | nothing |
news | news | include | News | editorial_news.significance >= 6 or opinion_editorial.significance >= 6; and the area part, and relevance.answer = "yes", each when given | areaMatch, areaRelevance, relevance |
creator_posts | news | include | Creator posts | any of behind_the_scenes, daily_life, life_milestone, personal_interest, professional_update, fan_directed, celebrity_interaction at significance >= 5; and the area and relevance parts, each when given | areaMatch, areaRelevance, relevance |
The area part is areaMatch.match = "match", or, with areaRelevance,
any(areaMatch.match = "match", areaRelevance.answer = "yes"): an item is in
the area when it lies inside the area's boundaries, or the area relevance
processor judges it to be about the area. See Areas.
What each one leaves out or lets in:
completeness: events missing too much of what a listing needs.age_restricted: age-restricted events: 21+ and 18+ venues, bar crawls, gambling.promotional: "events" that are mainly a sale or brand activation.not_an_occasion: listings that are not an occasion people can attend: deals and specials, broadcasts, giveaways, permanent exhibits.in_area: events in the area. With relevance, the event must also be relevant.sponsored_or_advertorial: paid or sponsored placements.self_promotion: authors promoting their own work, product or event.news: editorial news and opinion pieces; with an area, only those in it; with relevance, only relevant ones.creator_posts: creators' posts about their lives and work; with an area, only those in it; with relevance, only relevant ones.
Parameters
Some opt-ins take your processors as parameters, by name, in with:
| Parameter | Takes |
|---|---|
areaMatch | An area_match processor: the area |
areaRelevance | An area_relevance processor, OR-ed with the area match. Needs areaMatch |
relevance | A classifier that must also say yes: a custom classifier, or an event_relevance / news_relevance processor with geographyDecidedSeparately: true |
Each must be one of your organization's processors, run on the feed's item
type and not be archived. A part of the condition that reads a parameter you
leave out is dropped: news with no areaMatch lets in news from anywhere.
Give the area relevance processor the same places as the area match (see
Areas).
A relevance processor given as relevance must have
geographyDecidedSeparately: true, or it would still judge geography from
the feed's description and the area would be decided twice.
Refusals name the parameter (with.<parameter>) in details.problems:
- A required processor left out, or
areaRelevancewithoutareaMatch:422MISSING_OPT_IN_PARAM. - A processor the opt-in cannot take (unknown, another organization's,
archived, the wrong template or item type, a relevance processor that
judges geography) or a parameter it does not take:
422INVALID_OPT_IN_PARAM.
Adding an opt-in
POST /feeds/{type}/{id}/filters
{
"optIn": "in_area",
"with": {
"areaMatch": "5c0e8f9a-3b1d-4f6e-9a2c-7d4b1e0f8a63",
"areaRelevance": "0a7d2c4e-9f1b-4e3a-8c6d-1b2e3f4a5c6d"
}
}
The response is the new filter (see Filters).
If the feed already has a filter that decides the same (same action and,
once generated, the same condition, whether yours or an opt-in), the request
is refused with 409 FILTER_ALREADY_PRESENT; details.equalTo is that
filter's id.
Sets
A set adds several opt-ins in one request:
| Key | Feed | Name | Members |
|---|---|---|---|
community_events | event | Community events | completeness, age_restricted, promotional, not_an_occasion, in_area |
standard_news | news | Standard news | sponsored_or_advertorial, self_promotion, news |
creator_social | news | Creator social | sponsored_or_advertorial, self_promotion, creator_posts |
POST /feeds/{type}/{id}/filter-sets/{setKey}
{
"with": {
"areaMatch": "5c0e8f9a-3b1d-4f6e-9a2c-7d4b1e0f8a63",
"areaRelevance": "0a7d2c4e-9f1b-4e3a-8c6d-1b2e3f4a5c6d"
}
}
setKey must be a set of the feed's type: a set of the other feed type (for
example standard_news on an event feed) is a 400 INVALID_PARAMS. Each
member gets the parameters it takes from with. Members the feed
already has a filter for (same action and condition, yours or an opt-in) are
skipped, and the response says which were added and which were skipped:
{
"success": true,
"data": {
"added": [
{
"id": "7f3c2b1a-6e5d-4c4b-9a3f-2e1d0c9b8a71",
"name": "In the area",
"action": "include",
"type": "opt_in",
"optIn": {
"key": "in_area",
"with": {
"areaMatch": "5c0e8f9a-3b1d-4f6e-9a2c-7d4b1e0f8a63",
"areaRelevance": "0a7d2c4e-9f1b-4e3a-8c6d-1b2e3f4a5c6d"
}
},
"condition": {
"any": [
{
"processor": "5c0e8f9a-3b1d-4f6e-9a2c-7d4b1e0f8a63",
"output": "match",
"op": "=",
"value": "match"
},
{
"processor": "0a7d2c4e-9f1b-4e3a-8c6d-1b2e3f4a5c6d",
"output": "answer",
"op": "=",
"value": "yes"
}
]
},
"createdAt": "2026-10-28T14:05:00.000Z",
"updatedAt": "2026-10-28T14:05:00.000Z"
}
],
"skipped": [
{
"optIn": "completeness",
"equalTo": "3e9a1c7b-2d4f-4a8e-b6c5-9f0e1d2c3b4a"
}
]
}
}
A set is added in one change: when a member's parameters are refused
(MISSING_OPT_IN_PARAM, INVALID_OPT_IN_PARAM), nothing is added. The feed
is not linked to the set afterwards: each member is an ordinary opt-in filter
you can remove on its own, and a later change to the set's members does not
reach your feed.
Reading the catalog
GET /opt-in-filters and GET /opt-in-filter-sets return the catalog and
the sets, for every API key. A catalog condition shows each parameter's
processor as a placeholder ({areaMatch}) and every optional part, as if
every parameter were given:
{
"key": "in_area",
"feedType": "event",
"action": "include",
"name": "In the area",
"description": "Includes events in the area: the area match finds them inside it, or the area relevance processor says yes. With relevance, the event must also be relevant.",
"parameters": [
{ "name": "areaMatch", "required": true, "processor": "area_match" },
{
"name": "areaRelevance",
"required": false,
"processor": "area_relevance"
},
{ "name": "relevance", "required": false, "processor": "classifier" }
],
"condition": {
"all": [
{
"any": [
{
"processor": "{areaMatch}",
"output": "match",
"op": "=",
"value": "match"
},
{
"processor": "{areaRelevance}",
"output": "answer",
"op": "=",
"value": "yes"
}
]
},
{
"processor": "{relevance}",
"output": "answer",
"op": "=",
"value": "yes"
}
]
}
}
{
"key": "community_events",
"feedType": "event",
"name": "Community events",
"members": [
"completeness",
"age_restricted",
"promotional",
"not_an_occasion",
"in_area"
]
}
Both lists come in { "success": true, "data": [ … ] }.