---
title: "Search activities"
method: POST
path: "/api/activities/search"
tags: ["activities"]
---

# Search activities

`POST /api/activities/search`

## Request

- Base URL: `https://beta.getsales.io/playtables/v1`
- URL: `https://beta.getsales.io/playtables/v1/api/activities/search`
- Auth: HTTP bearer and API key in header `Team-SID`

The append-only event feed of a person or company: channel, website and profile-view facts (private context, never repeated to the lead), workflow, object, tag and note changes. Scope with object_sid (the timeline), playtable_sid, play_sid, sender_profile_sid or involved_workflow_sid; created_at is when a fact reached the ledger; page_size 0 = counts.groups alone. Includes: person, company, play_acts, person_journey. Not for message bodies or workflow state.

Contract:
- MCP tool `search_activities`, registry package `mcp.playtables/activities`, mount `playtables.people`.
- Operation `search`, response envelope `search`.
- Flags: read only.

## Request body

- SearchActivitiesRequest: Request body of `search_activities`.
  - `filter` object: Field filters, ANDed: {field: {eq | ne | in | nin | gte | lte | gt | lt | is_null}}; q inside it is free text. Omit for every row.
    - `sid` object: Activity sid(s), cr_ac_ prefix (prefix-validated).
      - `eq` string: Activity sid (cr_ac_…).
      - `in` string[]
    - `object_type` object: person | company.
      - `eq` 'person' | 'company'
    - `object_sid` object: Timeline scope - cr_pp_/cr_co_ sid(s); `in` for company roll-ups (person sids from ./people.md search).
      - `eq` string
      - `in` string[]
    - `category` object: Type-group filter - cheaper than a long type.in list.
      - `eq` 'object' | 'workflow' | 'ai_agent' | 'linkedin' | 'email' | 'website' | 'other'
      - `in` string[]
      - `nin` string[]
    - `type` object: Exact fact kinds.
      - `eq` 'object_created' | 'object_updated' | 'object_deleted' | 'object_playtable_changed' | 'object_pipeline_stage_changed' | 'tags_added' | 'tags_removed' | 'workflow_added' | 'workflow_restarted' | 'workflow_cancelled' | 'workflow_finished' | 'workflow_failed' | 'ai_agent_status_changed' | 'ai_agent_fact_saved' | 'linkedin_connection_request_sent' | 'linkedin_connection_request_accepted' | 'linkedin_connection_request_withdrawn' | 'linkedin_blocked' | 'linkedin_message_sent' | 'linkedin_inmail_sent' | 'linkedin_message_replied' | 'linkedin_inmail_replied' | 'linkedin_message_opened' | 'linkedin_link_clicked' | 'linkedin_post_liked' | 'linkedin_post_commented' | 'linkedin_profile_visited' | 'linkedin_skills_endorsed' | 'linkedin_invitation_received' | 'linkedin_invitation_accepted' | 'linkedin_invitation_ignored' | 'linkedin_invitation_expired' | 'linkedin_connection_removed' | 'linkedin_followed' | 'linkedin_message_reacted' | 'linkedin_message_deleted' | 'linkedin_profile_viewed_us' | 'email_sent' | 'email_replied' | 'email_opened' | 'email_bounced' | 'email_link_clicked' | 'email_unsubscribed' | 'email_complained' | 'website_visited' | 'website_key_page_visited' | 'website_form_submitted' | 'website_event' | 'manual_task_completed' | 'note_left' | 'object_enriched' | 'object_data_changed' | 'linkedin_job_changed' | 'linkedin_post_published' | 'linkedin_birthday' | 'linkedin_work_anniversary' | 'linkedin_profile_followed' | 'linkedin_post_engaged'
      - `in` string[]
      - `nin` string[]
    - `workflow_sid` object: wf_wf_ sid(s); is_null:true = facts outside any workflow.
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `workflow_step_id` object: The step id (within its workflow) the fact was produced by; is_null:true = facts outside any step.
      - `eq` integer
      - `in` integer[]
      - `is_null` boolean
    - `occurred_at` object: ISO 8601 range; combine bounds in one object. Ignored on metrics - period owns the window.
      - `gte` string
      - `lte` string
      - `gt` string
      - `lt` string
    - `playtable_sid` object: A table's feed: the facts of its live people and the website facts of the accounts they work at. eq only.
      - `eq` string
    - `play_sid` object: What plays caused: the people their find_people sources created (object_created) and the journeys their workflow sources began or started over (workflow_added, workflow_restarted). A non-empty in only.
      - `in` string[]
    - `sender_profile_sid` object: The sender profile a fact came through (ub_sp_). A fact no sender profile made (website, CRM, workflow) never passes this leaf, leave it out to keep them; is_null true keeps only such facts. One of eq, non-empty in or is_null; another prefix is a 422.
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `act_state` object: waiting = a task waits on the event (a draft, a question, a failed act); done = handled, nothing waiting (a task of any status names it, an act left its fact, a wait woke); none = nothing touched it, never a kind no play handles. eq or non-empty in.
      - `eq` 'waiting' | 'done' | 'none'
      - `in` string[]
    - `acted_play_sid` object: The events those plays acted on, by a task or a fact naming the event. A non-empty in only.
      - `in` string[]
    - `involved_sender_profile_sid` object: The facts stamped with those sender profiles, and the events a task or a fact of theirs answers (a post carries no sender profile; the comment drafted on it does). A non-empty in only.
      - `in` string[]
    - `involved_workflow_sid` object: One campaign's events: the events of the people who hold or held a record of those workflows (a left journey counts) and the facts those workflows wrote. Wider than workflow_sid, which keeps the workflow's own facts alone. A non-empty in only.
      - `in` string[]
    - `act_do` object: What an act did about the event, by a DONE task's act.do or the act's fact: like = linkedin_post_liked, comment = linkedin_post_commented, send_message = linkedin_message_sent; ask and add_to_workflow by the task alone. A non-empty in only.
      - `in` string[]
    - `field_sid` object: The facts a column's pull wrote, read off payload.field_sid (object_enriched, object_data_changed, linkedin_job_changed, linkedin_post_published carry it): with object_sid, one cell's history. eq or a non-empty in; a sid outside pt_fd_ is a 422.
      - `eq` string
      - `in` string[]
    - `created_at` object: ISO 8601 range on when the fact reached the ledger, which can be long after it happened (a history walk). New since I looked = created_at gt seen_at with an occurred_at floor (seen_at minus 3 days); when it happened = occurred_at. On metrics too.
      - `gte` string
      - `lte` string
      - `gt` string
      - `lt` string
  - `include` string[]: Relations to attach to every item; omit for the bare rows.
  - `sort` object: One column and its direction; omit for the default order.
    - `field` 'occurred_at', required: The column to order by.
    - `direction` 'asc' | 'desc': asc or desc; default desc.
  - `page_size` integer: 0..500, default 50; 0 = counts only, 1 = the first row.
  - `cursor` string, nullable: pagination.next_cursor of the previous page.

