---
title: "Suggest company filter values"
method: POST
path: "/api/companies/suggest"
tags: ["companies"]
---

# Suggest company filter values

`POST /api/companies/suggest`

## Request

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

Facet helper for building filters - distinct values + row counts for ONE field within a filter scope (ES aggregation). Only field: tag_sids - returns tag sids with counts; resolve labels via tags search. term narrows values by prefix/infix. Firmographic facets (industry, specialities, employee ranges, HQ, …) are playtable field values - facet over cells, not here; free-text name/domain typeahead = q on search_companies.

Contract:
- MCP tool `suggest_company_filter_values`, registry package `mcp.playtables/companies`, mount `playtables.people`.
- Operation `action`, response envelope `action`.
- Flags: read only.

## Request body

- SuggestCompanyFilterValuesRequest: Request body of `suggest_company_filter_values`.
  - `field` 'tag_sids', required: Facetable field. tag_sids returns tag sids - resolve labels via tags search.
  - `term` string: Prefix/infix narrowing; omit for top values.
  - `filter` object: Scope (typically { playtable_sids: { in: […] } }).
    - `sid` object: Prefix-validated cr_co_ sid(s).
      - `eq` string: Company sid (cr_co_…).
      - `in` string[]
    - `playtable_sids` object: THE table context - every company tab passes { in: [<table>] }; array-overlap. nin answers the complement, memberless rows included.
      - `in` string[]
      - `nin` string[]
    - `pipeline_stage_category` object: The account's funnel bucket (one of seven), expanded on the server into the team's company stage sids of those categories: ask by name, never resolve the stages yourself. eq approaching = someone was invited or written to and nobody answered.
      - `eq` 'cold' | 'approaching' | 'engaging' | 'positive' | 'nurture' | 'negative' | 'disqualified'
      - `in` string[]
    - `signals` object[]: ES-only. Named signals of the account, all must hold: its own visit and the account names rolled up over the people to work (disqualified or stoplisted people do not count). Never compose the roll-ups yourself. A person's or a thread's name is a 422.
      - `key` 'awaiting_reply' | 'opened_not_replied' | 'clicked_not_replied' | 'multi_opened' | 'accepted_not_replied' | 'note_read_not_replied' | 'reacted_not_replied' | 'invited_us' | 'followed_us' | 'lead_messaged_first' | 'unanswered_inbound' | 'draft_pending' | 'escalated_open' | 'task_overdue' | 'went_quiet' | 'reactivated' | 'invite_pending' | 'connection_removed' | 'blocked_us' | 'deleted_message' | 'bounced' | 'bounced_hard' | 'complained' | 'booking_link_sent' | 'objective_reached' | 'viewed_our_profile' | 'visited_our_site' | 'visited_not_replied' | 'visited_key_page' | 'multi_visited' | 'submitted_form' | 'company_visited_our_site' | 'no_people' | 'thin_coverage' | 'nobody_reached' | 'no_engagement' | 'no_reply' | 'exhausted' | 'dormant' | 'dm_missing', required: A catalog signal name. Thread and person names: awaiting_reply (our message is the last), opened_not_replied and clicked_not_replied (our email opened or its link clicked, no reply), multi_opened (3+ opens), accepted_not_replied (invite accepted, nothing after), note_read_not_replied (the accept delivered our invite note, no reply), reacted_not_replied (an emoji on our message, no reply), invited_us (their invitation to us, unanswered), followed_us, lead_messaged_first (an inbound thread), unanswered_inbound, draft_pending (an AI draft awaits approval), escalated_open (handed to a person, task open), task_overdue, went_quiet (they had replied, then nothing), reactivated (an inbound after 30+ quiet days), invite_pending (our invite out, neither accepted nor withdrawn), connection_removed, blocked_us, deleted_message, bounced, bounced_hard (the address is gone), complained, booking_link_sent, objective_reached (the live dialog landed its goal), viewed_our_profile. Website names: visited_our_site, visited_not_replied, visited_key_page (a page the team marked key), multi_visited, submitted_form, company_visited_our_site (someone from the company, nobody recognized; a person's and a company's). Account names, companies only (dormant also a person's): no_people (nobody to work), thin_coverage (under 3 people to work), nobody_reached, no_engagement (touched, nothing came back), no_reply (touched, no reply), exhausted (everyone nurture or negative), dormant (touched once, quiet since), dm_missing (a Wrong Decision Maker named, no positive person left). Tracking facts are private: never tell the lead (submitted_form excepted).
      - `age_days` integer: At least this many days on the signal's clock (0 = any). Defaults when omitted: 1 visited_not_replied; 3 awaiting_reply and the *_not_replied names; 14 went_quiet, invite_pending; 30 no_engagement, no_reply; 180 dormant; the rest any age.
    - `data_source_sid` object: Import provenance (ds_sc_…).
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `status` object
      - `eq` 'ok' | 'failed_validation' | 'duplicate' | 'stoplisted'
      - `ne` 'ok' | 'failed_validation' | 'duplicate' | 'stoplisted'
      - `in` string[]
      - `nin` string[]
    - `duplicate_of_sid` object: The copies of a primary: { eq: <primary sid> }. is_null:true = rows that are not flagged duplicates.
      - `eq` string: Company sid (cr_co_…).
      - `in` string[]
      - `is_null` boolean
    - `tag_sids` object: Array-overlap (any of); cr_tg_ sids - resolve labels via tags. nin answers the complement, untagged rows included.
      - `in` string[]
      - `nin` string[]
    - `ln_id` object: Exact LinkedIn company id.
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `ln_nickname` object: Exact page slug; fuzzy matching goes through q.
      - `eq` string
      - `is_null` boolean
    - `domain` object: Lowercased apex; is_null = enrichment gap.
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `name` object: Exact match; substring goes through q.
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `q` string: Free text over name, domain, website, ln_nickname (ES full-text).
    - `created_at` object: ISO 8601 range; combine bounds in one object.
      - `gte` string
      - `lte` string
      - `gt` string
      - `lt` string
    - `updated_at` object
      - `gte` string
      - `lte` string
      - `gt` string
      - `lt` string
    - `deleted_at` object: Default scope is { is_null: true } (live rows).
      - `gte` string
      - `lte` string
      - `is_null` boolean
  - `limit` integer: Default 20.

## Response `200`

`action` success envelope.

- SuggestCompanyFilterValuesResponse
  - `success` true, required
  - `operation` 'action', required
  - `action` string, required: kebab-case verb; matches the route segment.
  - `item` unknown, required
  - `result` object, required
    - `suggestions` object[], required
      - `value` string, required: Distinct field value (cr_tg_ sid for tag_sids).
      - `count` integer, required: Matching rows within the filter scope.
  - `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.

## 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)
