Skip to content

Posts

client.posts reads posts (detail, lists, comments, history, visibility) and writes custom posts (type 1), comments and workflow data, and event posts (type 2): create, edit, copy and the answer to the invitation (see Event posts).

Reading a post

client.posts.get(post_id) returns a Post with id, community_id, title, description_plain_text, creation_timestamp, last_modify_timestamp, comments_count, likes_count, draft (True for a draft, False once published) and publication_timestamp (publication time, epoch milliseconds, UTC). Fields the tenant does not send are None; everything else is on .raw.

Writing posts

Every write mirrors the read API: explicit snake_case keyword arguments for every field of the request DTO, a *_raw() variant for callers holding a pre-built DTO, and a facade over the server response. Only the fields you pass are sent, in camelCase. Each call sends one request: a timeout, a network error or a 409 is raised to the caller and never retried by the library.

from datetime import datetime
from zoneinfo import ZoneInfo

from pynteracta.client import InteractaClient
from pynteracta.exceptions import ConcurrencyError, ValidationError

with InteractaClient(base_url="https://tenant.example.com", credentials=...) as client:
    try:
        created = client.posts.create(
            79,
            title="Safety procedures Q4",
            description="New procedures in force from 1 January.",
            description_format=2,  # 2 = plain text, 1 = Quill delta
            custom_data={"1411": 226, "1413": True},
            watcher_user_ids=[1042],
            client_uid="safety-2026-q4",
            scheduled_publication=datetime(2026, 12, 31, 18, 0, tzinfo=ZoneInfo("Europe/Rome")),
        )
    except ValidationError as exc:
        print(exc.response_body)  # e.g. which custom field the server rejected
        raise
    print(created.post_id, created.next_occ_token, created.post.title)

    # Edit replaces the post: read it first, then send back every field that must survive.
    # References (catalog entries, users) are read as objects but written as ids.
    form = client.posts.get_for_edit(created.post_id)
    try:
        edited = client.posts.edit(
            created.post_id,
            form.occ_token,
            title="Safety procedures Q4 (rev. 2)",
            description=form.content_data.descriptionDelta,
            description_format=1,
            custom_data={"1411": 226, "1413": True, "2003": [89]},
            visibility=form.content_data.visibility,
        )
    except ConcurrencyError:
        # the post changed after we read it: re-read and decide — the library never retries
        raise

    client.posts.edit_watchers(created.post_id, add_user_ids=[1099])
    comment = client.posts.add_comment(created.post_id, comment="Read and approved", comment_format=2)

    copy_form = client.posts.get_for_copy(created.post_id)
    copied = client.posts.copy(created.post_id, copy_form.occ_token, title="Safety procedures Q1")

    client.posts.delete(copied.post_id)
Method Endpoint Returns
get_for_create(community_id) GET …/post-data-for-create/{communityId} PostForCreate
get_for_edit(post_id, load_attachments=None) GET …/post-data-for-edit/{postId} PostForEdit (with occ_token)
get_for_copy(post_id, load_attachments=None) GET …/post-data-for-copy/{postId} PostForCopy (with occ_token)
create(community_id, …) / create_raw POST …/create-post/{communityId} PostWriteResult
edit(post_id, occ_token, …) / edit_raw PUT …/edit-post/{postId}/{occToken} PostWriteResult
edit_custom_data(post_id, occ_token, …) / edit_custom_data_raw PUT …/edit-post-custom-data/{postId}/{occToken} PostWriteResult
copy(post_id, occ_token, …) / copy_raw PUT …/copy-post/{postId}/{occToken} PostWriteResult (the new post)
edit_watchers(post_id, add_user_ids, remove_user_ids) / edit_watchers_raw PUT …/edit-post-watchers/{postId} None
edit_attachments(post_id, add, update, remove_ids) / edit_attachments_raw PUT …/edit-post-attachments/{postId} PostAttachmentsWriteResult
delete(post_id) DELETE …/delete-post/{postId} the postId
mark_as_erasable(post_id) PUT …/mark-post-as-erasable/{postId} the server's postId (observed: 0)
add_comment(post_id, …) / add_comment_raw POST …/create-comment/{postId} PostComment
get_workflow_screen(post_id, operation_id=None) GET …/post-workflow-screen-data-for-edit/{postId} WorkflowScreen (with screen_occ_token)
execute_workflow_operation(post_id, operation_id, …) / _raw POST …/execute-post-workflow-operation/{postId}/{opId} WorkflowOperationResult
edit_workflow_screen(post_id, screen_occ_token, …) / _raw PUT …/edit-post-workflow-screen-data/{postId}/{token} WorkflowScreenWriteResult

All paths are under communication/posts/manage/.

Concurrency: occ_token

The post detail (get()) carries no concurrency token. edit(), edit_custom_data() and copy() take the occ_token read with get_for_edit() or get_for_copy(); the workflow screen has its own screen_occ_token, read with get_workflow_screen(). Every successful write returns the token for the next one (next_occ_token, next_screen_occ_token). If the post changed in the meantime the server answers 409, raised as ConcurrencyError: the library does not re-read and retry (ADR 0001). edit_watchers(), edit_attachments(), delete(), mark_as_erasable() and add_comment() need no token.

Custom fields and descriptions

