Filtering and sorting posts¶
This guide covers all the filtering and ordering capabilities of
client.posts.list_in_community() and client.posts.iterate_in_community().
Ordering¶
from pathlib import Path
from pynteracta.auth import load_service_account_key
from pynteracta.client import InteractaClient
key = load_service_account_key(Path("sa.json"))
with InteractaClient(base_url="https://interacta.example.it", credentials=key) as client:
# Most recently modified first (default API behavior)
page = client.posts.list_in_community(
56,
order_by="postLastModifyAndCommentTimestamp",
order_desc=True,
)
# Alphabetical by title, ascending
page = client.posts.list_in_community(
56,
order_by="postTitle",
order_desc=False,
)
# Order by a custom datetime field
page = client.posts.list_in_community(
56,
order_by="postCustomField-1954",
order_desc=True,
pinned_first=True, # pinned posts always appear first
)
Allowed static order_by values:
| Value | Description |
|---|---|
postCustomId |
Custom/sequential post id |
postTitle |
Title |
postCreatorUser |
Creator user |
postCreationTimestamp |
Creation date |
postLastModifyUser |
Last modifier |
postLastModifyTimestamp |
Last modification date |
postLastModifyAndCommentTimestamp |
Last modification or comment date |
postViewedByMeTimestamp |
Last viewed by current user |
postModifiedByMeTimestamp |
Last modified by current user |
postCommentedByMeTimestamp |
Last commented by current user |
postScheduledPublication |
Scheduled publication date |
postRecency |
Recency score |
postCustomField-{id} |
Sort by custom field with given column id |
Passing an invalid value raises ValidationError immediately (client-side, no network call).
Common filters¶
All filter kwargs map to fields in communityPostFilters. They are all optional; omit any you
don't need.
from datetime import datetime, timezone
with InteractaClient(base_url="https://interacta.example.it", credentials=key) as client:
page = client.posts.list_in_community(
56,
# Text filters
title="Incident",
description="firewall",
contains_text="CVE-2025",
# Creator filters
created_by_user_ids=[101, 102],
created_by_group_ids=[37],
# Date range (accepts int epoch-ms, datetime, or ISO-8601 string)
creation_timestamp_from="2025-01-01T00:00:00+00:00",
creation_timestamp_to=datetime(2025, 6, 30, tzinfo=timezone.utc),
# Hashtags
hashtag_ids=[5, 12],
hashtags_logical_and=True, # require ALL hashtags (default: OR)
# Post type: 1=CUSTOM, 2=EVENTO, 3=QUESTIONARIO
post_types=[1],
# Workflow
current_workflow_status_ids=[3, 4],
# Visibility: 1=PUBLIC, 2=PRIVATE (check your tenant's enum)
visibility=1,
# Personal filters
followed_by_me=True,
mentioned=True,
to_manage=True,
only_pinned=True,
)
Date filter formats¶
The *_timestamp_from / *_timestamp_to kwargs accept three equivalent forms:
# epoch-milliseconds int
creation_timestamp_from=1735689600000
# datetime object (naive → UTC assumed)
from datetime import datetime, timezone
creation_timestamp_from=datetime(2025, 1, 1, tzinfo=timezone.utc)
# ISO-8601 string
creation_timestamp_from="2025-01-01T00:00:00+00:00"
Custom-field filters¶
Custom fields are filtered via post_field_filters (or screen_field_filters for workflow
screen fields). Each entry requires three values:
column_id— the field's numeric id (from the community's post-definition)type_id— the filter operator (seeFilterTypeenum)parameters— a list of values whose type depends ontype_id
FilterType values¶
FilterType |
int | parameters |
|---|---|---|
EQUAL |
1 | [value] |
INTERVAL |
2 | [from_epoch_ms, to_epoch_ms] |
LIKE |
3 | ["substring"] |
IN |
4 | [id1, id2, ...] |
CONTAINS |
5 | [value] |
IS_NULL_OR_IN |
6 | [id1, ...] |
IS_EMPTY |
7 | [] |
Field type → operator mapping (confirmed)¶
| Field type | Recommended FilterType |
|---|---|
| ENUM, ENUM_LIST, HIERARCHICAL_ENUM, GENERIC_ENTITY_LIST | IN |
| DATE, DATETIME | INTERVAL |
| STRING, TEXT_AREA, DELTA_AREA | LIKE |
Building filters by id¶
from pynteracta.models.facade.post_filters import FilterType, PostFieldFilter
with InteractaClient(base_url="https://interacta.example.it", credentials=key) as client:
page = client.posts.list_in_community(
56,
post_field_filters=[
# ENUM field "Tipologia" IN [226 "Manutenzione sistemistica"]
PostFieldFilter(column_id=1411, type_id=FilterType.IN, parameters=[226]),
# DATETIME field "Data e ora inizio" in a date range
PostFieldFilter(
column_id=1954,
type_id=FilterType.INTERVAL,
parameters=[1780264800000, 1780955999999],
),
# DELTA_AREA field "Causa" LIKE substring
PostFieldFilter(column_id=1957, type_id=FilterType.LIKE, parameters=["firewall"]),
],
)
Raw dicts are also accepted (both camelCase and snake_case keys):
Discovering fields: the post-definition¶
To find the column_id values for your community and the allowed enum parameters, fetch the
community's post-definition (already exposed in v0.1.0):
pd = client.communities.post_definition(56)
for fd in pd.field_definitions:
if not fd.searchable:
continue
print(f"{fd.id:5} {fd.type.name if fd.type else '?':20} {fd.label}")
for ev in fd.enum_values:
status = " [deleted]" if ev.deleted else ""
print(f" {ev.id:6} {ev.label}{status}")
Example output:
1411 ENUM Tipologia
226 Manutenzione sistemistica (aggiornamenti software, ecc..)
512 Modifica configurazioni (firewall, console amministrative..)
28 Generica
26 Progetto [deleted]
1954 DATETIME Data e ora inizio
1957 DELTA_AREA Causa
Building filters by label¶
PostFieldFilterBuilder resolves field externalId or label to column_id, and enum value
label to its numeric id, so you don't need to know the ids upfront.
from pynteracta.models.facade.post_filters import PostFieldFilterBuilder, FilterType
pd = client.communities.post_definition(56)
builder = PostFieldFilterBuilder(pd)
page = client.posts.list_in_community(
56,
post_field_filters=[
# By field externalId + enum value label
builder.build("assegnatario", [3872]), # externalId "assegnatario" = col 1415
builder.build("Tipologia", ["Generica"]), # label resolves to id 28
builder.build("Tipologia", ["Manutenzione sistemistica (aggiornamenti software, ecc..)"]),
# By field label + explicit type_id override
builder.build("Data e ora inizio",
[1780264800000, 1780955999999],
type_id=FilterType.INTERVAL),
# By numeric column_id (type inferred from field type)
builder.build(1957, ["firewall"]),
],
)
Resolution rules:
externalIdis preferred overlabel— use it when available (stable, unambiguous).- Deleted enum values are excluded by default. Pass
include_deleted=Trueto the builder constructor to include them. - Duplicate labels raise
ValidationError— use the numeric id directly in that case.
Opt-in validation¶
Pass validate_with= to validate custom-field filters against the post-definition before the
network call. If a column_id doesn't exist or a parameter id is not a valid enum value,
ValidationError is raised immediately (no API request is made).
pd = client.communities.post_definition(56)
# This raises ValidationError immediately if column_id 9999 isn't in the post-definition
page = client.posts.list_in_community(
56,
post_field_filters=[
PostFieldFilter(column_id=9999, type_id=FilterType.IN, parameters=[1]),
],
validate_with=pd,
)
What validate_with checks:
- Each
column_idexists in the community's field definitions. - For enum fields (ENUM / ENUM_LIST / HIERARCHICAL_ENUM), every
parametersid is a valid (non-deleted, by default) enum value. - The
type_idis compatible with the field's type for confirmed pairings (e.g., usingLIKEon an ENUM field raises an error). Unconfirmed field types are skipped (permissive).
The CLI equivalent is posts list --validate, which performs the post-definition lookup for you
and applies the same checks to --field-filter and --screen-field-filter (exit code 6 on
failure):
Escape hatches¶
Pre-built community_post_filters dict¶
For long-tail fields not promoted to explicit kwargs (e.g. eventPostFilter,
acknowledgeTaskFilter, draftType), pass a raw dict:
client.posts.list_in_community(
56,
community_post_filters={
"eventPostFilter": {"startDateFrom": 1780264800000},
"draftType": 1,
},
)
Explicit kwargs and community_post_filters are merged; explicit kwargs take precedence for
overlapping keys.
**filters passthrough (Python API)¶
Any additional keyword argument is camelCased and added to the top-level request body
(not to communityPostFilters). The only top-level field of
ListCommunityPostsFilteredRequestDTO without an explicit kwarg is communityAttachmentFilters,
a dict shaped like the swagger CommunityAttachmentFiltersDTO (name, mimeTypes,
mimeTypeCategory, types, createdByUserIds, creationTimestampFrom/To, …; the generated
model is an opaque stub, so the dict is forwarded as-is):
client.posts.list_in_community(
56,
community_attachment_filters={"mimeTypes": ["application/pdf"]},
)
Every other top-level field (pageToken, pageSize, calculateTotalItemsCount, orderBy,
orderDesc, pinnedFirst) already has an explicit kwarg.
CLI note:
--filter KEY=VALUEmaps tocommunity_post_filters, not to the top-level body.
list_in_community_raw()¶
Pass a fully pre-built ListCommunityPostsFilteredRequestDTO:
from pynteracta.models.facade.posts import ListCommunityPostsFilteredRequestDTO
req = ListCommunityPostsFilteredRequestDTO(
orderBy="postTitle",
pageSize=50,
)
client.posts.list_in_community_raw(56, req)
Pagination¶
# Single page
page = client.posts.list_in_community(56, order_by="postTitle", page_size=50)
for post in page.items_typed:
print(post.title)
# All pages lazily
for post in client.posts.iterate_in_community(
56,
order_by="postCreationTimestamp",
order_desc=False,
post_types=[1],
page_size=100,
):
print(post.title)
All kwargs accepted by list_in_community are also accepted by iterate_in_community.