## Response `200`

`search` success envelope.

- SearchActivitiesResponse
  - `success` true, required
  - `operation` 'search', required
  - `items` object[], required
    - `item` object, required
      - `sid` string, required: Activity sid (cr_ac_…).
      - `team_sid` string, required: Owning team (ts_tm_…, external - gs.service.id).
      - `object_type` 'person' | 'company', required: Which object the fact is about: person | company.
      - `object_sid` string, required: cr_pp_… (person) or cr_co_… (company) - the object the fact attaches to.
      - `category` 'object' | 'workflow' | 'ai_agent' | 'linkedin' | 'email' | 'website' | 'other', required: The type's group - derived from type by the fixed server-side map; stored for indexed channel filters.
      - `type` 'object_created' | 'object_updated' | 'object_deleted' | 'object_playtable_changed' | 'object_pipeline_stage_changed' | 'tags_added' | 'tags_removed' | 'workflow_added' | 'workflow_restarted' | 'workflow_cancelled' | 'workflow_finished' | 'workflow_failed' | 'ai_agent_status_changed' | 'ai_agent_fact_saved' | 'linkedin_connection_request_sent' | 'linkedin_connection_request_accepted' | 'linkedin_connection_request_withdrawn' | 'linkedin_blocked' | 'linkedin_message_sent' | 'linkedin_inmail_sent' | 'linkedin_message_replied' | 'linkedin_inmail_replied' | 'linkedin_message_opened' | 'linkedin_link_clicked' | 'linkedin_post_liked' | 'linkedin_post_commented' | 'linkedin_profile_visited' | 'linkedin_skills_endorsed' | 'linkedin_invitation_received' | 'linkedin_invitation_accepted' | 'linkedin_invitation_ignored' | 'linkedin_invitation_expired' | 'linkedin_connection_removed' | 'linkedin_followed' | 'linkedin_message_reacted' | 'linkedin_message_deleted' | 'linkedin_profile_viewed_us' | 'email_sent' | 'email_replied' | 'email_opened' | 'email_bounced' | 'email_link_clicked' | 'email_unsubscribed' | 'email_complained' | 'website_visited' | 'website_key_page_visited' | 'website_form_submitted' | 'website_event' | 'manual_task_completed' | 'note_left' | 'object_enriched' | 'object_data_changed' | 'linkedin_job_changed' | 'linkedin_post_published' | 'linkedin_birthday' | 'linkedin_work_anniversary' | 'linkedin_profile_followed' | 'linkedin_post_engaged', required: 56-value fact vocabulary; past-tense fact label, not a state.
      - `payload` union, required: Per-type references (sids, tracking ids, reasons) - never message bodies. Shape keyed by the sibling type field.
        - object
          - `origin` 'recheck' | 'catch_up', required: Where the change was seen.
          - `changes` object[], required: The title and the company, old and new, with every other key field that moved beside them.
            - `key` string, required: The answer's path (headline, company.name).
            - `label` string, required: The word the row shows for it.
            - `old` unknown
            - `new` unknown
          - `field_sid` string, nullable: pt_fd_… the column that re-checked; null from the catch-up feed.
          - `column` string, nullable: The column's name at the time; null from the catch-up feed.
          - `source` 'linkedin_profile' | 'company_page' | 'work_email' | 'phone' | 'posts' | 'people' | 'api', nullable: What was read; null from the catch-up feed.
          - `sender_profile_sid` string, nullable: ub_sp_… the sender profile whose catch-up feed carried the card; null on a re-check.
          - `linkedin_account_sid` string, nullable: The gtm LinkedIn account that read the card; null on a re-check.
        - object
          - `field_sid` string, required: pt_fd_… the column that pulled.
          - `column` string, required: The column's name at the time.
          - `source` 'linkedin_profile' | 'company_page' | 'work_email' | 'phone' | 'posts' | 'people' | 'api', required: What was read.
          - `changes` object[], required: Every key field that moved, old and new.
            - `key` string, required: The answer's path (headline, company.name).
            - `label` string, required: The word the row shows for it.
            - `old` unknown
            - `new` unknown
        - object
          - `field_sid` string, required: pt_fd_… the column that pulled - see ./playtable_fields.md.
          - `column` string, required: The column's name at the time.
          - `source` 'linkedin_profile' | 'company_page' | 'work_email' | 'phone' | 'posts' | 'people' | 'api', required: What was read.
          - `first` boolean, required: true = Enriched: the first pull of this column for the row that came back with an answer; false = Re-checked, every later one, changes or not.
          - `outcome` 'found' | 'nothing_found' | 'not_verified', required: What came back.
          - `fields` integer, required: How many of the answer's fields carried a value.
          - `from_cache` boolean, nullable: true when the answer came from the cache rather than the network.
          - `credits` number, nullable: What the pull cost, in credits.
          - `run_sid` string, nullable: pt_rn_… the run that made the pull - see ./playtable_runs.md.
          - `values` object[], nullable: The source's key fields that carry a value in this answer, in the source's order (2026-10-15): what the Enriched row's tree shows. [] when the answer held none (a search that found nothing); null for posts, people and api, which name no key fields; absent on facts written before.
            - `key` string, required: The key field's path in the answer (a search's is `value`).
            - `label` string, required: The word the row shows: Name, Headline, Title, Company, Location; Name, Industry, Size, Headquarters, Website; Work email; Phone.
            - `value` string, required: The value as a change compares it, at most 500 characters.
          - `verdict` string, nullable: The email verifier's word on the address a work email search kept (valid, catch_all, unknown, risky; catch_all, unknown and risky make the outcome not_verified); null for every other source and when no verifier spoke.
        - object
          - `activity_urn` string, required: The post's activity URN, the one a Like or a comment addresses.
          - `kind` 'post' | 'repost_with_comment', required: The person's own post, or a repost with their own words.
          - `excerpt` string, required: The post's text cut at 140 characters, the whitespace flattened; may be empty.
          - `text` string, nullable: The whole post, its line breaks kept, 3000 characters at most (2026-10-15); absent on older facts.
          - `post_urn` string, nullable: The post's share or ugcPost URN, when it has one.
          - `posted_at` string, nullable: ISO 8601 UTC - when the post was published, as the network said.
          - `field_sid` string, nullable: pt_fd_… the column that read the posts; null when a workflow step's read wrote the fact.
          - `column` string, nullable: The column's name at the time.
          - `likes` integer, required: The network's count at the read.
          - `comments` integer, required: The network's count at the read.
          - `reposts` integer, required: The network's count at the read.
          - `images` integer, required: How many images the post carries; their copies come with the re-host, never a URL here.
          - `reactions` object, nullable: The count by reaction kind as the read names the kinds (LIKE, EMPATHY, PRAISE, INTEREST, APPRECIATION, ENTERTAINMENT), 2026-10-15; null when the read carried none.
        - object
          - `activity_urn` string, required: The watched post's activity URN, never a URL.
          - `kind` 'reaction' | 'comment' | 'reshare', required: A reaction, a comment or a reshare.
          - `data_source_sid` string, required: ds_sc_… the engagers source that saw it - see ./data_sources.md.
          - `reaction` string, nullable: The reaction's name (like, celebrate, …) when the kind is a reaction.
          - `author_name` string, nullable: The post author's name, for the row.
          - `excerpt` string, nullable: The post's text cut at 140 characters, for the row.
          - `engaged_at` string, nullable: ISO 8601 UTC - when the engagement happened, when the network said.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `year` integer, required: The year the card is for: the dedup key with the kind.
          - `linkedin_account_sid` string, nullable: The gtm LinkedIn account that read the card.
          - `card_sid` string, nullable: The feed card's URN.
          - `text` string, nullable: The card's own words, for the row.
        - object
          - `playtable_sid` string, nullable, required: pt_tb_… table the object landed in - see ./playtables.md.
          - `data_source_sid` string, nullable, required: ds_sc_… source that produced the object - see ./data_sources.md.
          - `data_source_item_sid` string, nullable, required: ds_it_… item the object was promoted from - see ./data_source_items.md.
          - `tags` unknown[], nullable, required: Tags attached at creation; element shape deferred in research (see tags_added for the {sid, name} snapshot convention).
            - unknown
          - `qualified` boolean, nullable: true = born from an item of a data source whose Check on save was on, so the record passed the source's criterion (2026-10-15). null otherwise (no gate, a hand row, the rows born before the stamp); never false: a record the gate turns away is never born.
        - object
          - `fields` string[], required: Changed field names.
          - `old` object, required: Previous values, keyed by field.
          - `new` object, required: New values, keyed by field.
        - object
          - `old` string, required: pt_tb_… membership before the move.
          - `new` string, required: pt_tb_… membership after the move.
          - `data_source_sid` string, nullable, required: ds_sc_… when a source import triggered the move.
        - object
          - `name` string, required: Tombstone snapshot - object display name at deletion time.
        - object
          - `tags` object[], required: Tags added/removed in this change, with name snapshots.
            - `sid` string, required: cr_tg_… tag - see ./tags.md.
            - `name` string, required: Tag name snapshot at event time.
        - object
          - `reason` string, nullable, required: Human-readable cancellation reason.
        - object
          - `reason` string, required: Human-readable failure reason.
        - object
          - `old` string, required: Previous AI SDR status (Messaging-owned vocabulary).
          - `new` string, required: New AI SDR status.
          - `message_sid` string, nullable, required: External Messaging message that triggered the change; null when none.
          - `channel` string, nullable, required: Channel the status change relates to (Messaging-owned); null when not channel-bound.
        - object
          - `fact` string, required: The fact as the Playbook question names it ("Channel", "Their tool").
          - `question` string, required: The question in the agent's words.
          - `answer` string, required: The lead's answer, clamped server-side; untrusted text.
          - `conversation_sid` string, required: The unibox thread it was learned on (ub_cv_...).
          - `run_sid` string, nullable, required: The dialog turn that heard it (ub_rn_...); null when unknown.
          - `changed` boolean, required: true when it replaced an earlier answer to the same question on this thread.
        - object
          - `workflow_task_sid` string, required: wf_tk_… completed manual task - see ./workflow_tasks.md (legacy task_uuid).
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account, when the task was LinkedIn-scoped.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `invitation_sid` string, required: ln_ci_… the gtm invitation row.
          - `note` string, nullable, required: The lead's invitation text; null when none.
          - `source` string, nullable, required: How the end was learned, action | sync; null on the receipt.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `connection_sid` string, required: ln_cn_… the gtm connection row that was severed.
          - `removal_kind` string, nullable, required: removed (the lead removed us) | blocked (the account was blocked); null when unknown.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `block_log_sid` string, required: The gtm linkedin-account-block-log row: the verdict, permanent for the account and the person.
          - `connection_sid` string, nullable, required: ln_cn_… the connection the block closed, when they were one; null otherwise.
          - `activity_log_sid` string, nullable, required: ln_al_… the read of gtm's activity log that established the block; null when unknown.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `follower_sid` string, required: ln_fw_… the gtm follower row.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `message_sid` string, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `emoji` string, required: The reaction, as LinkedIn reports it.
          - `count` integer, nullable, required: How many of the lead's side reacted with it; null when unknown.
        - object
          - `sender_profile_sid` string, required: ub_sp_… the sender profile whose profile was looked at (the one the collector named: one sid on unibox and on the playtables copy) - see ./sender_profiles.md.
          - `times_seen` integer, required: How many runs of the collector listed the viewer: the first sighting and every re-view since.
          - `first_seen_at` string, required: ISO 8601 UTC: when the collector first saw this viewer on this sender profile; the fact's occurred_at on the first sighting.
          - `is_return` boolean, required: True on a re-sighting after thirty days of absence (a second fact under a dated key); false on the first sighting.
          - `linkedin_account_sid` string, nullable, required: The gtm account the list was read on; null when unknown.
          - `viewed_at_text` string, nullable, required: The relative text LinkedIn printed last ("2 days ago"); null when none.
          - `display_name` string, nullable, required: The viewer's name as the list printed it at that moment; null when none.
          - `headline` string, nullable, required: The viewer's headline as the list printed it; null when none.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `mailbox_sid` string, nullable, required: External Messaging mailbox.
          - `message_sid` string, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `bounce_log_sid` string, nullable, required: em_bl_… gtm's bounce log row behind the complaint; null when it did not ride the event.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `message_sid` string, nullable, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `template_sid` string, nullable, required: External Messaging template; null when no template was used.
          - `connected_at` string, required: ISO 8601 UTC - when the connection was accepted.
          - `note_delivered` boolean, nullable, required: Whether the invite's note reached the thread as its first message at the accept (LinkedIn delivers it then, 2026-09-26): true when the invite went through the ledger with a note, false without one or when no invite of ours went (an already-connected accept), null when no ledger task sent the invite. With the messages sent, the base of the messages' reply rate.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `endorsed_count` integer, required: Number of skills endorsed.
          - `skills` string[], required: Endorsed skill names.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `message_sid` string, nullable, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `template_sid` string, nullable, required: External Messaging template; null when no template was used.
          - `tracking_id` string, required: Tracking id of the clicked link.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `message_sid` string, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `template_sid` string, nullable, required: External Messaging template; null when no template was used.
          - `replied_message_sid` string, nullable, required: Our message that was replied to; null when not resolvable.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `message_sid` string, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `template_sid` string, nullable, required: External Messaging template; null when no template was used.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
          - `message_sid` string, nullable, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `template_sid` string, nullable, required: External Messaging template; null when no template was used.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable: The gtm LinkedIn account that followed.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `linkedin_account_sid` string, nullable, required: External Messaging LinkedIn account.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `mailbox_sid` string, nullable, required: External Messaging mailbox.
          - `message_sid` string, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `template_sid` string, nullable, required: External Messaging template; null when no template was used.
          - `replied_message_sid` string, nullable, required: Our message that was replied to; null when not resolvable.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `mailbox_sid` string, nullable, required: External Messaging mailbox.
          - `message_sid` string, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `template_sid` string, nullable, required: External Messaging template; null when no template was used.
        - object
          - `sender_profile_sid` string, required: ub_sp_… sender profile that acted - see ./sender_profiles.md.
          - `mailbox_sid` string, nullable, required: External Messaging mailbox.
          - `message_sid` string, required: External Messaging message id (legacy email_uuid/message_uuid).
          - `bounce_type` string, nullable, required: hard | soft | policy, gtm's classification (2026-09-28); null on facts written before it.
        - object
          - `session_sid` string, required: sg_ws_... the session in gs.service.signals (get_website_session reads its pages and events).
          - `site_sid` string, required: sg_si_... the registered site the visit landed on.
          - `attribution` string, required: How the owner was named: code (the person code in our link), identified (an identify call or a form), fingerprint (the device), manual (a bind by hand), company_code (the company code in our link) and company_network (the visitor's network), both with the company as the object. The signals service's vocabulary, stored as told.
          - `entry_path` string, nullable: The path of the first page view, with its query.
          - `referrer_type` string, nullable: direct | internal | search | social | email | ads | referral | ai_assistant | unknown.
          - `utm_source` string, nullable
          - `utm_campaign` string, nullable
          - `landing_code_used` boolean, nullable: A code in our link named the owner: the person code (attribution code) or the company code (company_code).
          - `visitor_sid` string, nullable: sg_wv_... the browser behind the visit.
        - object
          - `session_sid` string, required: sg_ws_... the session in gs.service.signals (get_website_session reads its pages and events).
          - `key_page_sid` string, required: sg_kp_... the key page whose pattern matched.
          - `key` string, required: The key page's slug (pricing, demo, signup, contact, or one the team added).
          - `path` string, nullable: The path that matched the pattern.
        - object
          - `session_sid` string, required: sg_ws_... the session in gs.service.signals (get_website_session reads its pages and events).
          - `form` string, required: The form's name as the site reported it.
          - `visitor_sid` string, nullable: sg_wv_... the browser the form was submitted from.
        - object
          - `session_sid` string, required: sg_ws_... the session in gs.service.signals (get_website_session reads its pages and events).
          - `event` string, required: The registered event name, as the site sent it.
          - `props` union: The event's properties as sent, 50 keys at most; [] when empty.
            - object
            - unknown[]
              - …
            - unknown
        - object
          - `note_sid` string, required: cr_nt_… the note - see ./notes.md (legacy note_uuid).
        - object
        - unknown[]
          - unknown
      - `workflow_sid` string, nullable, required: wf_wf_… when a workflow produced the fact - see ./workflows.md; null otherwise.
      - `workflow_step_id` integer, nullable, required: Step id inside the version's steps JSON - see ./workflow_versions.md step-id contract.
      - `workflow_record_sid` string, nullable, required: wf_rc_… enrollment that produced the fact - see ./workflow_records.md.
      - `external_sid` string, nullable, required: Messaging event id (max 64) - ingest dedup key; null on in-process rows.
      - `occurred_at` string, required: ISO 8601 UTC - fact time at source; the timeline sort key.
      - `created_by` object, required: Recording actor; actor_type=system on ingested rows.
        - `actor_type` 'user' | 'support' | 'api_key' | 'system' | 'agent', required
        - `actor_sid` string, nullable, required
        - `team_sid` string, required
        - `actor_name` string, nullable: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job.
        - `oauth_client_sid` string, nullable: The acting OAuth client (id_oc_*); null off the OAuth path.
        - `reason` string, nullable: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise.
        - `permissions` object, required: Internal audit context: the grant set the actor held at write time. Not a contract.
        - `cluster_id` integer, nullable: Internal audit context: the cluster that served the write.
        - `trace_id` string, nullable: Internal audit context: the trace id of the request that wrote the row.
      - `created_at` string, required: ISO 8601 UTC - row write time (ingest lag vs occurred_at possible).
      - `updated_at` string, required: ISO 8601 UTC - always equals created_at (no update path).
    - `included` object, required
      - `person` object: PeopleDomain row (cr_pp_…) - see ./people.md; present on object_type=person rows when requested.
        - `sid` string, required
      - `company` object: CompanyDomain row (cr_co_…) - see ./companies.md; present on object_type=company rows when requested.
        - `sid` string, required
      - `play_acts` object: What was done about the row (2026-10-14, the Signals feed): present on every row when requested, with empty lists, a null journey, an empty records object, a null acts_as and a null invite where nothing acted. The act_state leaf reads the same rows.
        - `tasks` object[], required: The workflow tasks naming this row as their trigger (WorkflowTaskDomain rows, see ./workflow_tasks.md), any status, oldest first: a play's (a draft waiting, a reaction sent, a question answered), a person's act by hand (initiator user, 2026-10-15), a journey's Like or comment on the post its read picked (2026-10-15). A journey's wait is the journey instead.
          - `sid` string, required
        - `facts` object[], required: The facts an act left naming this row as their trigger (ActivityDomain rows), oldest first: the comment, the message, the journey entered or left.
          - `sid` string, required
        - `plays` object[], required: Every play the row, its tasks, its facts and its passes name, deleted ones included so the name still reads.
          - `sid` string, required
          - `name` string, required
          - `catalog_key` string, nullable, required: The playbook entry the play was born from (PlayCatalogKeyEnum); null for a play saved from a view.
          - `action_type` 'find_people' | 'add_to_workflow' | 'refresh' | 'congratulate' | 'on_job_change' | 'engage_posts' | 'on_website_visit', required
          - `deleted_at` string, nullable, required: ISO 8601 UTC when the play was deleted; its name still reads.
        - `journey` object, nullable, required: The workflow that acted on the event: a journey's wait_for_event the event woke (the wait names it as its trigger), with the step that followed. Null when no journey waited on it.
          - `workflow_sid` string, required
          - `workflow_record_sid` string, required
          - `record_status` 'waiting_limit' | 'blocked' | 'active' | 'waiting' | 'paused_on_reply' | 'paused_manual' | 'paused_blocked' | 'failed' | 'completed' | 'exited', nullable, required: The journey's status now; null only when the record is gone.
          - `workflow_name` string, nullable, required: The workflow's name, read with the deleted ones (2026-10-15); null only when the row is gone.
          - `next` object, nullable, required: The record's first task after the wait (another wait or a play's question skipped), whatever its status; null when nothing follows yet.
            - `step_id` integer, required
            - `step_ordinal` integer, nullable, required: 1-based place of the step in the pinned version, depth first ("step 3 of 5"); null when the version does not have it.
            - `step_count` integer, nullable, required: Steps in the pinned version, nested ones and end steps counted; null with step_ordinal.
            - `step_type` string, nullable, required: The step's type in the version (WorkflowStepTypeEnum: linkedin_send_message, email_send, condition, ...); null with step_ordinal.
            - `status` 'pending' | 'scheduled' | 'dispatched' | 'done' | 'failed' | 'skipped' | 'skipped_reply' | 'skipped_stoplisted' | 'cancelled' | 'expired', required
            - `at` string, required: ISO 8601 UTC: finished_at, else scheduled_at, else created_at.
            - `text` string, nullable, required: The words the task sends (its message, comment or email body as rendered, perhaps edited since), 2026-10-15; null for a step that sends nothing.
        - `records` object, required: The journeys the row's play tasks ask about (a question names its record), keyed by workflow_record_sid, each with its current step's place. An empty object when none.
        - `passes` object[], required: Why a play that watches the event passed on it (2026-10-15), one per play: the moment off, nobody connected, the weekly cap, a post too old, the person outside the audience, another hand's Like or comment on the post already. Empty when no play passed.
          - `play_sid` string, required: The play that passed; named in plays.
          - `reason` 'outside_audience' | 'act_failed' | 'moment_off' | 'no_connected_sender_profile' | 'empty_message' | 'no_journey' | 'journey_moved_on' | 'nothing_to_do' | 'post_unnamed' | 'post_too_old' | 'weekly_cap' | 'no_sender_profile' | 'comment_not_written' | 'already_engaged' | 'page_not_watched' | 'workflow_unnamed' | 'already_in_workflow', required: Why it passed on the event (the newest run's reason).
          - `at` string, required: ISO 8601 UTC: when a run last passed for this reason.
        - `acts_as` object, nullable, required: The sender profile act_on_activity would act as when given none (2026-10-15): on a post the connected one, else the team's first that can; on any other person's event the one the fact came through, else the connected one. Null for a company's event or when nobody can.
          - `sender_profile_sid` string, required
        - `invite` object, nullable, required: On a linkedin_connection_request_accepted row (2026-10-16): the invitation the accept answers, the person's newest done linkedin_send_connection_request task finished before the accept (a deleted journey's too), so "Accepted the invitation after N days" reads off sent_at. Null for an invitation sent by hand or unknown, and null on every other type.
          - `sent_at` string, required: ISO 8601 UTC: when the invitation went out (the invite task's finished_at).
          - `workflow_sid` string, nullable, required: The journey that sent it (wf_wf_).
          - `workflow_record_sid` string, nullable, required: Its record (wf_rc_).
      - `person_journey` object, nullable: The person's current journey (2026-10-16, the feed's workflow chip): the newest workflow record of the row's person whatever became of it, its status, its current step's place and name in the pinned version, the workflow's name (deleted records and workflows included). On every row when requested; null on a company's row and on a person with no record.
        - `workflow_sid` string, required
        - `workflow_name` string, nullable, required: The workflow's name, read with the deleted ones; null only when the row is gone.
        - `workflow_record_sid` string, required
        - `status` 'waiting_limit' | 'blocked' | 'active' | 'waiting' | 'paused_on_reply' | 'paused_manual' | 'paused_blocked' | 'failed' | 'completed' | 'exited', required: The record's status as stored (WorkflowRecordStatusEnum).
        - `current_step_id` integer, required
        - `step_ordinal` integer, nullable, required: 1-based place of the step in the pinned version, depth first ("step 3 of 5"); null when the version does not have it.
        - `step_count` integer, nullable, required: Steps in the pinned version, nested ones and end steps counted; null with step_ordinal.
        - `step_type` string, nullable, required: The step's type in the version (WorkflowStepTypeEnum: linkedin_send_message, email_send, condition, ...); null with step_ordinal.
        - `step_name` string, nullable, required: The step's own name in the pinned version (the builder's label, 255 at most); null when the builder gave none.
        - `entered_at` string, nullable, required: ISO 8601 UTC: when the journey began; null while the row is held at the door.
        - `finished_at` string, nullable, required: ISO 8601 UTC: when the journey ended; null until a terminal status.
  - `pagination` object, required
    - `next_cursor` string, nullable, required
    - `has_more` boolean, required
    - `total_count` integer, nullable, required
  - `applied_filters` object, required
  - `includes` string[], required
  - `meta` object, required
    - `trace_id` string, required: UUID v7; same 128-bit value as the X-Trace-Id header.
    - `span_id` string, required: 16 hex chars, root span of this request.
    - `timestamp` string, required: ISO 8601 UTC (Y-m-dTH:i:sZ), response time.
    - `duration_ms` integer, required: Server-side wall clock.
    - `team_sid` string, nullable: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends.
    - `actor_type` string, nullable: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends.
  - `counts` object
    - `total_count` integer, required: Rows matching the filter (full filter scope, not the page).
    - `groups` object, required: One axis per ActivityGroupableFieldsEnum value (§4.17); PHP empty map serialises as [].
      - `category` union, required: Flat {value: count} per ActivityCategoryEnum value present in scope.
        - object
        - unknown[]
          - unknown
      - `type` union, required: Flat {value: count} per ActivityTypeEnum value present in scope - the engagement-widget axis.
        - object
        - unknown[]
          - unknown
      - `object_type` union, required: Flat {person: n, company: m} row counts.
        - object
        - unknown[]
          - unknown

## Other responses

- `4XX`: MCP error envelope. `error.code` is one of validation_failed, nothing_to_update, not_found, relation_not_found, invalid_transition, limit_exceeded, payment_required, duplicate_rejected, conflict, delete_blocked, unauthorized, forbidden, rate_limited, not_implemented.
- `5XX`: MCP error envelope with `error.code` internal_error or service_unavailable.

---

[API](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables.md) - [All operations](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables/llms.txt) - [OpenAPI document](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables/revisions/aa394506515d?raw)