custom_data is a dict keyed by custom-field id ({"1411": 226}), sent as is: the server validates it against the community's post definition, and a rejected value raises ValidationError with the server's detail in exc.response_body. description is sent in the format given by description_format: 1 = Quill delta (the server's default, and the format get_for_edit() returns in content_data.descriptionDelta), 2 = plain text. Comments work the same way with comment and comment_format.

Scheduled publication

scheduled_publication must be a timezone-aware datetime; a naive one raises ValueError before any request. With an IANA zone the local time and the zone name are sent ({"datetime": "2026-12-31T18:00:00", "timezone": "Europe/Rome"}); with a fixed offset the value is converted to UTC.

Attachments

attachments, add_attachments, update_attachments and edit_attachments() accept files just uploaded with client.attachments.upload() (an UploadedAttachment, sent as name + contentRef) and attachments the server already knows (attachmentId, or name + contentRef), as dicts or InputPostAttachmentDTO1 models. For a new version of an attachment pass uploaded.as_version_of(attachment_id) in update_attachments (or update). See Uploading files.

edit() and copy() are replacements

Fields you do not pass are not sent, and the server treats edit() as a replacement, not a patch: a missing description counts as empty, so an edit() with only a title fails with 400 REQUIRED_FIELD on description (verified against a tenant). Read the post with get_for_edit() (or get_for_copy() before a copy) and send back every field that must survive, as in the example above. copy() behaves the same way: the copy does not inherit the fields you omit, so send back the description, custom data and visibility read with get_for_copy(). description_format=2 (plain text) is accepted by edit() too. The CLI commands posts edit, posts edit-custom-data and posts copy do all this for you.

References are written as ids

Custom fields and workflow screen fields that point to catalog entries, users or groups are read as full objects ("2003": [{"id": 89, "catalogId": 12, "label": "3 - Bassa", …}]) but must be written as ids ("2003": [89]): sending the objects back fails with 400 INVALID_VALUE. Rich-text (delta) fields are written as Quill delta unless the request sets delta_area_format=2, which applies to every delta field of the request.

Workflow

client.posts.capabilities(post_id).workflow_permitted_operations lists the transitions the caller may execute (id, name, fromState, toState). A transition with a screen needs its data and token:

from pynteracta.client import InteractaClient

with InteractaClient(base_url="https://tenant.example.com", credentials=...) as client:
    caps = client.posts.capabilities(21269)
    operation = caps.workflow_permitted_operations[0]
    screen = client.posts.get_workflow_screen(21269, operation_id=operation.id)
    # screen.screen_data returns references as objects: write them back as ids
    result = client.posts.execute_workflow_operation(
        21269,
        operation.id,
        screen_data={"5233": [8341], "5237": [3872]},
        screen_occ_token=screen.screen_occ_token,
    )
    print(result.new_current_state.name, [op.name for op in result.new_permitted_operations])

A transition without a screen is executed with no arguments: the server accepts the empty body (verified against a tenant). edit_workflow_screen() changes the screen data of the current state, with the token read by get_workflow_screen(post_id); all the transitions of a post share that screen_occ_token. When the screen data of the current state are not editable (capabilities().can_edit_workflow_screen_data is False), get_workflow_screen(post_id) without operation_id raises PermissionError (403); the screen of a permitted transition can still be read with operation_id.

Delete and mark as erasable

delete() and mark_as_erasable() both make the post unreadable through the API (404 on every read afterwards). mark_as_erasable() also marks it for future physical erasure; its response carries postId: 0 on the tenants observed so far, and the method returns that value as is. The CLI reports the id you asked for.

Event posts

Event posts have their own create, edit and copy endpoints, a form read for each, and the answer to the invitation. The event block is built from flat keyword arguments: dates, time zone, all-day flag, location and invitees. The same rules as for custom posts apply: only the fields you pass are sent, one request per call, a 409 raised as ConcurrencyError and never retried. Watchers, attachments, delete, mark-as-erasable and comments of an event post use the methods above (edit_watchers(), edit_attachments(), delete(), …): the endpoints are the same for every post type.

from datetime import date, datetime
from zoneinfo import ZoneInfo

from pynteracta.client import InteractaClient
from pynteracta.models.facade import ParticipationAnswer

rome = ZoneInfo("Europe/Rome")

with InteractaClient(base_url="https://tenant.example.com", credentials=...) as client:
    created = client.posts.create_event(
        79,
        start_at=datetime(2026, 11, 5, 10, 0, tzinfo=rome),
        end_at=datetime(2026, 11, 5, 12, 0, tzinfo=rome),
        location="Room A",
        invited_user_ids=[1042],  # no invitation_type_id: guests
        title="Quarterly review",
        description="Agenda in the attachment.",
        description_format=2,
        client_uid="review-2026-q4",
    )

    form = client.posts.get_event_for_edit(created.post_id)
    event = form.event  # EventData, or None if the server returns no event block
    content = form.content_data
    print(form.occ_token, event.start_at, event.timezone, event.location, event.my_answer)

    # The server replaces the post: send back everything that must survive.
    client.posts.edit_event(
        created.post_id,
        form.occ_token,
        title=content.title,
        description=content.descriptionDelta,
        description_format=1,
        visibility=content.visibility,
        start_at=event.start_at,
        end_at=event.end_at,
        location="Room B",
        invited_user_ids=[1042],  # the form does not return the invitees
    )
    client.posts.participate(created.post_id, ParticipationAnswer.YES, notes="Arriving late")

    copy_form = client.posts.get_event_for_copy(created.post_id)
    copied = client.posts.copy_event(
        created.post_id,
        copy_form.occ_token,
        title="Quarterly review (Q1)",
        visibility=copy_form.content_data.visibility,
        start_at=datetime(2027, 2, 4, 10, 0, tzinfo=rome),
        end_at=datetime(2027, 2, 4, 12, 0, tzinfo=rome),
        location="Room A",
        invited_user_ids=[1042],
    )

    holiday = client.posts.create_event(
        79,
        start_at=date(2026, 12, 24),
        end_at=date(2026, 12, 26),
        all_day=True,  # dates only, no time zone
        location="Everywhere",
        invited_group_ids=[3],
        title="Office closed",
    )
Method Endpoint Returns
get_event_for_create(community_id) GET …/event-post-data-for-create/{communityId} EventPostForCreate
get_event_for_edit(post_id, load_attachments=None) GET …/event-post-data-for-edit/{postId} EventPostForEdit (with occ_token and event)
get_event_for_copy(post_id, load_attachments=None) GET …/event-post-data-for-copy/{postId} EventPostForCopy (with occ_token and event)
create_event(community_id, *, start_at, …) / create_event_raw POST …/create-event-post/{communityId} PostWriteResult
edit_event(post_id, occ_token, …) / edit_event_raw PUT …/edit-event-post/{postId}/{occToken} PostWriteResult
copy_event(post_id, occ_token, …) / copy_event_raw PUT …/copy-event-post/{postId}/{occToken} PostWriteResult (the new post)
participate(post_id, answer, notes=None) / participate_raw PUT …/post-event/{postId}/partecipate None

Dates and time zone

start_at (required by create_event()) and end_at are timezone-aware datetime objects; a naive one raises ValueError before any request. The library sends each date as a local date-time without offset ("startAt": {"localDatetime": "2026-11-05T10:00:00"}) plus the IANA name of the zone of start_at in event.timezone; end_at is converted into that zone. With a fixed offset (no IANA name) both are converted to UTC and "UTC" is sent. In edit_event() and copy_event(), where start_at is optional, the zone comes from end_at when start_at is missing. Without a time zone the server falls back to its own (Europe/Paris on the tested tenant).

All-day events take dates only: with all_day=True the dates are sent as "2026-11-05", with no timezone key, the only form the server accepts (a time or a time zone is rejected with 400). start_at and end_at can then be date objects, or datetime objects whose date is taken in their own zone; a plain date without all_day=True raises ValueError.

EventData.start_at and end_at are read in the event's IANA zone (localDatetime plus timezone), so passing them back to edit_event() keeps the event where it is; without a usable zone they come from zonedDatetime (a fixed offset). For all-day events they are date objects. They are None when nothing can be read.

Invitees and answers

invited_user_ids and invited_group_ids become event.invitations.users and .groups, as {"id": N} items; with invitation_type_id every item also gets "typeId" (0 guest, 2 collaborator). Without it the server treats the invitees as guests. The server requires invitees on create, edit and copy, and at least one guest among them: no invitees, or collaborators only, are rejected with 400 REQUIRED_FIELD event.inivations (the misspelling is the server's). Different types per invitee need the *_raw variant with a prebuilt DTO. send_edit_post_notifications=True notifies the invitees when the post is edited. EventData.invited_users and invited_groups list EventInvitee objects (id, name, type_id, .raw), but the tested tenant returns them empty in the forms: keep the invitee ids on your side and pass them again when you edit or copy.

participate() records the answer of the authenticated identity: the technical identity with a service account (accepted even when it is not invited), the linked user with Google OAuth2. answer is a ParticipationAnswer (YES = 1, MAYBE = 2, NO = 3) or its integer value; anything else raises ValueError before the request. notes is plain text, sent as a one-line Quill delta ([{"insert":"Arriving late\n"}]) because the server rejects plain text; participate_raw() sends a prebuilt delta as it is. EventData.my_answer is the answer already given, None if there is none. The server answers 404 (NotFoundError) for a post that does not exist or is not an event.

Cover image, watcher groups and pinning

cover_image_content_ref is the contentRef of an image uploaded with client.attachments.upload() (see Uploading files). watcher_group_ids (create) and add_watcher_group_ids / remove_watcher_group_ids (edit, copy) work like their user counterparts. pinned=None leaves the pin as it is. link_preview is sent as given, in the shape of LinkPreviewDTO.

Omitted fields in edit_event() and copy_event()

Only the fields you pass are sent, and inside event only the keys you pass, but the server treats edit and copy as a replacement of the post, as for custom posts:

  • event is required, and so are title, event.endAt, event.location and the invitees (400 REQUIRED_FIELD); create_event() requires event.endAt and event.location too;
  • without visibility the server answers 500 with no body;
  • an omitted description is cleared, an omitted event.timezone becomes the server's default.

So read the post with get_event_for_edit() (or get_event_for_copy()) and send back every field that must survive, as in the example above. The CLI commands posts edit-event and posts copy-event do this for you, except for the invitees. Write responses carry the post in postData without the event block: read the form again to see the event as saved.

API Reference

pynteracta.api.posts

Posts resource client.

PostsAPI

Bases: PostsWriteAPI, PostsEventAPI

Client for post detail, community listing, and comments endpoints.

Le scritture dei post custom, dei commenti e del workflow (spec 03) arrivano da :class:~pynteracta.api.posts_write.PostsWriteAPI; quelle dei post evento e la partecipazione (spec 08) da :class:~pynteracta.api.posts_event.PostsEventAPI.

Source code in src/pynteracta/api/posts.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
class PostsAPI(PostsWriteAPI, PostsEventAPI):
    """Client for post detail, community listing, and comments endpoints.

    Le scritture dei post custom, dei commenti e del workflow (spec 03) arrivano da
    :class:`~pynteracta.api.posts_write.PostsWriteAPI`; quelle dei post evento e la
    partecipazione (spec 08) da :class:`~pynteracta.api.posts_event.PostsEventAPI`.
    """

    def __init__(self, transport: HttpTransport) -> None:
        super().__init__(transport)

    def get(  # noqa: PLR0913
        self,
        post_id: int,
        *,
        load_main_attachment: bool = False,
        load_main_attachment_view_link: bool = False,
        load_main_attachment_download_link: bool = False,
        load_main_attachment_preview_image_link: bool = False,
        load_main_attachment_preview_image_animated_link: bool = False,
        load_main_attachment_preview_image_hi_res_link: bool = False,
        load_main_attachment_preview_image_hi_res_animated_link: bool = False,
    ) -> Post:
        """GET ``/communication/posts/data/post-detail-by-id/{postId}``."""
        path = _GET_POST_PATH.format(post_id=post_id)
        params = build_query_params(
            load_main_attachment=load_main_attachment,
            load_main_attachment_view_link=load_main_attachment_view_link,
            load_main_attachment_download_link=load_main_attachment_download_link,
            load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
            load_main_attachment_preview_image_animated_link=(
                load_main_attachment_preview_image_animated_link
            ),
            load_main_attachment_preview_image_hi_res_link=(
                load_main_attachment_preview_image_hi_res_link
            ),
            load_main_attachment_preview_image_hi_res_animated_link=(
                load_main_attachment_preview_image_hi_res_animated_link
            ),
        )
        return Post.from_dict(self._get(path, params=params or None))

    def list_in_community(  # noqa: PLR0912, PLR0913, PLR0915
        self,
        community_id: int,
        *,
        page_token: str | None = None,
        page_size: int | None = None,
        calculate_total_items_count: bool | None = None,
        load_post_details: bool = True,
        load_main_attachment: bool | None = None,
        load_main_attachment_view_link: bool | None = None,
        load_main_attachment_download_link: bool | None = None,
        load_main_attachment_preview_image_link: bool | None = None,
        load_main_attachment_preview_image_animated_link: bool | None = None,
        load_main_attachment_preview_image_hi_res_link: bool | None = None,
        load_main_attachment_preview_image_hi_res_animated_link: bool | None = None,
        load_capabilities: bool | None = None,
        # --- ordering ---
        order_by: str | None = None,
        order_desc: bool | None = None,
        pinned_first: bool | None = None,
        # --- communityPostFilters (curated subset) ---
        title: str | None = None,
        description: str | None = None,
        contains_text: str | None = None,
        created_by_user_ids: list[int] | None = None,
        created_by_group_ids: list[int] | None = None,
        creation_timestamp_from: int | float | str | None = None,
        creation_timestamp_to: int | float | str | None = None,
        modified_timestamp_from: int | float | str | None = None,
        modified_timestamp_to: int | float | str | None = None,
        hashtag_ids: list[int] | None = None,
        hashtags_logical_and: bool | None = None,
        post_types: list[int] | None = None,
        current_workflow_status_ids: list[int] | None = None,
        visibility: int | None = None,
        followed_by_me: bool | None = None,
        mentioned: bool | None = None,
        to_manage: bool | None = None,
        only_pinned: bool | None = None,
        post_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
        screen_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
        # --- opt-in validation ---
        validate_with: PostDefinition | None = None,
        # --- escape hatch ---
        community_post_filters: dict[str, Any] | None = None,
        **filters: Any,
    ) -> PostList:
        """POST ``/communication/posts/data/list/community/{communityId}``.

        Args:
            community_id: Target community.
            order_by: Sort field — one of :data:`POST_ORDER_FIELDS` or ``'postCustomField-{id}'``.
            order_desc: Descending sort (``True``) or ascending (``False``).
            pinned_first: Show pinned posts first.
            title: Filter on post title.
            description: Filter on post description.
            contains_text: Full-text filter on post content.
            created_by_user_ids: Filter by creator user ids.
            created_by_group_ids: Filter by creator group ids.
            creation_timestamp_from: Lower bound on creation date (epoch-ms, datetime, or ISO str).
            creation_timestamp_to: Upper bound on creation date.
            modified_timestamp_from: Lower bound on modification date.
            modified_timestamp_to: Upper bound on modification date.
            hashtag_ids: Filter by hashtag ids.
            hashtags_logical_and: Combine hashtag filters with AND (default OR).
            post_types: Filter by post type ids (1=CUSTOM, 2=EVENTO, 3=QUESTIONARIO).
            current_workflow_status_ids: Filter by workflow status ids.
            visibility: Filter by visibility (public/private).
            followed_by_me: Only posts followed by the current user.
            mentioned: Only posts where the current user was mentioned.
            to_manage: Only posts the current user has actions to take on.
            only_pinned: Only pinned posts.
            post_field_filters: Custom-field filters — list of :class:`PostFieldFilter` or dicts
                with keys ``column_id``/``columnId``, ``type_id``/``typeId``, ``parameters``.
            screen_field_filters: Workflow screen-field filters (same structure).
            validate_with: When supplied, validates ``post_field_filters`` and
                ``screen_field_filters`` against this community's post-definition before sending
                (no extra network call; raises :class:`~pynteracta.exceptions.ValidationError`).
            community_post_filters: Pre-built ``communityPostFilters`` dict — escape hatch for
                the long-tail fields not promoted to explicit kwargs.
            **filters: Additional camelCase fields forwarded to the request body (escape hatch).
        """
        if order_by is not None:
            _validate_order_by(order_by)

        # Coerce date kwargs to epoch-millis
        cf_from = to_epoch_millis(creation_timestamp_from)
        cf_to = to_epoch_millis(creation_timestamp_to)
        mf_from = to_epoch_millis(modified_timestamp_from)
        mf_to = to_epoch_millis(modified_timestamp_to)

        # Opt-in validation of field filters
        coerced_pff: list[PostFieldFilter] | None = None
        coerced_sff: list[PostFieldFilter] | None = None
        if post_field_filters is not None and validate_with is not None:
            coerced_pff = validate_field_filters(post_field_filters, validate_with)
        elif post_field_filters is not None:
            coerced_pff = [
                f if isinstance(f, PostFieldFilter) else PostFieldFilter.from_dict(f)
                for f in post_field_filters
            ]
        if screen_field_filters is not None and validate_with is not None:
            coerced_sff = validate_field_filters(screen_field_filters, validate_with, screen=True)
        elif screen_field_filters is not None:
            coerced_sff = [
                f if isinstance(f, PostFieldFilter) else PostFieldFilter.from_dict(f)
                for f in screen_field_filters
            ]

        # Build the complete communityPostFilters (SaaS-compatible: all fields present).
        # Priority: defaults → community_post_filters escape hatch → explicit kwargs.
        cpf: dict[str, Any] = dict(_DEFAULT_COMMUNITY_POST_FILTERS)
        if community_post_filters:
            cpf.update(community_post_filters)
        if title is not None:
            cpf["title"] = title
        if description is not None:
            cpf["description"] = description
        if contains_text is not None:
            cpf["containsText"] = contains_text
        if created_by_user_ids is not None:
            cpf["createdByUserIds"] = created_by_user_ids
        if created_by_group_ids is not None:
            cpf["createdByGroupIds"] = created_by_group_ids
        if cf_from is not None:
            cpf["creationTimestampFrom"] = cf_from
        if cf_to is not None:
            cpf["creationTimestampTo"] = cf_to
        if mf_from is not None:
            cpf["modifiedTimestampFrom"] = mf_from
        if mf_to is not None:
            cpf["modifiedTimestampTo"] = mf_to
        if hashtag_ids is not None:
            cpf["hashtagIds"] = hashtag_ids
        if hashtags_logical_and is not None:
            cpf["hashtagsLogicalAnd"] = hashtags_logical_and
        if post_types is not None:
            cpf["postTypes"] = post_types
        if current_workflow_status_ids is not None:
            cpf["currentWorkflowStatusIds"] = current_workflow_status_ids
        if visibility is not None:
            cpf["visibility"] = visibility
        if followed_by_me is not None:
            cpf["followedByMe"] = followed_by_me
        if mentioned is not None:
            cpf["mentioned"] = mentioned
        if to_manage is not None:
            cpf["toManage"] = to_manage
        if only_pinned is not None:
            cpf["onlyPinned"] = only_pinned
        if coerced_pff is not None:
            cpf["postFieldFilters"] = [f.to_dict() for f in coerced_pff]
        if coerced_sff is not None:
            cpf["screenFieldFilters"] = [f.to_dict() for f in coerced_sff]

        # Build the complete request body matching the SaaS payload structure.
        body: dict[str, Any] = {}
        if page_token is not None:
            body["pageToken"] = page_token
        if page_size is not None:
            body["pageSize"] = page_size
        if calculate_total_items_count is not None:
            body["calculateTotalItemsCount"] = calculate_total_items_count
        body["orderBy"] = order_by if order_by is not None else _DEFAULT_ORDER_BY
        body["orderDesc"] = order_desc if order_desc is not None else True
        body["communityPostFilters"] = cpf
        body["pinnedFirst"] = pinned_first if pinned_first is not None else True
        body["communityAttachmentFilters"] = dict(_DEFAULT_COMMUNITY_ATTACHMENT_FILTERS)
        for key, value in filters.items():
            if value is not None:
                body[snake_to_camel(key)] = value

        path = _LIST_COMMUNITY_PATH.format(community_id=community_id)
        params = build_query_params(
            load_post_details=load_post_details,
            load_main_attachment=load_main_attachment,
            load_main_attachment_view_link=load_main_attachment_view_link,
            load_main_attachment_download_link=load_main_attachment_download_link,
            load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
            load_main_attachment_preview_image_animated_link=(
                load_main_attachment_preview_image_animated_link
            ),
            load_main_attachment_preview_image_hi_res_link=(
                load_main_attachment_preview_image_hi_res_link
            ),
            load_main_attachment_preview_image_hi_res_animated_link=(
                load_main_attachment_preview_image_hi_res_animated_link
            ),
            load_capabilities=load_capabilities,
        )
        return PostList.from_dict(self._post(path, json=body, params=params))

    def list_in_community_raw(  # noqa: PLR0913
        self,
        community_id: int,
        req: ListCommunityPostsFilteredRequestDTO,
        *,
        load_post_details: bool = True,
        load_main_attachment: bool | None = None,
        load_main_attachment_view_link: bool | None = None,
        load_main_attachment_download_link: bool | None = None,
        load_main_attachment_preview_image_link: bool | None = None,
        load_main_attachment_preview_image_animated_link: bool | None = None,
        load_main_attachment_preview_image_hi_res_link: bool | None = None,
        load_main_attachment_preview_image_hi_res_animated_link: bool | None = None,
        load_capabilities: bool | None = None,
    ) -> PostList:
        """POST community post list with a pre-built request DTO (escape hatch)."""
        path = _LIST_COMMUNITY_PATH.format(community_id=community_id)
        params = build_query_params(
            load_post_details=load_post_details,
            load_main_attachment=load_main_attachment,
            load_main_attachment_view_link=load_main_attachment_view_link,
            load_main_attachment_download_link=load_main_attachment_download_link,
            load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
            load_main_attachment_preview_image_animated_link=(
                load_main_attachment_preview_image_animated_link
            ),
            load_main_attachment_preview_image_hi_res_link=(
                load_main_attachment_preview_image_hi_res_link
            ),
            load_main_attachment_preview_image_hi_res_animated_link=(
                load_main_attachment_preview_image_hi_res_animated_link
            ),
            load_capabilities=load_capabilities,
        )
        return PostList.from_dict(
            self._post(path, json=req.model_dump(mode="json", exclude_none=True), params=params)
        )

    def iterate_in_community(  # noqa: PLR0913
        self,
        community_id: int,
        *,
        page_size: int | None = None,
        order_by: str | None = None,
        order_desc: bool | None = None,
        pinned_first: bool | None = None,
        title: str | None = None,
        description: str | None = None,
        contains_text: str | None = None,
        created_by_user_ids: list[int] | None = None,
        created_by_group_ids: list[int] | None = None,
        creation_timestamp_from: int | float | str | None = None,
        creation_timestamp_to: int | float | str | None = None,
        modified_timestamp_from: int | float | str | None = None,
        modified_timestamp_to: int | float | str | None = None,
        hashtag_ids: list[int] | None = None,
        hashtags_logical_and: bool | None = None,
        post_types: list[int] | None = None,
        current_workflow_status_ids: list[int] | None = None,
        visibility: int | None = None,
        followed_by_me: bool | None = None,
        mentioned: bool | None = None,
        to_manage: bool | None = None,
        only_pinned: bool | None = None,
        post_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
        screen_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
        validate_with: PostDefinition | None = None,
        community_post_filters: dict[str, Any] | None = None,
        **filters: Any,
    ) -> PageIterator[generated.BaseListPostsElementDTOModel]:
        """Lazy iterator over all pages of :meth:`list_in_community`."""

        def fetch(page_token: str | None) -> PostList:
            return self.list_in_community(
                community_id,
                page_token=page_token,
                page_size=page_size,
                order_by=order_by,
                order_desc=order_desc,
                pinned_first=pinned_first,
                title=title,
                description=description,
                contains_text=contains_text,
                created_by_user_ids=created_by_user_ids,
                created_by_group_ids=created_by_group_ids,
                creation_timestamp_from=creation_timestamp_from,
                creation_timestamp_to=creation_timestamp_to,
                modified_timestamp_from=modified_timestamp_from,
                modified_timestamp_to=modified_timestamp_to,
                hashtag_ids=hashtag_ids,
                hashtags_logical_and=hashtags_logical_and,
                post_types=post_types,
                current_workflow_status_ids=current_workflow_status_ids,
                visibility=visibility,
                followed_by_me=followed_by_me,
                mentioned=mentioned,
                to_manage=to_manage,
                only_pinned=only_pinned,
                post_field_filters=post_field_filters,
                screen_field_filters=screen_field_filters,
                validate_with=validate_with,
                community_post_filters=community_post_filters,
                **filters,
            )

        return PageIterator(fetch, items_getter=lambda page: page.items_typed)

    def get_by_client_uid(  # noqa: PLR0913
        self,
        client_uid: str,
        *,
        load_main_attachment: bool = False,
        load_main_attachment_view_link: bool = False,
        load_main_attachment_download_link: bool = False,
        load_main_attachment_preview_image_link: bool = False,
        load_main_attachment_preview_image_animated_link: bool = False,
        load_main_attachment_preview_image_hi_res_link: bool = False,
        load_main_attachment_preview_image_hi_res_animated_link: bool = False,
    ) -> Post:
        """GET ``/communication/posts/data/post-detail-by-client-uid/{clientUid}``."""
        path = _GET_POST_BY_CLIENT_UID_PATH.format(client_uid=client_uid)
        params = build_query_params(
            load_main_attachment=load_main_attachment,
            load_main_attachment_view_link=load_main_attachment_view_link,
            load_main_attachment_download_link=load_main_attachment_download_link,
            load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
            load_main_attachment_preview_image_animated_link=(
                load_main_attachment_preview_image_animated_link
            ),
            load_main_attachment_preview_image_hi_res_link=(
                load_main_attachment_preview_image_hi_res_link
            ),
            load_main_attachment_preview_image_hi_res_animated_link=(
                load_main_attachment_preview_image_hi_res_animated_link
            ),
        )
        return Post.from_dict(self._get(path, params=params or None))

    def capabilities(self, post_id: int) -> PostCapabilities:
        """GET ``/communication/posts/data/post-capabilities/{postId}``."""
        path = _POST_CAPABILITIES_PATH.format(post_id=post_id)
        return PostCapabilities.from_dict(self._get(path))

    def history(
        self,
        post_id: int,
        *,
        page_token: str | None = None,
        page_size: int | None = None,
        calculate_total_items_count: bool | None = None,
        **filters: Any,
    ) -> PostHistoryEventList:
        """POST ``/communication/posts/data/history-list/{postId}``."""
        body = build_paginated_body(
            page_token=page_token,
            page_size=page_size,
            calculate_total_items_count=calculate_total_items_count,
            **filters,
        )
        req = ListPostHistoryEventsRequestDTO.model_validate(body)
        return self.history_raw(post_id, req)

    def history_raw(
        self, post_id: int, req: ListPostHistoryEventsRequestDTO
    ) -> PostHistoryEventList:
        """POST history with a pre-built request DTO (escape hatch)."""
        path = _HISTORY_LIST_PATH.format(post_id=post_id)
        return PostHistoryEventList.from_dict(
            self._post(path, json=req.model_dump(mode="json", exclude_none=True))
        )

    def iterate_history(
        self,
        post_id: int,
        *,
        page_size: int | None = None,
        **filters: Any,
    ) -> PageIterator[generated.PostActivityHistoryEventDTO1]:
        """Lazy iterator over all pages of :meth:`history`."""

        def fetch(page_token: str | None) -> PostHistoryEventList:
            return self.history(post_id, page_token=page_token, page_size=page_size, **filters)

        return PageIterator(fetch, items_getter=lambda page: page.items_typed)

    def global_stream(  # noqa: PLR0913
        self,
        *,
        sync_token: str | None = None,
        page_token: str | None = None,
        load_main_attachment: bool | None = None,
        load_main_attachment_view_link: bool | None = None,
        load_main_attachment_download_link: bool | None = None,
        load_main_attachment_preview_image_link: bool | None = None,
        load_main_attachment_preview_image_animated_link: bool | None = None,
        load_main_attachment_preview_image_hi_res_link: bool | None = None,
        load_main_attachment_preview_image_hi_res_animated_link: bool | None = None,
    ) -> GlobalPostStream:
        """POST ``/communication/posts/data/global-stream`` (filters via query params)."""
        params = build_query_params(
            sync_token=sync_token,
            page_token=page_token,
            load_main_attachment=load_main_attachment,
            load_main_attachment_view_link=load_main_attachment_view_link,
            load_main_attachment_download_link=load_main_attachment_download_link,
            load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
            load_main_attachment_preview_image_animated_link=(
                load_main_attachment_preview_image_animated_link
            ),
            load_main_attachment_preview_image_hi_res_link=(
                load_main_attachment_preview_image_hi_res_link
            ),
            load_main_attachment_preview_image_hi_res_animated_link=(
                load_main_attachment_preview_image_hi_res_animated_link
            ),
        )
        return GlobalPostStream.from_dict(
            self._post(_GLOBAL_STREAM_PATH, json={}, params=params or None)
        )

    def iterate_global_stream(
        self,
        *,
        sync_token: str | None = None,
        load_main_attachment: bool | None = None,
    ) -> PageIterator[generated.BasePostsStreamChunkElementDTOModel]:
        """Lazy iterator over all pages of :meth:`global_stream`."""

        def fetch(page_token: str | None) -> GlobalPostStream:
            return self.global_stream(
                sync_token=sync_token,
                page_token=page_token,
                load_main_attachment=load_main_attachment,
            )

        return PageIterator(fetch, items_getter=lambda page: page.items_typed)

    def community_list(
        self,
        community_id: int,
        *,
        page_token: str | None = None,
        page_size: int | None = None,
        calculate_total_items_count: bool | None = None,
        **filters: Any,
    ) -> PostList:
        """POST ``/communication/posts/data/community-list/{communityId}``.

        Lighter listing endpoint using :class:`ListCommunityPostsRequestDTO` (basic filters only).
        Distinct from ``list/community`` which uses the more fully-featured
        :class:`ListCommunityPostsFilteredRequestDTO`.
        """
        body = build_paginated_body(
            page_token=page_token,
            page_size=page_size,
            calculate_total_items_count=calculate_total_items_count,
            **filters,
        )
        req = ListCommunityPostsRequestDTO.model_validate(body)
        return self.community_list_raw(community_id, req)

    def community_list_raw(self, community_id: int, req: ListCommunityPostsRequestDTO) -> PostList:
        """POST community-list with a pre-built request DTO (escape hatch)."""
        path = _COMMUNITY_LIST_PATH.format(community_id=community_id)
        return PostList.from_dict(
            self._post(path, json=req.model_dump(mode="json", exclude_none=True))
        )

    def iterate_community_list(
        self,
        community_id: int,
        *,
        page_size: int | None = None,
        **filters: Any,
    ) -> PageIterator[generated.BaseListPostsElementDTOModel]:
        """Lazy iterator over all pages of :meth:`community_list`."""

        def fetch(page_token: str | None) -> PostList:
            return self.community_list(
                community_id, page_token=page_token, page_size=page_size, **filters
            )

        return PageIterator(fetch, items_getter=lambda page: page.items_typed)

    def check_visibility(self, post_ids: list[int]) -> VisibilityResult:
        """POST ``/communication/posts/data/check-visibility``."""
        req = CheckVisibilityRequestDTO(ids=post_ids)
        return self.check_visibility_raw(req)

    def check_visibility_raw(self, req: CheckVisibilityRequestDTO) -> VisibilityResult:
        """POST check-visibility with a pre-built request DTO (escape hatch)."""
        return VisibilityResult.from_dict(
            self._post(_CHECK_VISIBILITY_PATH, json=req.model_dump(mode="json", exclude_none=True))
        )

    def check_visibility_with_comments(self, post_ids: list[int]) -> VisibilityResult:
        """POST ``/communication/posts/data/check-visibility-with-comments``."""
        req = CheckVisibilityRequestDTO(ids=post_ids)
        return self.check_visibility_with_comments_raw(req)

    def check_visibility_with_comments_raw(
        self, req: CheckVisibilityRequestDTO
    ) -> VisibilityResult:
        """POST check-visibility-with-comments with a pre-built request DTO (escape hatch)."""
        return VisibilityResult.from_dict(
            self._post(
                _CHECK_VISIBILITY_WITH_COMMENTS_PATH,
                json=req.model_dump(mode="json", exclude_none=True),
            )
        )

    def comments(
        self,
        post_id: int,
        *,
        page_token: str | None = None,
        page_size: int | None = None,
        calculate_total_items_count: bool | None = None,
        **filters: Any,
    ) -> PostCommentList:
        """POST ``/communication/posts/data/comments-list/{postId}``."""
        body = build_paginated_body(
            page_token=page_token,
            page_size=page_size,
            calculate_total_items_count=calculate_total_items_count,
            **filters,
        )
        req = ListPostCommentsRequestDTO.model_validate(body)
        return self.comments_raw(post_id, req)

    def comments_raw(self, post_id: int, req: ListPostCommentsRequestDTO) -> PostCommentList:
        """POST post comments with a pre-built request DTO (escape hatch)."""
        path = _COMMENTS_PATH.format(post_id=post_id)
        return PostCommentList.from_dict(
            self._post(path, json=req.model_dump(mode="json", exclude_none=True))
        )

    def iterate_comments(
        self,
        post_id: int,
        *,
        page_size: int | None = None,
        **filters: Any,
    ) -> PageIterator[generated.PostCommentDTO1]:
        """Lazy iterator over all pages of :meth:`comments`."""

        def fetch(page_token: str | None) -> PostCommentList:
            return self.comments(post_id, page_token=page_token, page_size=page_size, **filters)

        return PageIterator(fetch, items_getter=lambda page: page.items_typed)

capabilities(post_id)

GET /communication/posts/data/post-capabilities/{postId}.

Source code in src/pynteracta/api/posts.py
def capabilities(self, post_id: int) -> PostCapabilities:
    """GET ``/communication/posts/data/post-capabilities/{postId}``."""
    path = _POST_CAPABILITIES_PATH.format(post_id=post_id)
    return PostCapabilities.from_dict(self._get(path))

check_visibility(post_ids)

POST /communication/posts/data/check-visibility.

Source code in src/pynteracta/api/posts.py
def check_visibility(self, post_ids: list[int]) -> VisibilityResult:
    """POST ``/communication/posts/data/check-visibility``."""
    req = CheckVisibilityRequestDTO(ids=post_ids)
    return self.check_visibility_raw(req)

check_visibility_raw(req)

POST check-visibility with a pre-built request DTO (escape hatch).

Source code in src/pynteracta/api/posts.py
def check_visibility_raw(self, req: CheckVisibilityRequestDTO) -> VisibilityResult:
    """POST check-visibility with a pre-built request DTO (escape hatch)."""
    return VisibilityResult.from_dict(
        self._post(_CHECK_VISIBILITY_PATH, json=req.model_dump(mode="json", exclude_none=True))
    )

check_visibility_with_comments(post_ids)

POST /communication/posts/data/check-visibility-with-comments.

Source code in src/pynteracta/api/posts.py
def check_visibility_with_comments(self, post_ids: list[int]) -> VisibilityResult:
    """POST ``/communication/posts/data/check-visibility-with-comments``."""
    req = CheckVisibilityRequestDTO(ids=post_ids)
    return self.check_visibility_with_comments_raw(req)

check_visibility_with_comments_raw(req)

POST check-visibility-with-comments with a pre-built request DTO (escape hatch).

Source code in src/pynteracta/api/posts.py
def check_visibility_with_comments_raw(
    self, req: CheckVisibilityRequestDTO
) -> VisibilityResult:
    """POST check-visibility-with-comments with a pre-built request DTO (escape hatch)."""
    return VisibilityResult.from_dict(
        self._post(
            _CHECK_VISIBILITY_WITH_COMMENTS_PATH,
            json=req.model_dump(mode="json", exclude_none=True),
        )
    )

comments(post_id, *, page_token=None, page_size=None, calculate_total_items_count=None, **filters)

POST /communication/posts/data/comments-list/{postId}.

Source code in src/pynteracta/api/posts.py
def comments(
    self,
    post_id: int,
    *,
    page_token: str | None = None,
    page_size: int | None = None,
    calculate_total_items_count: bool | None = None,
    **filters: Any,
) -> PostCommentList:
    """POST ``/communication/posts/data/comments-list/{postId}``."""
    body = build_paginated_body(
        page_token=page_token,
        page_size=page_size,
        calculate_total_items_count=calculate_total_items_count,
        **filters,
    )
    req = ListPostCommentsRequestDTO.model_validate(body)
    return self.comments_raw(post_id, req)

comments_raw(post_id, req)

POST post comments with a pre-built request DTO (escape hatch).

Source code in src/pynteracta/api/posts.py
def comments_raw(self, post_id: int, req: ListPostCommentsRequestDTO) -> PostCommentList:
    """POST post comments with a pre-built request DTO (escape hatch)."""
    path = _COMMENTS_PATH.format(post_id=post_id)
    return PostCommentList.from_dict(
        self._post(path, json=req.model_dump(mode="json", exclude_none=True))
    )

community_list(community_id, *, page_token=None, page_size=None, calculate_total_items_count=None, **filters)

POST /communication/posts/data/community-list/{communityId}.

Lighter listing endpoint using :class:ListCommunityPostsRequestDTO (basic filters only). Distinct from list/community which uses the more fully-featured :class:ListCommunityPostsFilteredRequestDTO.

Source code in src/pynteracta/api/posts.py
def community_list(
    self,
    community_id: int,
    *,
    page_token: str | None = None,
    page_size: int | None = None,
    calculate_total_items_count: bool | None = None,
    **filters: Any,
) -> PostList:
    """POST ``/communication/posts/data/community-list/{communityId}``.

    Lighter listing endpoint using :class:`ListCommunityPostsRequestDTO` (basic filters only).
    Distinct from ``list/community`` which uses the more fully-featured
    :class:`ListCommunityPostsFilteredRequestDTO`.
    """
    body = build_paginated_body(
        page_token=page_token,
        page_size=page_size,
        calculate_total_items_count=calculate_total_items_count,
        **filters,
    )
    req = ListCommunityPostsRequestDTO.model_validate(body)
    return self.community_list_raw(community_id, req)

community_list_raw(community_id, req)

POST community-list with a pre-built request DTO (escape hatch).

Source code in src/pynteracta/api/posts.py
def community_list_raw(self, community_id: int, req: ListCommunityPostsRequestDTO) -> PostList:
    """POST community-list with a pre-built request DTO (escape hatch)."""
    path = _COMMUNITY_LIST_PATH.format(community_id=community_id)
    return PostList.from_dict(
        self._post(path, json=req.model_dump(mode="json", exclude_none=True))
    )

get(post_id, *, load_main_attachment=False, load_main_attachment_view_link=False, load_main_attachment_download_link=False, load_main_attachment_preview_image_link=False, load_main_attachment_preview_image_animated_link=False, load_main_attachment_preview_image_hi_res_link=False, load_main_attachment_preview_image_hi_res_animated_link=False)

GET /communication/posts/data/post-detail-by-id/{postId}.

Source code in src/pynteracta/api/posts.py
def get(  # noqa: PLR0913
    self,
    post_id: int,
    *,
    load_main_attachment: bool = False,
    load_main_attachment_view_link: bool = False,
    load_main_attachment_download_link: bool = False,
    load_main_attachment_preview_image_link: bool = False,
    load_main_attachment_preview_image_animated_link: bool = False,
    load_main_attachment_preview_image_hi_res_link: bool = False,
    load_main_attachment_preview_image_hi_res_animated_link: bool = False,
) -> Post:
    """GET ``/communication/posts/data/post-detail-by-id/{postId}``."""
    path = _GET_POST_PATH.format(post_id=post_id)
    params = build_query_params(
        load_main_attachment=load_main_attachment,
        load_main_attachment_view_link=load_main_attachment_view_link,
        load_main_attachment_download_link=load_main_attachment_download_link,
        load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
        load_main_attachment_preview_image_animated_link=(
            load_main_attachment_preview_image_animated_link
        ),
        load_main_attachment_preview_image_hi_res_link=(
            load_main_attachment_preview_image_hi_res_link
        ),
        load_main_attachment_preview_image_hi_res_animated_link=(
            load_main_attachment_preview_image_hi_res_animated_link
        ),
    )
    return Post.from_dict(self._get(path, params=params or None))

get_by_client_uid(client_uid, *, load_main_attachment=False, load_main_attachment_view_link=False, load_main_attachment_download_link=False, load_main_attachment_preview_image_link=False, load_main_attachment_preview_image_animated_link=False, load_main_attachment_preview_image_hi_res_link=False, load_main_attachment_preview_image_hi_res_animated_link=False)

GET /communication/posts/data/post-detail-by-client-uid/{clientUid}.

Source code in src/pynteracta/api/posts.py
def get_by_client_uid(  # noqa: PLR0913
    self,
    client_uid: str,
    *,
    load_main_attachment: bool = False,
    load_main_attachment_view_link: bool = False,
    load_main_attachment_download_link: bool = False,
    load_main_attachment_preview_image_link: bool = False,
    load_main_attachment_preview_image_animated_link: bool = False,
    load_main_attachment_preview_image_hi_res_link: bool = False,
    load_main_attachment_preview_image_hi_res_animated_link: bool = False,
) -> Post:
    """GET ``/communication/posts/data/post-detail-by-client-uid/{clientUid}``."""
    path = _GET_POST_BY_CLIENT_UID_PATH.format(client_uid=client_uid)
    params = build_query_params(
        load_main_attachment=load_main_attachment,
        load_main_attachment_view_link=load_main_attachment_view_link,
        load_main_attachment_download_link=load_main_attachment_download_link,
        load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
        load_main_attachment_preview_image_animated_link=(
            load_main_attachment_preview_image_animated_link
        ),
        load_main_attachment_preview_image_hi_res_link=(
            load_main_attachment_preview_image_hi_res_link
        ),
        load_main_attachment_preview_image_hi_res_animated_link=(
            load_main_attachment_preview_image_hi_res_animated_link
        ),
    )
    return Post.from_dict(self._get(path, params=params or None))

global_stream(*, sync_token=None, page_token=None, load_main_attachment=None, load_main_attachment_view_link=None, load_main_attachment_download_link=None, load_main_attachment_preview_image_link=None, load_main_attachment_preview_image_animated_link=None, load_main_attachment_preview_image_hi_res_link=None, load_main_attachment_preview_image_hi_res_animated_link=None)

POST /communication/posts/data/global-stream (filters via query params).

Source code in src/pynteracta/api/posts.py
def global_stream(  # noqa: PLR0913
    self,
    *,
    sync_token: str | None = None,
    page_token: str | None = None,
    load_main_attachment: bool | None = None,
    load_main_attachment_view_link: bool | None = None,
    load_main_attachment_download_link: bool | None = None,
    load_main_attachment_preview_image_link: bool | None = None,
    load_main_attachment_preview_image_animated_link: bool | None = None,
    load_main_attachment_preview_image_hi_res_link: bool | None = None,
    load_main_attachment_preview_image_hi_res_animated_link: bool | None = None,
) -> GlobalPostStream:
    """POST ``/communication/posts/data/global-stream`` (filters via query params)."""
    params = build_query_params(
        sync_token=sync_token,
        page_token=page_token,
        load_main_attachment=load_main_attachment,
        load_main_attachment_view_link=load_main_attachment_view_link,
        load_main_attachment_download_link=load_main_attachment_download_link,
        load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
        load_main_attachment_preview_image_animated_link=(
            load_main_attachment_preview_image_animated_link
        ),
        load_main_attachment_preview_image_hi_res_link=(
            load_main_attachment_preview_image_hi_res_link
        ),
        load_main_attachment_preview_image_hi_res_animated_link=(
            load_main_attachment_preview_image_hi_res_animated_link
        ),
    )
    return GlobalPostStream.from_dict(
        self._post(_GLOBAL_STREAM_PATH, json={}, params=params or None)
    )

history(post_id, *, page_token=None, page_size=None, calculate_total_items_count=None, **filters)

POST /communication/posts/data/history-list/{postId}.

Source code in src/pynteracta/api/posts.py
def history(
    self,
    post_id: int,
    *,
    page_token: str | None = None,
    page_size: int | None = None,
    calculate_total_items_count: bool | None = None,
    **filters: Any,
) -> PostHistoryEventList:
    """POST ``/communication/posts/data/history-list/{postId}``."""
    body = build_paginated_body(
        page_token=page_token,
        page_size=page_size,
        calculate_total_items_count=calculate_total_items_count,
        **filters,
    )
    req = ListPostHistoryEventsRequestDTO.model_validate(body)
    return self.history_raw(post_id, req)

history_raw(post_id, req)

POST history with a pre-built request DTO (escape hatch).

Source code in src/pynteracta/api/posts.py
def history_raw(
    self, post_id: int, req: ListPostHistoryEventsRequestDTO
) -> PostHistoryEventList:
    """POST history with a pre-built request DTO (escape hatch)."""
    path = _HISTORY_LIST_PATH.format(post_id=post_id)
    return PostHistoryEventList.from_dict(
        self._post(path, json=req.model_dump(mode="json", exclude_none=True))
    )

iterate_comments(post_id, *, page_size=None, **filters)

Lazy iterator over all pages of :meth:comments.

Source code in src/pynteracta/api/posts.py
def iterate_comments(
    self,
    post_id: int,
    *,
    page_size: int | None = None,
    **filters: Any,
) -> PageIterator[generated.PostCommentDTO1]:
    """Lazy iterator over all pages of :meth:`comments`."""

    def fetch(page_token: str | None) -> PostCommentList:
        return self.comments(post_id, page_token=page_token, page_size=page_size, **filters)

    return PageIterator(fetch, items_getter=lambda page: page.items_typed)

iterate_community_list(community_id, *, page_size=None, **filters)

Lazy iterator over all pages of :meth:community_list.

Source code in src/pynteracta/api/posts.py
def iterate_community_list(
    self,
    community_id: int,
    *,
    page_size: int | None = None,
    **filters: Any,
) -> PageIterator[generated.BaseListPostsElementDTOModel]:
    """Lazy iterator over all pages of :meth:`community_list`."""

    def fetch(page_token: str | None) -> PostList:
        return self.community_list(
            community_id, page_token=page_token, page_size=page_size, **filters
        )

    return PageIterator(fetch, items_getter=lambda page: page.items_typed)

iterate_global_stream(*, sync_token=None, load_main_attachment=None)

Lazy iterator over all pages of :meth:global_stream.

Source code in src/pynteracta/api/posts.py
def iterate_global_stream(
    self,
    *,
    sync_token: str | None = None,
    load_main_attachment: bool | None = None,
) -> PageIterator[generated.BasePostsStreamChunkElementDTOModel]:
    """Lazy iterator over all pages of :meth:`global_stream`."""

    def fetch(page_token: str | None) -> GlobalPostStream:
        return self.global_stream(
            sync_token=sync_token,
            page_token=page_token,
            load_main_attachment=load_main_attachment,
        )

    return PageIterator(fetch, items_getter=lambda page: page.items_typed)

iterate_history(post_id, *, page_size=None, **filters)

Lazy iterator over all pages of :meth:history.

Source code in src/pynteracta/api/posts.py
def iterate_history(
    self,
    post_id: int,
    *,
    page_size: int | None = None,
    **filters: Any,
) -> PageIterator[generated.PostActivityHistoryEventDTO1]:
    """Lazy iterator over all pages of :meth:`history`."""

    def fetch(page_token: str | None) -> PostHistoryEventList:
        return self.history(post_id, page_token=page_token, page_size=page_size, **filters)

    return PageIterator(fetch, items_getter=lambda page: page.items_typed)

iterate_in_community(community_id, *, page_size=None, order_by=None, order_desc=None, pinned_first=None, title=None, description=None, contains_text=None, created_by_user_ids=None, created_by_group_ids=None, creation_timestamp_from=None, creation_timestamp_to=None, modified_timestamp_from=None, modified_timestamp_to=None, hashtag_ids=None, hashtags_logical_and=None, post_types=None, current_workflow_status_ids=None, visibility=None, followed_by_me=None, mentioned=None, to_manage=None, only_pinned=None, post_field_filters=None, screen_field_filters=None, validate_with=None, community_post_filters=None, **filters)

Lazy iterator over all pages of :meth:list_in_community.

Source code in src/pynteracta/api/posts.py
def iterate_in_community(  # noqa: PLR0913
    self,
    community_id: int,
    *,
    page_size: int | None = None,
    order_by: str | None = None,
    order_desc: bool | None = None,
    pinned_first: bool | None = None,
    title: str | None = None,
    description: str | None = None,
    contains_text: str | None = None,
    created_by_user_ids: list[int] | None = None,
    created_by_group_ids: list[int] | None = None,
    creation_timestamp_from: int | float | str | None = None,
    creation_timestamp_to: int | float | str | None = None,
    modified_timestamp_from: int | float | str | None = None,
    modified_timestamp_to: int | float | str | None = None,
    hashtag_ids: list[int] | None = None,
    hashtags_logical_and: bool | None = None,
    post_types: list[int] | None = None,
    current_workflow_status_ids: list[int] | None = None,
    visibility: int | None = None,
    followed_by_me: bool | None = None,
    mentioned: bool | None = None,
    to_manage: bool | None = None,
    only_pinned: bool | None = None,
    post_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
    screen_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
    validate_with: PostDefinition | None = None,
    community_post_filters: dict[str, Any] | None = None,
    **filters: Any,
) -> PageIterator[generated.BaseListPostsElementDTOModel]:
    """Lazy iterator over all pages of :meth:`list_in_community`."""

    def fetch(page_token: str | None) -> PostList:
        return self.list_in_community(
            community_id,
            page_token=page_token,
            page_size=page_size,
            order_by=order_by,
            order_desc=order_desc,
            pinned_first=pinned_first,
            title=title,
            description=description,
            contains_text=contains_text,
            created_by_user_ids=created_by_user_ids,
            created_by_group_ids=created_by_group_ids,
            creation_timestamp_from=creation_timestamp_from,
            creation_timestamp_to=creation_timestamp_to,
            modified_timestamp_from=modified_timestamp_from,
            modified_timestamp_to=modified_timestamp_to,
            hashtag_ids=hashtag_ids,
            hashtags_logical_and=hashtags_logical_and,
            post_types=post_types,
            current_workflow_status_ids=current_workflow_status_ids,
            visibility=visibility,
            followed_by_me=followed_by_me,
            mentioned=mentioned,
            to_manage=to_manage,
            only_pinned=only_pinned,
            post_field_filters=post_field_filters,
            screen_field_filters=screen_field_filters,
            validate_with=validate_with,
            community_post_filters=community_post_filters,
            **filters,
        )

    return PageIterator(fetch, items_getter=lambda page: page.items_typed)

list_in_community(community_id, *, page_token=None, page_size=None, calculate_total_items_count=None, load_post_details=True, load_main_attachment=None, load_main_attachment_view_link=None, load_main_attachment_download_link=None, load_main_attachment_preview_image_link=None, load_main_attachment_preview_image_animated_link=None, load_main_attachment_preview_image_hi_res_link=None, load_main_attachment_preview_image_hi_res_animated_link=None, load_capabilities=None, order_by=None, order_desc=None, pinned_first=None, title=None, description=None, contains_text=None, created_by_user_ids=None, created_by_group_ids=None, creation_timestamp_from=None, creation_timestamp_to=None, modified_timestamp_from=None, modified_timestamp_to=None, hashtag_ids=None, hashtags_logical_and=None, post_types=None, current_workflow_status_ids=None, visibility=None, followed_by_me=None, mentioned=None, to_manage=None, only_pinned=None, post_field_filters=None, screen_field_filters=None, validate_with=None, community_post_filters=None, **filters)

POST /communication/posts/data/list/community/{communityId}.

Parameters:

Name Type Description Default
community_id int

Target community.

required
order_by str | None

Sort field — one of :data:POST_ORDER_FIELDS or 'postCustomField-{id}'.

None
order_desc bool | None

Descending sort (True) or ascending (False).

None
pinned_first bool | None

Show pinned posts first.

None
title str | None

Filter on post title.

None
description str | None

Filter on post description.

None
contains_text str | None

Full-text filter on post content.

None
created_by_user_ids list[int] | None

Filter by creator user ids.

None
created_by_group_ids list[int] | None

Filter by creator group ids.

None
creation_timestamp_from int | float | str | None

Lower bound on creation date (epoch-ms, datetime, or ISO str).

None
creation_timestamp_to int | float | str | None

Upper bound on creation date.

None
modified_timestamp_from int | float | str | None

Lower bound on modification date.

None
modified_timestamp_to int | float | str | None

Upper bound on modification date.

None
hashtag_ids list[int] | None

Filter by hashtag ids.

None
hashtags_logical_and bool | None

Combine hashtag filters with AND (default OR).

None
post_types list[int] | None

Filter by post type ids (1=CUSTOM, 2=EVENTO, 3=QUESTIONARIO).

None
current_workflow_status_ids list[int] | None

Filter by workflow status ids.

None
visibility int | None

Filter by visibility (public/private).

None
followed_by_me bool | None

Only posts followed by the current user.

None
mentioned bool | None

Only posts where the current user was mentioned.

None
to_manage bool | None

Only posts the current user has actions to take on.

None
only_pinned bool | None

Only pinned posts.

None
post_field_filters list[PostFieldFilter | dict[str, Any]] | None

Custom-field filters — list of :class:PostFieldFilter or dicts with keys column_id/columnId, type_id/typeId, parameters.

None
screen_field_filters list[PostFieldFilter | dict[str, Any]] | None

Workflow screen-field filters (same structure).

None
validate_with PostDefinition | None

When supplied, validates post_field_filters and screen_field_filters against this community's post-definition before sending (no extra network call; raises :class:~pynteracta.exceptions.ValidationError).

None
community_post_filters dict[str, Any] | None

Pre-built communityPostFilters dict — escape hatch for the long-tail fields not promoted to explicit kwargs.

None
**filters Any

Additional camelCase fields forwarded to the request body (escape hatch).

{}
Source code in src/pynteracta/api/posts.py
def list_in_community(  # noqa: PLR0912, PLR0913, PLR0915
    self,
    community_id: int,
    *,
    page_token: str | None = None,
    page_size: int | None = None,
    calculate_total_items_count: bool | None = None,
    load_post_details: bool = True,
    load_main_attachment: bool | None = None,
    load_main_attachment_view_link: bool | None = None,
    load_main_attachment_download_link: bool | None = None,
    load_main_attachment_preview_image_link: bool | None = None,
    load_main_attachment_preview_image_animated_link: bool | None = None,
    load_main_attachment_preview_image_hi_res_link: bool | None = None,
    load_main_attachment_preview_image_hi_res_animated_link: bool | None = None,
    load_capabilities: bool | None = None,
    # --- ordering ---
    order_by: str | None = None,
    order_desc: bool | None = None,
    pinned_first: bool | None = None,
    # --- communityPostFilters (curated subset) ---
    title: str | None = None,
    description: str | None = None,
    contains_text: str | None = None,
    created_by_user_ids: list[int] | None = None,
    created_by_group_ids: list[int] | None = None,
    creation_timestamp_from: int | float | str | None = None,
    creation_timestamp_to: int | float | str | None = None,
    modified_timestamp_from: int | float | str | None = None,
    modified_timestamp_to: int | float | str | None = None,
    hashtag_ids: list[int] | None = None,
    hashtags_logical_and: bool | None = None,
    post_types: list[int] | None = None,
    current_workflow_status_ids: list[int] | None = None,
    visibility: int | None = None,
    followed_by_me: bool | None = None,
    mentioned: bool | None = None,
    to_manage: bool | None = None,
    only_pinned: bool | None = None,
    post_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
    screen_field_filters: list[PostFieldFilter | dict[str, Any]] | None = None,
    # --- opt-in validation ---
    validate_with: PostDefinition | None = None,
    # --- escape hatch ---
    community_post_filters: dict[str, Any] | None = None,
    **filters: Any,
) -> PostList:
    """POST ``/communication/posts/data/list/community/{communityId}``.

    Args:
        community_id: Target community.
        order_by: Sort field — one of :data:`POST_ORDER_FIELDS` or ``'postCustomField-{id}'``.
        order_desc: Descending sort (``True``) or ascending (``False``).
        pinned_first: Show pinned posts first.
        title: Filter on post title.
        description: Filter on post description.
        contains_text: Full-text filter on post content.
        created_by_user_ids: Filter by creator user ids.
        created_by_group_ids: Filter by creator group ids.
        creation_timestamp_from: Lower bound on creation date (epoch-ms, datetime, or ISO str).
        creation_timestamp_to: Upper bound on creation date.
        modified_timestamp_from: Lower bound on modification date.
        modified_timestamp_to: Upper bound on modification date.
        hashtag_ids: Filter by hashtag ids.
        hashtags_logical_and: Combine hashtag filters with AND (default OR).
        post_types: Filter by post type ids (1=CUSTOM, 2=EVENTO, 3=QUESTIONARIO).
        current_workflow_status_ids: Filter by workflow status ids.
        visibility: Filter by visibility (public/private).
        followed_by_me: Only posts followed by the current user.
        mentioned: Only posts where the current user was mentioned.
        to_manage: Only posts the current user has actions to take on.
        only_pinned: Only pinned posts.
        post_field_filters: Custom-field filters — list of :class:`PostFieldFilter` or dicts
            with keys ``column_id``/``columnId``, ``type_id``/``typeId``, ``parameters``.
        screen_field_filters: Workflow screen-field filters (same structure).
        validate_with: When supplied, validates ``post_field_filters`` and
            ``screen_field_filters`` against this community's post-definition before sending
            (no extra network call; raises :class:`~pynteracta.exceptions.ValidationError`).
        community_post_filters: Pre-built ``communityPostFilters`` dict — escape hatch for
            the long-tail fields not promoted to explicit kwargs.
        **filters: Additional camelCase fields forwarded to the request body (escape hatch).
    """
    if order_by is not None:
        _validate_order_by(order_by)

    # Coerce date kwargs to epoch-millis
    cf_from = to_epoch_millis(creation_timestamp_from)
    cf_to = to_epoch_millis(creation_timestamp_to)
    mf_from = to_epoch_millis(modified_timestamp_from)
    mf_to = to_epoch_millis(modified_timestamp_to)

    # Opt-in validation of field filters
    coerced_pff: list[PostFieldFilter] | None = None
    coerced_sff: list[PostFieldFilter] | None = None
    if post_field_filters is not None and validate_with is not None:
        coerced_pff = validate_field_filters(post_field_filters, validate_with)
    elif post_field_filters is not None:
        coerced_pff = [
            f if isinstance(f, PostFieldFilter) else PostFieldFilter.from_dict(f)
            for f in post_field_filters
        ]
    if screen_field_filters is not None and validate_with is not None:
        coerced_sff = validate_field_filters(screen_field_filters, validate_with, screen=True)
    elif screen_field_filters is not None:
        coerced_sff = [
            f if isinstance(f, PostFieldFilter) else PostFieldFilter.from_dict(f)
            for f in screen_field_filters
        ]

    # Build the complete communityPostFilters (SaaS-compatible: all fields present).
    # Priority: defaults → community_post_filters escape hatch → explicit kwargs.
    cpf: dict[str, Any] = dict(_DEFAULT_COMMUNITY_POST_FILTERS)
    if community_post_filters:
        cpf.update(community_post_filters)
    if title is not None:
        cpf["title"] = title
    if description is not None:
        cpf["description"] = description
    if contains_text is not None:
        cpf["containsText"] = contains_text
    if created_by_user_ids is not None:
        cpf["createdByUserIds"] = created_by_user_ids
    if created_by_group_ids is not None:
        cpf["createdByGroupIds"] = created_by_group_ids
    if cf_from is not None:
        cpf["creationTimestampFrom"] = cf_from
    if cf_to is not None:
        cpf["creationTimestampTo"] = cf_to
    if mf_from is not None:
        cpf["modifiedTimestampFrom"] = mf_from
    if mf_to is not None:
        cpf["modifiedTimestampTo"] = mf_to
    if hashtag_ids is not None:
        cpf["hashtagIds"] = hashtag_ids
    if hashtags_logical_and is not None:
        cpf["hashtagsLogicalAnd"] = hashtags_logical_and
    if post_types is not None:
        cpf["postTypes"] = post_types
    if current_workflow_status_ids is not None:
        cpf["currentWorkflowStatusIds"] = current_workflow_status_ids
    if visibility is not None:
        cpf["visibility"] = visibility
    if followed_by_me is not None:
        cpf["followedByMe"] = followed_by_me
    if mentioned is not None:
        cpf["mentioned"] = mentioned
    if to_manage is not None:
        cpf["toManage"] = to_manage
    if only_pinned is not None:
        cpf["onlyPinned"] = only_pinned
    if coerced_pff is not None:
        cpf["postFieldFilters"] = [f.to_dict() for f in coerced_pff]
    if coerced_sff is not None:
        cpf["screenFieldFilters"] = [f.to_dict() for f in coerced_sff]

    # Build the complete request body matching the SaaS payload structure.
    body: dict[str, Any] = {}
    if page_token is not None:
        body["pageToken"] = page_token
    if page_size is not None:
        body["pageSize"] = page_size
    if calculate_total_items_count is not None:
        body["calculateTotalItemsCount"] = calculate_total_items_count
    body["orderBy"] = order_by if order_by is not None else _DEFAULT_ORDER_BY
    body["orderDesc"] = order_desc if order_desc is not None else True
    body["communityPostFilters"] = cpf
    body["pinnedFirst"] = pinned_first if pinned_first is not None else True
    body["communityAttachmentFilters"] = dict(_DEFAULT_COMMUNITY_ATTACHMENT_FILTERS)
    for key, value in filters.items():
        if value is not None:
            body[snake_to_camel(key)] = value

    path = _LIST_COMMUNITY_PATH.format(community_id=community_id)
    params = build_query_params(
        load_post_details=load_post_details,
        load_main_attachment=load_main_attachment,
        load_main_attachment_view_link=load_main_attachment_view_link,
        load_main_attachment_download_link=load_main_attachment_download_link,
        load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
        load_main_attachment_preview_image_animated_link=(
            load_main_attachment_preview_image_animated_link
        ),
        load_main_attachment_preview_image_hi_res_link=(
            load_main_attachment_preview_image_hi_res_link
        ),
        load_main_attachment_preview_image_hi_res_animated_link=(
            load_main_attachment_preview_image_hi_res_animated_link
        ),
        load_capabilities=load_capabilities,
    )
    return PostList.from_dict(self._post(path, json=body, params=params))

list_in_community_raw(community_id, req, *, load_post_details=True, load_main_attachment=None, load_main_attachment_view_link=None, load_main_attachment_download_link=None, load_main_attachment_preview_image_link=None, load_main_attachment_preview_image_animated_link=None, load_main_attachment_preview_image_hi_res_link=None, load_main_attachment_preview_image_hi_res_animated_link=None, load_capabilities=None)

POST community post list with a pre-built request DTO (escape hatch).

Source code in src/pynteracta/api/posts.py
def list_in_community_raw(  # noqa: PLR0913
    self,
    community_id: int,
    req: ListCommunityPostsFilteredRequestDTO,
    *,
    load_post_details: bool = True,
    load_main_attachment: bool | None = None,
    load_main_attachment_view_link: bool | None = None,
    load_main_attachment_download_link: bool | None = None,
    load_main_attachment_preview_image_link: bool | None = None,
    load_main_attachment_preview_image_animated_link: bool | None = None,
    load_main_attachment_preview_image_hi_res_link: bool | None = None,
    load_main_attachment_preview_image_hi_res_animated_link: bool | None = None,
    load_capabilities: bool | None = None,
) -> PostList:
    """POST community post list with a pre-built request DTO (escape hatch)."""
    path = _LIST_COMMUNITY_PATH.format(community_id=community_id)
    params = build_query_params(
        load_post_details=load_post_details,
        load_main_attachment=load_main_attachment,
        load_main_attachment_view_link=load_main_attachment_view_link,
        load_main_attachment_download_link=load_main_attachment_download_link,
        load_main_attachment_preview_image_link=load_main_attachment_preview_image_link,
        load_main_attachment_preview_image_animated_link=(
            load_main_attachment_preview_image_animated_link
        ),
        load_main_attachment_preview_image_hi_res_link=(
            load_main_attachment_preview_image_hi_res_link
        ),
        load_main_attachment_preview_image_hi_res_animated_link=(
            load_main_attachment_preview_image_hi_res_animated_link
        ),
        load_capabilities=load_capabilities,
    )
    return PostList.from_dict(
        self._post(path, json=req.model_dump(mode="json", exclude_none=True), params=params)
    )

pynteracta.api.posts_write.PostsWriteAPI

Bases: ResourceClient

Scritture dei post custom, commenti e workflow, con le letture propedeutiche.

add_comment(post_id, *, comment=None, comment_format=None, client_uid=None, attachments=None, parent_comment_id=None)

POST /communication/posts/manage/create-comment/{postId}.

Parameters:

Name Type Description Default
post_id int

Il post da commentare.

required
comment str | None

Testo, nel formato di comment_format.

None
comment_format int | None

1 = Quill delta (default del server), 2 = testo semplice.

None
client_uid str | None

Identificativo scelto dal chiamante.

None
attachments WriteItems

Allegati: UploadedAttachment o InputPostCommentAttachmentDTO.

None
parent_comment_id int | None

Commento a cui si risponde.

None

Returns:

Type Description
PostComment

Il commento creato (:class:PostComment).

add_comment_raw(post_id, req)

Come :meth:add_comment, da un CreatePostCommentRequestDTO.

copy(post_id, occ_token, *, title=None, description=None, description_format=None, custom_data=None, delta_area_format=None, add_attachments=None, update_attachments=None, remove_attachment_ids=None, add_watcher_user_ids=None, remove_watcher_user_ids=None, visibility=None, workflow_init_state_id=None, draft=None, scheduled_publication=None, announcement=None)

PUT /communication/posts/manage/copy-post/{postId}/{occToken}.

Crea un post nuovo copiando post_id; occ_token è quello letto con :meth:get_for_copy. Gli argomenti sono quelli di :meth:edit più announcement.

Returns:

Name Type Description
Un PostWriteResult

class:PostWriteResult con il post_id del post nuovo.

copy_raw(post_id, occ_token, req)

Come :meth:copy, da un CopyCustomPostRequestDTO già costruito.

create(community_id, *, announcement=False, title=None, description=None, description_format=None, custom_data=None, delta_area_format=None, attachments=None, watcher_user_ids=None, workflow_init_state_id=None, visibility=None, client_uid=None, draft=None, scheduled_publication=None)

POST /communication/posts/manage/create-post/{communityId}.

Il corpo contiene announcement (l'unico campo obbligatorio del DTO) e i soli altri campi passati. custom_data è inviato così com'è: lo valida il server, e un errore arriva come :class:~pynteracta.exceptions.ValidationError con il body in response_body.

Parameters:

Name Type Description Default
community_id int

La community in cui creare il post.

required
announcement bool

Post marcato come annuncio.

False
title str | None

Titolo.

None
description str | None

Descrizione, nel formato di description_format.

None
description_format int | None

1 = Quill delta (default del server), 2 = testo semplice.

None
custom_data dict[str, Any] | None

Campi custom, per id del campo (per esempio {"1411": 226}).

None
delta_area_format int | None

Formato dei campi custom di tipo delta (1 delta, 2 testo).

None
attachments WriteItems

Allegati: :class:~pynteracta.models.facade.attachments.UploadedAttachment appena caricati con client.attachments.upload, oppure riferimenti già noti al server nella forma di InputPostAttachmentDTO (dict o modello).

None
watcher_user_ids list[int] | None

Utenti osservatori.

None
workflow_init_state_id int | None

Stato iniziale del workflow, se la community lo permette.

None
visibility int | None

1 privato, 2 pubblico.

None
client_uid str | None

Identificativo scelto dal chiamante, per ritrovare il post con get_by_client_uid dopo un esito incerto.

None
draft bool | None

Creazione in bozza.

None
scheduled_publication datetime | None

Pubblicazione programmata, datetime con fuso.

None

Returns:

Name Type Description
Un PostWriteResult

class:PostWriteResult con post_id, next_occ_token e post.

create_raw(community_id, req)

Come :meth:create, da un CreateCustomPostRequest già costruito.

delete(post_id)

DELETE /communication/posts/manage/delete-post/{postId}.

Returns:

Type Description
int | None

Il postId della risposta.

edit(post_id, occ_token, *, title=None, description=None, description_format=None, custom_data=None, delta_area_format=None, add_attachments=None, update_attachments=None, remove_attachment_ids=None, add_watcher_user_ids=None, remove_watcher_user_ids=None, visibility=None, workflow_init_state_id=None, draft=None, scheduled_publication=None)

PUT /communication/posts/manage/edit-post/{postId}/{occToken}.

occ_token è quello letto con :meth:get_for_edit: se il post è cambiato nel frattempo il server risponde 409 (:class:~pynteracta.exceptions.ConcurrencyError) e la libreria non rilegge né riprova. Il corpo contiene solo i campi passati; l'effetto sui campi omessi lo decide il server (vedi la documentazione).

Parameters:

Name Type Description Default
post_id int

Il post da modificare.

required
occ_token int

Token di concorrenza ottimistica letto.

required
title str | None

Titolo.

None
description str | None

Descrizione, nel formato di description_format.

None
description_format int | None

1 = Quill delta, 2 = testo semplice.

None
custom_data dict[str, Any] | None

Campi custom, per id del campo.

None
delta_area_format int | None

Formato dei campi custom di tipo delta.

None
add_attachments WriteItems

Allegati da aggiungere: UploadedAttachment o InputPostAttachmentDTO.

None
update_attachments WriteItems

Allegati da aggiornare (con contentRef = nuova versione, per esempio uploaded.as_version_of(attachment_id)).

None
remove_attachment_ids list[int] | None

Allegati da togliere.

None
add_watcher_user_ids list[int] | None

Utenti osservatori da aggiungere.

None
remove_watcher_user_ids list[int] | None

Utenti osservatori da togliere.

None
visibility int | None

1 privato, 2 pubblico.

None
workflow_init_state_id int | None

Stato iniziale del workflow.

None
draft bool | None

Bozza o pubblicato.

None
scheduled_publication datetime | None

Pubblicazione programmata, datetime con fuso.

None

Returns:

Name Type Description
Un PostWriteResult

class:PostWriteResult; next_occ_token è il token per la modifica

PostWriteResult

successiva.

edit_attachments(post_id, *, add=None, update=None, remove_ids=None)

PUT /communication/posts/manage/edit-post-attachments/{postId}.

Accetta allegati appena caricati (:class:~pynteracta.models.facade.attachments.UploadedAttachment, da client.attachments.upload) e riferimenti già noti al server (attachmentId, oppure name + contentRef).

Parameters:

Name Type Description Default
post_id int

Il post.

required
add WriteItems

Allegati da aggiungere: UploadedAttachment o InputPostAttachmentDTO.

None
update WriteItems

Allegati da aggiornare (con contentRef = nuova versione, per esempio uploaded.as_version_of(attachment_id)).

None
remove_ids list[int] | None

Id degli allegati da togliere.

None

Returns:

Name Type Description
Un PostAttachmentsWriteResult

class:PostAttachmentsWriteResult con gli allegati aggiunti, aggiornati e tolti.

edit_attachments_raw(post_id, req)

Come :meth:edit_attachments, da un EditPostAttachmentsRequestDTO.

edit_custom_data(post_id, occ_token, *, custom_data=None, delta_area_format=None, tables=None)

PUT /communication/posts/manage/edit-post-custom-data/{postId}/{occToken}.

Modifica i soli campi custom. occ_token come in :meth:edit.

Parameters:

Name Type Description Default
post_id int

Il post da modificare.

required
occ_token int

Token di concorrenza ottimistica letto con :meth:get_for_edit.

required
custom_data dict[str, Any] | None

Campi custom, per id del campo.

None
delta_area_format int | None

Formato dei campi custom di tipo delta.

None
tables WriteItems

Tabelle, nella forma di CreateEditPostTableRequestDTO.

None

Returns:

Name Type Description
Un PostWriteResult

class:PostWriteResult con il next_occ_token.

edit_custom_data_raw(post_id, occ_token, req)

Come :meth:edit_custom_data, da un EditPostCustomDataRequestDTO.

edit_raw(post_id, occ_token, req)

Come :meth:edit, da un EditCustomPostRequestDTO già costruito.

edit_watchers(post_id, *, add_user_ids=None, remove_user_ids=None)

PUT /communication/posts/manage/edit-post-watchers/{postId}.

Senza occToken. Il server risponde 200 senza corpo.

Parameters:

Name Type Description Default
post_id int

Il post.

required
add_user_ids list[int] | None

Utenti osservatori da aggiungere.

None
remove_user_ids list[int] | None

Utenti osservatori da togliere.

None

edit_watchers_raw(post_id, req)

Come :meth:edit_watchers, da un EditPostWatchersRequestDTO.

edit_workflow_screen(post_id, screen_occ_token, *, screen_data=None, delta_area_format=None)

PUT /communication/posts/manage/edit-post-workflow-screen-data/{postId}/{token}.

Modifica i dati di screen dello stato corrente. screen_occ_token è quello letto con :meth:get_workflow_screen; un 409 diventa :class:~pynteracta.exceptions.ConcurrencyError.

Parameters:

Name Type Description Default
post_id int

Il post.

required
screen_occ_token int

Token di concorrenza dello screen.

required
screen_data dict[str, Any] | None

Valori dei campi dello screen, per id del campo.

None
delta_area_format int | None

Formato dei campi di tipo delta.

None

Returns:

Name Type Description
Un WorkflowScreenWriteResult

class:WorkflowScreenWriteResult con il next_screen_occ_token.

edit_workflow_screen_raw(post_id, screen_occ_token, req)

Come :meth:edit_workflow_screen, da un DTO già costruito.

execute_workflow_operation(post_id, operation_id, *, screen_data=None, delta_area_format=None, screen_occ_token=None)

POST /communication/posts/manage/execute-post-workflow-operation/{postId}/{opId}.

Esegue una transizione di workflow. Se la transizione ha uno screen, screen_data e screen_occ_token (letto con :meth:get_workflow_screen passando operation_id) vanno nel corpo; senza argomenti il corpo è {}. Gli operation_id permessi si leggono da PostCapabilities.workflow_permitted_operations.

Parameters:

Name Type Description Default
post_id int

Il post.

required
operation_id int

La transizione da eseguire.

required
screen_data dict[str, Any] | None

Valori dei campi dello screen, per id del campo.

None
delta_area_format int | None

Formato dei campi di tipo delta.

None
screen_occ_token int | None

Token di concorrenza dello screen.

None

Returns:

Type Description
WorkflowOperationResult

Nuovo stato, dati di screen e transizioni permesse (:class:WorkflowOperationResult).

execute_workflow_operation_raw(post_id, operation_id, req)

Come :meth:execute_workflow_operation, da un DTO già costruito.

get_for_copy(post_id, *, load_attachments=None)

GET /communication/posts/manage/post-data-for-copy/{postId}.

Parameters:

Name Type Description Default
post_id int

Il post da copiare.

required
load_attachments bool | None

loadAttachments in query, solo se passato.

None

Returns:

Type Description
PostForCopy

I dati da copiare e l'occ_token da passare a :meth:copy (:class:PostForCopy).

get_for_create(community_id)

GET /communication/posts/manage/post-data-for-create/{communityId}.

Parameters:

Name Type Description Default
community_id int

La community in cui si vuole creare il post.

required

Returns:

Type Description
PostForCreate

I dati iniziali della form di creazione (:class:PostForCreate).

get_for_edit(post_id, *, load_attachments=None)

GET /communication/posts/manage/post-data-for-edit/{postId}.

Parameters:

Name Type Description Default
post_id int

Il post da modificare.

required
load_attachments bool | None

loadAttachments in query, solo se passato (il server carica gli allegati per default).

None

Returns:

Type Description
PostForEdit

I dati editabili e l'occ_token da passare a :meth:edit ed

PostForEdit

meth:edit_custom_data (:class:PostForEdit).

get_workflow_screen(post_id, *, operation_id=None)

GET /communication/posts/manage/post-workflow-screen-data-for-edit/{postId}.

Parameters:

Name Type Description Default
post_id int

Il post.

required
operation_id int | None

Senza, lo screen dello stato corrente; con l'id di una transizione (workflowOperationId in query), lo screen di quella transizione.

None

Returns:

Type Description
WorkflowScreen

Dati, metadati e screen_occ_token dello screen (:class:WorkflowScreen).

mark_as_erasable(post_id)

PUT /communication/posts/manage/mark-post-as-erasable/{postId}, senza corpo.

Il post viene eliminato e marcato per una futura cancellazione fisica.

Returns:

Type Description
int | None

Il postId della risposta.

pynteracta.api.posts_event.PostsEventAPI

Bases: ResourceClient

Scritture dei post evento, con le letture propedeutiche e la partecipazione.

copy_event(post_id, occ_token, *, start_at=None, end_at=None, all_day=None, location=None, invited_user_ids=None, invited_group_ids=None, invitation_type_id=None, send_edit_post_notifications=None, title=None, description=None, description_format=None, cover_image_content_ref=None, add_attachments=None, update_attachments=None, remove_attachment_ids=None, add_watcher_user_ids=None, remove_watcher_user_ids=None, add_watcher_group_ids=None, remove_watcher_group_ids=None, visibility=None, link_preview=None, pinned=None, draft=None, scheduled_publication=None, announcement=None, client_uid=None)

PUT /communication/posts/manage/copy-event-post/{postId}/{occToken}.

Crea un post evento nuovo copiando post_id; occ_token è quello letto con :meth:get_event_for_copy. Gli argomenti sono quelli di :meth:edit_event più announcement e client_uid.

Returns:

Name Type Description
Un PostWriteResult

class:PostWriteResult con il post_id del post nuovo.

Raises:

Type Description
ValueError

se una data passata non ha fuso, prima della chiamata.

copy_event_raw(post_id, occ_token, req)

Come :meth:copy_event, da un CopyEventPostRequestDTO già costruito.

create_event(community_id, *, start_at, end_at=None, all_day=None, location=None, invited_user_ids=None, invited_group_ids=None, invitation_type_id=None, send_edit_post_notifications=None, title=None, description=None, description_format=None, cover_image_content_ref=None, attachments=None, watcher_user_ids=None, watcher_group_ids=None, visibility=None, announcement=None, client_uid=None, link_preview=None, pinned=None, draft=None, scheduled_publication=None)

POST /communication/posts/manage/create-event-post/{communityId}.

Il corpo contiene i soli campi passati; il blocco event lo compone :func:build_event_block. Una data senza fuso solleva ValueError prima della chiamata.

Parameters:

Name Type Description Default
community_id int

La community in cui creare il post evento.

required
start_at date

Inizio dell'evento, datetime con fuso (obbligatorio); con all_day anche un date.

required
end_at date | None

Fine dell'evento, convertita nel fuso di start_at.

None
all_day bool | None

Evento di tutto il giorno: le date viaggiano senza ora e senza fuso.

None
location str | None

Luogo.

None
invited_user_ids list[int] | None

Utenti invitati.

None
invited_group_ids list[int] | None

Gruppi invitati.

None
invitation_type_id int | None

Tipo di invito per tutti gli invitati (0 ospite, 2 collaboratore); senza, decide il server.

None
send_edit_post_notifications bool | None

Notifica agli invitati le modifiche del post.

None
title str | None

Titolo.

None
description str | None

Descrizione, nel formato di description_format.

None
description_format int | None

1 = Quill delta (default del server), 2 = testo semplice.

None
cover_image_content_ref str | None

contentRef dell'immagine di copertina, caricata con client.attachments.upload.

None
attachments WriteItems

Allegati: UploadedAttachment o InputPostAttachmentDTO.

None
watcher_user_ids list[int] | None

Utenti osservatori.

None
watcher_group_ids list[int] | None

Gruppi osservatori.

None
visibility int | None

1 privato, 2 pubblico.

None
announcement bool | None

Post marcato come annuncio; inviato solo se passato.

None
client_uid str | None

Identificativo scelto dal chiamante, per ritrovare il post con get_by_client_uid dopo un esito incerto.

None
link_preview dict[str, Any] | BaseModel | None

Anteprima di un link, nella forma di LinkPreviewDTO.

None
pinned bool | None

Post fissato in testa.

None
draft bool | None

Creazione in bozza.

None
scheduled_publication datetime | None

Pubblicazione programmata, datetime con fuso.

None

Returns:

Name Type Description
Un PostWriteResult

class:PostWriteResult con post_id, next_occ_token e post.

Raises:

Type Description
ValueError

se start_at, end_at o scheduled_publication non ha fuso, o se una data senza ora è passata senza all_day.

create_event_raw(community_id, req)

Come :meth:create_event, da un CreateEventPostRequestDTO già costruito.

edit_event(post_id, occ_token, *, start_at=None, end_at=None, all_day=None, location=None, invited_user_ids=None, invited_group_ids=None, invitation_type_id=None, send_edit_post_notifications=None, title=None, description=None, description_format=None, cover_image_content_ref=None, add_attachments=None, update_attachments=None, remove_attachment_ids=None, add_watcher_user_ids=None, remove_watcher_user_ids=None, add_watcher_group_ids=None, remove_watcher_group_ids=None, visibility=None, link_preview=None, pinned=None, draft=None, scheduled_publication=None)

PUT /communication/posts/manage/edit-event-post/{postId}/{occToken}.

occ_token è quello letto con :meth:get_event_for_edit: se il post è cambiato nel frattempo il server risponde 409 (:class:~pynteracta.exceptions.ConcurrencyError) e la libreria non rilegge né riprova. Il corpo contiene solo i campi passati; il blocco event compare solo se almeno un argomento dell'evento è passato, con il fuso di start_at o, se manca, di end_at. L'effetto sui campi omessi lo decide il server (vedi la documentazione).

Parameters:

Name Type Description Default
post_id int

Il post evento da modificare.

required
occ_token int

Token di concorrenza ottimistica letto.

required
start_at date | None

Nuovo inizio, datetime con fuso; con all_day anche un date.

None
end_at date | None

Nuova fine, datetime con fuso; con all_day anche un date.

None
all_day bool | None

Evento di tutto il giorno: le date viaggiano senza ora e senza fuso.

None
location str | None

Luogo.

None
invited_user_ids list[int] | None

Utenti invitati.

None
invited_group_ids list[int] | None

Gruppi invitati.

None
invitation_type_id int | None

Tipo di invito per tutti gli invitati (0 ospite, 2 collaboratore).

None
send_edit_post_notifications bool | None

Notifica agli invitati le modifiche del post.

None
title str | None

Titolo.

None
description str | None

Descrizione, nel formato di description_format.

None
description_format int | None

1 = Quill delta, 2 = testo semplice.

None
cover_image_content_ref str | None

contentRef della nuova immagine di copertina.

None
add_attachments WriteItems

Allegati da aggiungere.

None
update_attachments WriteItems

Allegati da aggiornare.

None
remove_attachment_ids list[int] | None

Allegati da togliere.

None
add_watcher_user_ids list[int] | None

Utenti osservatori da aggiungere.

None
remove_watcher_user_ids list[int] | None

Utenti osservatori da togliere.

None
add_watcher_group_ids list[int] | None

Gruppi osservatori da aggiungere.

None
remove_watcher_group_ids list[int] | None

Gruppi osservatori da togliere.

None
visibility int | None

1 privato, 2 pubblico.

None
link_preview dict[str, Any] | BaseModel | None

Anteprima di un link, nella forma di LinkPreviewDTO.

None
pinned bool | None

Post fissato in testa; None lo lascia com'è.

None
draft bool | None

Bozza o pubblicato.

None
scheduled_publication datetime | None

Pubblicazione programmata, datetime con fuso.

None

Returns:

Name Type Description
Un PostWriteResult

class:PostWriteResult; next_occ_token è il token per la modifica

PostWriteResult

successiva.

Raises:

Type Description
ValueError

se una data passata non ha fuso, prima della chiamata.

edit_event_raw(post_id, occ_token, req)

Come :meth:edit_event, da un EditEventPostRequestDTO già costruito.

get_event_for_copy(post_id, *, load_attachments=None)

GET /communication/posts/manage/event-post-data-for-copy/{postId}.

Parameters:

Name Type Description Default
post_id int

Il post evento da copiare.

required
load_attachments bool | None

loadAttachments in query, solo se passato.

None

Returns:

Type Description
EventPostForCopy

I dati da copiare e l'occ_token da passare a :meth:copy_event

EventPostForCopy

(:class:EventPostForCopy).

get_event_for_create(community_id)

GET /communication/posts/manage/event-post-data-for-create/{communityId}.

Parameters:

Name Type Description Default
community_id int

La community in cui si vuole creare il post evento.

required

Returns:

Type Description
EventPostForCreate

I dati iniziali della form di creazione (:class:EventPostForCreate).

get_event_for_edit(post_id, *, load_attachments=None)

GET /communication/posts/manage/event-post-data-for-edit/{postId}.

Parameters:

Name Type Description Default
post_id int

Il post evento da modificare.

required
load_attachments bool | None

loadAttachments in query, solo se passato.

None

Returns:

Type Description
EventPostForEdit

I dati editabili, l'evento e l'occ_token da passare a :meth:edit_event

EventPostForEdit

(:class:EventPostForEdit).

participate(post_id, answer, *, notes=None)

PUT /communication/posts/manage/post-event/{postId}/partecipate.

Registra la risposta all'invito dell'identità autenticata: con il service account l'identità tecnica, con Google OAuth2 l'utente collegato. Il server risponde senza corpo.

Parameters:

Name Type Description Default
post_id int

Il post evento.

required
answer ParticipationAnswer | int

:class:~pynteracta.models.facade.posts_event.ParticipationAnswer o il suo valore intero (1 sì, 2 forse, 3 no).

required
notes str | None

Note facoltative per l'organizzatore, in testo: si inviano come delta di una riga, l'unico formato che il server accetta. Un delta già pronto va con :meth:participate_raw.

None

Raises:

Type Description
ValueError

se answer non è 1, 2 o 3, prima della chiamata.

participate_raw(post_id, req)

Come :meth:participate, da un EditPostEventPartecipateRequestDTO.

Facade Reference

pynteracta.models.facade.posts_write

Façade per le scritture dei post, le letture propedeutiche, i commenti e il workflow (spec 03).

Molti DTO annidati sono generati come stub RootModel[Any]: le façade li rivalidano nelle varianti tipizzate (PostDetailDTO1, PostEditableContentDataDTO1, PostCommentDTO1, PostWorkflowDefinitionStateDTO1, PostWorkflowDefinitionTransitionDTO1, WorkflowDefinitionScreenDTO1, PostAttachmentDataDTO1, UserDTOModel). Il DTO generato resta sempre disponibile in .raw.

PostWriteResult

Façade sulla risposta di create-post, edit-post, edit-post-custom-data e copy-post.

Attributes:

Name Type Description
raw

Il DTO generato (CreatePostResponseDTO, EditPostResponseDTO o CopyPostResponseDTO).

next_occ_token property

Token di concorrenza da usare per la modifica successiva.

post property

Dati del post dopo la scrittura, tipizzati.

post_id property

Id del post scritto: dalla risposta (create, copy), altrimenti dai dati del post.

from_copy(data) classmethod

Legge la risposta di copy-post.

from_create(data) classmethod

Legge la risposta di create-post.

from_edit(data) classmethod

Legge la risposta di edit-post ed edit-post-custom-data.

PostForCreate

Façade su post-data-for-create: i dati iniziali della form di creazione.

Attributes:

Name Type Description
raw

Il GetCustomPostForCreateResponseDTO generato.

content_data property

Dati editabili proposti dal server per un post nuovo.

from_dict(data) classmethod

Legge la risposta di post-data-for-create.

PostForEdit

Façade su post-data-for-edit: dati editabili e occ_token per edit.

Attributes:

Name Type Description
raw

Il GetCustomPostForEditResponseDTO generato.

community_id property

Community del post.

content_data property

Dati editabili del post: titolo, descrizione, campi custom, allegati, watcher…

current_workflow_state property

Stato corrente del workflow, se la community ne ha uno.

custom_id property

Identificativo leggibile del post (per esempio POST-21269).

occ_token property

Token di concorrenza da passare a edit ed edit_custom_data.

from_dict(data) classmethod

Legge la risposta di post-data-for-edit.

PostForCopy

Façade su post-data-for-copy: dati da copiare e occ_token per copy.

Attributes:

Name Type Description
raw

Il GetCustomPostForCopyResponseDTO generato.

content_data property

Dati editabili del post da copiare.

occ_token property

Token di concorrenza da passare a copy.

from_dict(data) classmethod

Legge la risposta di post-data-for-copy.

PostComment

Façade sulla risposta di create-comment: il commento appena creato.

Attributes:

Name Type Description
raw

Il CreatePostCommentResponseDTO generato.

comment property

Il commento tipizzato.

comment_delta property

Testo del commento in formato Quill delta (JSON).

comment_plain_text property

Testo del commento.

creation_timestamp property

Data di creazione (epoch in millisecondi).

creator_user property

Autore del commento.

id property

Id del commento.

parent_comment_id property

Id del commento a cui questo risponde, se c'è.

from_dict(data) classmethod

Legge la risposta di create-comment.

PostAttachmentsWriteResult

Façade sulla risposta di edit-post-attachments.

Attributes:

Name Type Description
raw

L'EditPostAttachmentsResponseDTO generato.

added property

Allegati aggiunti.

post_id property

Id del post.

removed_ids property

Id degli allegati tolti.

updated property

Allegati aggiornati.

from_dict(data) classmethod

Legge la risposta di edit-post-attachments.

WorkflowScreen

Façade su post-workflow-screen-data-for-edit: dati e token dello screen.

Attributes:

Name Type Description
raw

Il GetPostWorkflowScreenDataForEditResponseDTO generato.

current_workflow_state property

Stato corrente del workflow del post.

screen property

Metadati dello screen (nome, messaggio, campi).

screen_data property

Valori correnti dei campi dello screen, per id del campo.

screen_occ_token property

Token di concorrenza dello screen.

from_dict(data) classmethod

Legge la risposta di post-workflow-screen-data-for-edit.

WorkflowOperationResult

Façade sulla risposta di execute-post-workflow-operation.

Attributes:

Name Type Description
raw

L'ExecutePostWorkflowOperationResponseDTO generato.

new_can_edit_workflow_screen_data property

Se i dati di screen del nuovo stato sono modificabili.

new_current_state property

Stato del workflow dopo la transizione.

new_permitted_operations property

Transizioni permesse dal nuovo stato.

new_screen_data property

Valori dei campi dello screen dopo la transizione.

post_data_has_changed property

Se la transizione ha cambiato anche i dati del post.

from_dict(data) classmethod

Legge la risposta di execute-post-workflow-operation.

WorkflowScreenWriteResult

Façade sulla risposta di edit-post-workflow-screen-data.

Attributes:

Name Type Description
raw

L'EditPostWorkflowScreenDataResponseDTO generato.

new_screen_data property

Valori dei campi dello screen dopo la modifica.

next_screen_occ_token property

Token di concorrenza dello screen per la modifica successiva.

post_data_has_changed property

Se la modifica ha cambiato anche i dati del post.

from_dict(data) classmethod

Legge la risposta di edit-post-workflow-screen-data.

pynteracta.models.facade.posts_event

Façade per i post evento: dati dell'evento, letture propedeutiche e partecipazione (spec 08).

I DTO annidati dell'evento sono generati come stub RootModel[Any]: le façade li rivalidano nelle varianti tipizzate (EventPostEditableContentDataDTOModel, EventPostDataDTOModel, EventDatetimeDTO, EventPostInvitationsDataDTO1, InvitationUserDTO1, InvitationGroupDTO1, PostCoverImageDTO1). Il DTO generato resta sempre in .raw.

EventData

Façade sul blocco event di un post evento.

Le date sono datetime nel fuso IANA dell'evento (localDatetime più timezone), così rimandarle a edit_event non sposta l'evento; senza un fuso valido valgono zonedDatetime (offset fisso). Gli eventi tutto il giorno hanno date senza ora: date. None se non si ricava nulla.

Attributes:

Name Type Description
raw

L'EventPostDataDTOModel generato.

all_day property

Evento di tutto il giorno.

end_at property

Fine dell'evento, se c'è.

invited_groups property

Gruppi invitati.

invited_users property

Utenti invitati.

location property

Luogo dell'evento.

my_answer property

Risposta dell'utente corrente all'invito; None se non ha ancora risposto.

participants_count property

Numero dei partecipanti.

send_edit_post_notifications property

Notifica agli invitati delle modifiche al post.

start_at property

Inizio dell'evento.

timezone property

Fuso IANA dell'evento.

EventInvitee

Un utente o un gruppo invitato all'evento.

Attributes:

Name Type Description
raw

L'InvitationUserDTO1 o l'InvitationGroupDTO1 generato.

id property

Id dell'utente o del gruppo.

name property

Nome e cognome dell'utente, o nome del gruppo.

type_id property

Tipo di invito (0 ospite, 2 collaboratore), se il server lo riporta.

EventPostForCreate

Façade su event-post-data-for-create: valori iniziali di un post evento nuovo.

Attributes:

Name Type Description
raw

Il GetEventPostForCreateResponseDTO generato.

content_data property

Dati editabili iniziali.

cover_image property

Immagine di copertina, se c'è.

event property

Blocco dell'evento, se il server lo propone.

from_dict(data) classmethod

Legge la risposta di event-post-data-for-create.

EventPostForEdit

Façade su event-post-data-for-edit: dati editabili e occ_token per edit_event.

Attributes:

Name Type Description
raw

Il GetEventPostForEditResponseDTO generato.

community_id property

Community del post.

content_data property

Dati editabili: titolo, descrizione, visibilità, copertina, evento…

cover_image property

Immagine di copertina, se c'è.

custom_id property

Identificativo leggibile del post.

event property

Blocco dell'evento; None se la risposta non lo ha.

occ_token property

Token di concorrenza da passare a edit_event.

from_dict(data) classmethod

Legge la risposta di event-post-data-for-edit.

EventPostForCopy

Façade su event-post-data-for-copy: dati da copiare e occ_token per copy_event.

Attributes:

Name Type Description
raw

Il GetEventPostForCopyResponseDTO generato.

content_data property

Dati editabili del post da copiare.

event property

Blocco dell'evento; None se la risposta non lo ha.

occ_token property

Token di concorrenza da passare a copy_event.

from_dict(data) classmethod

Legge la risposta di event-post-data-for-copy.

ParticipationAnswer

Bases: IntEnum

Risposta all'invito di un evento, come typeId di post-event/{postId}/partecipate.