> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getsales.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Update playtable field

> Partial update of name, type, payload or config; each JSON value is a full replacement, never a deep merge. slug, category and object_type are immutable. Dependency edges are rebuilt and cycle-checked (a cycle is 422). A set or changed scalar formula recomputes the whole column, manually pinned cells included (warn the user when it holds data); action payload or config changes touch only future runs, paid done cells are never re-run by themselves. At least one field.

Contract:
- MCP tool `update_playtable_field`, registry package `mcp.playtables/playtable_fields`, mount `playtables.columns`.
- Operation `update`, response envelope `update`.
- Flags: none.



## OpenAPI

````yaml /api-reference/playtables/openapi.yaml patch /api/playtable-fields/{sid}
openapi: 3.0.3
info:
  title: 'GetSales public contract: gs.service.playtables'
  description: >-
    The data platform and the outreach engine: tables of people and companies,
    their enrichment columns, cells and runs, the data sources that feed them,
    sender profiles, the stoplist, the activity feed, the credit ledger, and the
    multichannel workflows with their per-person journeys and tasks.


    GENERATED. This document is projected from the Zod MCP tool registry in
    `product/mcp/gs.mcp` (one tool per public endpoint, 1:1). Do not edit it by
    hand; edit the tool definition and regenerate with `pnpm openapi:public`.


    Surface: the public `/api` contract of `gs.service.playtables`, 142
    operations. This is the only OpenAPI document the platform publishes.
    Internal (`/internal`) and health endpoints are deliberately absent: they
    are not part of any contract, they can change without notice, and the
    service source is their only description.


    Conventions:

    - Auth is a bearer JWT, optionally narrowed by the `Team-SID` header.

    - Every success body is an MCP envelope: `success: true` plus one typed
    `operation` shape (`search`, `get`, `create`, `update`, `delete`, `metrics`,
    `group_by`, `action`), and a `meta` block with `trace_id` for support.

    - Every failure is the same `McpError` envelope with a code from a fixed
    16-code taxonomy, so a client maps errors once.

    - Lists page with `page_size` (0 to 500, default 50) plus an opaque forward
    `cursor`; `page_size: 0` returns counts only.

    - On `GET` and `DELETE`, object-valued query parameters (`filter`, `sort`)
    travel as JSON text and array-valued ones repeat as `name[]=value`.

    - The MCP-only `_meta` field (usage analytics) never reaches the backend and
    is not part of this contract.
  version: '1.0'
  contact:
    name: GetSales
    url: https://getsales.io
    email: support@getsales.io
  license:
    name: Proprietary
    url: https://getsales.io/terms
servers:
  - url: https://beta.getsales.io/playtables/v1
    description: >-
      Production (the gateway path on the beta ring; the origin is provisioned
      per DEPLOY_MAP.md)
security:
  - BearerJwt: []
    TeamSid: []
tags:
  - name: activities
    description: >-
      Registry package `mcp.playtables/activities`, served on MCP mount
      `playtables.journeys`.
  - name: activity_objects
    description: >-
      Registry package `mcp.playtables/activity_objects`, served on MCP mount
      `playtables.people`.
  - name: companies
    description: >-
      Registry package `mcp.playtables/companies`, served on MCP mount
      `playtables.people`.
  - name: credit_ledger_entries
    description: >-
      Registry package `mcp.playtables/credit_ledger_entries`, served on MCP
      mount `id.billing`.
  - name: data_source_items
    description: >-
      Registry package `mcp.playtables/data_source_items`, served on MCP mount
      `playtables.sources`.
  - name: data_sources
    description: >-
      Registry package `mcp.playtables/data_sources`, served on MCP mount
      `playtables.sources`.
  - name: notes
    description: >-
      Registry package `mcp.playtables/notes`, served on MCP mount
      `playtables.pipeline`.
  - name: people
    description: >-
      Registry package `mcp.playtables/people`, served on MCP mount
      `playtables.people`.
  - name: pipeline_stages
    description: >-
      Registry package `mcp.playtables/pipeline_stages`, served on MCP mount
      `playtables.pipeline`.
  - name: plays
    description: >-
      Registry package `mcp.playtables/plays`, served on MCP mount
      `playtables.pipeline`.
  - name: playtable_field_values
    description: >-
      Registry package `mcp.playtables/playtable_field_values`, served on MCP
      mount `playtables.columns`.
  - name: playtable_fields
    description: >-
      Registry package `mcp.playtables/playtable_fields`, served on MCP mount
      `playtables.columns`.
  - name: playtable_runs
    description: >-
      Registry package `mcp.playtables/playtable_runs`, served on MCP mount
      `playtables.columns`.
  - name: playtable_views
    description: >-
      Registry package `mcp.playtables/playtable_views`, served on MCP mount
      `playtables.tables`.
  - name: playtables
    description: >-
      Registry package `mcp.playtables/playtables`, served on MCP mount
      `playtables.tables`.
  - name: result_pages
    description: >-
      Registry package `mcp.playtables/result_pages`, served on MCP mount
      `playtables.tables`.
  - name: sender_profiles
    description: >-
      Registry package `mcp.playtables/sender_profiles`, served on MCP mount
      `playtables.sources`.
  - name: stoplist_entries
    description: >-
      Registry package `mcp.playtables/stoplist_entries`, served on MCP mount
      `playtables.stoplist`.
  - name: tags
    description: >-
      Registry package `mcp.playtables/tags`, served on MCP mount
      `playtables.pipeline`.
  - name: workflow_attachments
    description: >-
      Registry package `mcp.playtables/workflow_attachments`, served on MCP
      mount `playtables.workflows`.
  - name: workflow_records
    description: >-
      Registry package `mcp.playtables/workflow_records`, served on MCP mount
      `playtables.journeys`.
  - name: workflow_sources
    description: >-
      Registry package `mcp.playtables/workflow_sources`, served on MCP mount
      `playtables.workflows`.
  - name: workflow_tasks
    description: >-
      Registry package `mcp.playtables/workflow_tasks`, served on MCP mount
      `playtables.journeys`.
  - name: workflow_versions
    description: >-
      Registry package `mcp.playtables/workflow_versions`, served on MCP mount
      `playtables.workflows`.
  - name: workflows
    description: >-
      Registry package `mcp.playtables/workflows`, served on MCP mount
      `playtables.workflows`.
paths:
  /api/playtable-fields/{sid}:
    patch:
      tags:
        - playtable_fields
      summary: Update playtable field
      description: >-
        Partial update of name, type, payload or config; each JSON value is a
        full replacement, never a deep merge. slug, category and object_type are
        immutable. Dependency edges are rebuilt and cycle-checked (a cycle is
        422). A set or changed scalar formula recomputes the whole column,
        manually pinned cells included (warn the user when it holds data);
        action payload or config changes touch only future runs, paid done cells
        are never re-run by themselves. At least one field.


        Contract:

        - MCP tool `update_playtable_field`, registry package
        `mcp.playtables/playtable_fields`, mount `playtables.columns`.

        - Operation `update`, response envelope `update`.

        - Flags: none.
      operationId: update_playtable_field
      parameters:
        - name: sid
          in: path
          required: true
          description: Playtable field sid (pt_fd_…).
          schema:
            type: string
            minLength: 18
            maxLength: 18
            pattern: ^pt_fd_
            description: Playtable field sid (pt_fd_…).
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UpdatePlaytableFieldRequest'
      responses:
        '200':
          description: '`update` success envelope.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/UpdatePlaytableFieldResponse'
        4XX:
          $ref: '#/components/responses/McpClientError'
        5XX:
          $ref: '#/components/responses/McpServerError'
components:
  schemas:
    UpdatePlaytableFieldRequest:
      type: object
      description: Request body of `update_playtable_field`.
      properties:
        name:
          type: string
          minLength: 1
          maxLength: 255
          description: New display label (1..255); the slug never changes.
        type:
          type: string
          enum:
            - scalar_text
            - scalar_number
            - scalar_currency
            - scalar_date
            - scalar_url
            - scalar_checkbox
            - scalar_select
            - scalar_multiselect
            - scalar_image
          description: >-
            Type change of a scalar column (scalar to scalar only): every cell
            is re-cast, unconvertible values are flagged is_not_valid, the ES
            slot moves. Widgets and actions never convert.
        payload:
          anyOf:
            - type: object
              properties:
                formula:
                  type: string
                  nullable: true
                  maxLength: 8192
                  description: >-
                    CEL expression, NO {{ }} braces (those are for templates).
                    Reference paths extract typed values:
                    record.<slug>(.<seg>|[N])* - e.g.
                    "record.enrich.contact_info.websites[0].url" (extraction
                    column - the "Add as column" case; backfills all rows on
                    save, re-derives on every source run; absent path → empty
                    cell), and on a people grid
                    company.record.<slug>(.<seg>|[N])* - the linked account's
                    cell in this playtable (a Companies-tab column; on the
                    company grid the account is the row itself). A
                    company.record reference is checked against the Companies
                    tab at save, backfilled the same way, and is NOT re-derived
                    when the account's cell changes later (no cross-object
                    dependency: a snapshot until the column's next recalc). Full
                    CEL computes: operators, ?: conditions, has(), string concat
                    - e.g. 'record.employees > 50 ? 100 : 40'. Syntax errors 422
                    at save; runtime failures land as cell error_msg. Evaluated
                    backend-side; null = manually-entered column.
                    Setting/changing it recomputes EVERY cell including pinned
                    ones. When template is set, this is server-GENERATED from it
                    - send the template instead of hand-writing CEL.
                template:
                  type: string
                  nullable: true
                  maxLength: 8192
                  description: >-
                    The unified authoring source - prose + {{record.<slug>…}} /
                    {{people.<attr>}} / {{company.<attr>}} /
                    {{company.record.<slug>…}} variables, as in a flow-node
                    message: "Hey {{people.first_name}}, saw {{company.name}}!".
                    record.<slug> is THIS tab's columns only
                    ({{record.full_name}} is refused unless a column has that
                    slug); people.<attr> the person's catalog (full_name,
                    first_name, company_name, ln_nickname, work_email, timezone,
                    pipeline_stage_name...); company.<attr> the linked account's
                    (name, domain, website, ln_nickname, people_count...);
                    company.record.<slug> the company tab's columns. An
                    attribute outside the catalogs is refused at save (unknown
                    template variable people.title); people.role and
                    people.headline are derived (the title and the profile line
                    the enrichment, the search record or the inbox observed),
                    and {{record.data_source.position}} still reads the raw
                    record. Compiled into formula on every save: absent value →
                    empty string; a LONE variable
                    ({{record.enrich.company.employees}}) → the bare typed
                    reference (numbers stay numbers); stray braces → 422 on
                    payload.template. Round-trips verbatim. null = formula
                    authored as CEL; template:"" clears both.
                nl_formula:
                  type: string
                  nullable: true
                  maxLength: 2048
                  description: >-
                    Natural-language source of truth the formula was compiled
                    from - agents edit THIS and regenerate formula.
                options:
                  type: array
                  nullable: true
                  items:
                    type: string
                  minItems: 1
                  description: >-
                    Option labels for scalar_select / scalar_multiselect (min
                    1); null for every other scalar type.
                currency:
                  type: string
                  nullable: true
                  pattern: ^[A-Z]{3}$
                  description: >-
                    ISO-4217 code (e.g. USD) for scalar_currency only; null =
                    render default USD; null for every other scalar type.
                option_colors:
                  type: object
                  nullable: true
                  additionalProperties:
                    type: string
                    pattern: ^#[0-9a-f]{6}$
                  description: >-
                    Option name → #rrggbb hex for scalar_select /
                    scalar_multiselect only; keys ⊆ options (min 1 entry - send
                    null instead of an empty map).
              required:
                - formula
                - template
                - nl_formula
                - options
                - currency
                - option_colors
            - type: object
              properties: {}
              additionalProperties: false
              description: >-
                Always {} - widget rendering is type-driven
                (widget_active_workflows and the two channel widgets carry their
                own knobs, below).
            - type: object
              properties:
                workflow_sid:
                  type: string
                  nullable: true
                  minLength: 18
                  maxLength: 18
                  pattern: ^wf_wf_
                  description: >-
                    null = All workflows: a cell counts the lead's live journeys
                    by state. A wf_wf_ sid = Specific workflow: the column is
                    pinned to it, a cell shows the lead's record there, finished
                    too; a live workflow (422 relation_not_found). A pin
                    outlives its workflow.
              required:
                - workflow_sid
              additionalProperties: false
            - type: object
              properties:
                stats_view:
                  type: string
                  enum:
                    - all
                    - last
                    - select
                  description: >-
                    Whose numbers the cell shows: all = every sender profile's
                    facts summed, no face; last = the sender profile that
                    touched the person on that channel last, its face and
                    counters (the default); select = the one named by
                    sender_profile_sid.
                sender_profile_sid:
                  type: string
                  nullable: true
                  minLength: 18
                  maxLength: 18
                  pattern: ^ub_sp_
                  description: >-
                    The sender profile of a select view (ub_sp_): required under
                    select, null otherwise (422 validation_failed). It must name
                    a live sender profile of the team (422 relation_not_found);
                    a deleted pick is kept until another is set.
              required:
                - stats_view
                - sender_profile_sid
              additionalProperties: false
            - type: object
              properties:
                prompt:
                  type: string
                  minLength: 1
                  maxLength: 8192
                  description: >-
                    Twig-templated research instruction; the template's
                    variables, an unknown one 422. What the source found on a
                    person (the role, the location) is in the Data source cell:
                    {{record.data_source}} (its slug on a new table) reads it
                    whole.
                model:
                  type: string
                  minLength: 1
                  maxLength: 128
                  description: >-
                    'auto' (gtm-api routes the call) or a concrete gtm-api model
                    id; validated against the gtm-api registry at save.
                output:
                  type: string
                  enum:
                    - text
                    - number
                    - select
                    - json
                  description: >-
                    Cell shape: text | number (non-numeric model answer → cell
                    error) | select (one of payload.options) | json (extract
                    values into columns via extraction formulas
                    record.<slug>.<path>; push onto people/company attributes
                    via output_mapping).
                options:
                  type: array
                  nullable: true
                  items:
                    type: string
                  minItems: 1
                  description: Required (min 1) when output=select; null otherwise.
                output_mapping:
                  type: array
                  nullable: true
                  items:
                    type: object
                    properties:
                      path:
                        type: string
                        minLength: 1
                        maxLength: 512
                        description: >-
                          JSON path into the tool/model result, e.g. $.email or
                          $.techs[0].name.
                      target:
                        type: string
                        minLength: 1
                        maxLength: 128
                        description: >-
                          Entity-attribute target ONLY: people.<attr> or
                          company.<attr> (writable-attribute registries;
                          fill-if-empty at projection); validated at save. No
                          record.<slug> targets: columns pull via extraction
                          formulas (record.<slug>.<path>), never via push
                          mapping.
                    required:
                      - path
                      - target
                  maxItems: 20
                  description: >-
                    Project a 'json' result onto people/company attributes,
                    fill-if-empty (max 20); null = no attribute writes. Columns
                    pull via extraction formulas instead.
                web_search:
                  type: boolean
                  description: >-
                    Default false: the model answers with the vendor's
                    server-side web search on. A per-model capability: 422
                    relation_not_found at save, and web_search_not_supported on
                    a preview, for a model without it.
              required:
                - prompt
                - model
                - output
                - options
                - output_mapping
            - type: object
              properties:
                steps:
                  type: array
                  items:
                    type: object
                    properties:
                      tool_sid:
                        type: string
                        minLength: 1
                        description: >-
                          The step: a gtm-api tool registry sid, an
                          integration-platform step (in:{provider}.{operation},
                          in:tool.{sid}) or the row itself
                          (row:people.work_email: the row's own address, free,
                          verified unless already ok; people, once). Price
                          validated at save.
                      params:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Tool params; string values may be Twig templates over
                          the same variable namespace.
                    required:
                      - tool_sid
                      - params
                  maxItems: 10
                  description: >-
                    1..10 ordered gtm-api tool steps, first accepted result
                    wins; pass [] when config.preset_sid materializes them
                    server-side (never both).
                stop_on_first:
                  type: boolean
                  description: >-
                    true (default) = stop at the first step returning a
                    non-empty accepted result; false = run all, first non-empty
                    wins.
                output_mapping:
                  type: array
                  nullable: true
                  items:
                    type: object
                    properties:
                      path:
                        type: string
                        minLength: 1
                        maxLength: 512
                        description: >-
                          JSON path into the tool/model result, e.g. $.email or
                          $.techs[0].name.
                      target:
                        type: string
                        minLength: 1
                        maxLength: 128
                        description: >-
                          Entity-attribute target ONLY: people.<attr> or
                          company.<attr> (writable-attribute registries;
                          fill-if-empty at projection); validated at save. No
                          record.<slug> targets: columns pull via extraction
                          formulas (record.<slug>.<path>), never via push
                          mapping.
                    required:
                      - path
                      - target
                  maxItems: 20
                  description: >-
                    Winning step's result → people/company attributes,
                    fill-if-empty (max 20); null = no attribute writes.
                verify:
                  type: object
                  nullable: true
                  properties:
                    tool_sid:
                      type: string
                      minLength: 1
                      description: >-
                        The step: a gtm-api tool registry sid, an
                        integration-platform step (in:{provider}.{operation},
                        in:tool.{sid}) or the row itself (row:people.work_email:
                        the row's own address, free, verified unless already ok;
                        people, once). Price validated at save.
                    params:
                      type: object
                      additionalProperties: {}
                      description: >-
                        Tool params; string values may be Twig templates over
                        the same variable namespace.
                  required:
                    - tool_sid
                    - params
                  description: >-
                    One in:{provider}.email.verify step on every email a finder
                    returns, no params. valid accepts and ends the chain, so
                    does catch_all while accept_catch_all is on; invalid,
                    unknown or a failure rejects, the next finder runs. null =
                    none, first found wins.
                accept_catch_all:
                  type: boolean
                  description: >-
                    true (default): a catch-all address is accepted the moment
                    the verifier says so and the chain stops there. false =
                    catch-all emails are rejected like invalid ones (safe to
                    send only) and the next finder runs. Meaningful only with
                    verify set.
              required:
                - steps
                - stop_on_first
                - output_mapping
            - type: object
              properties:
                tool_sid:
                  type: string
                  minLength: 1
                  description: >-
                    gtm-api tool registry sid (external format); existence +
                    price validated at save.
                params:
                  type: object
                  additionalProperties: {}
                  description: >-
                    Tool params; string values may be Twig templates over the
                    same variable namespace.
                output_mapping:
                  type: array
                  nullable: true
                  items:
                    type: object
                    properties:
                      path:
                        type: string
                        minLength: 1
                        maxLength: 512
                        description: >-
                          JSON path into the tool/model result, e.g. $.email or
                          $.techs[0].name.
                      target:
                        type: string
                        minLength: 1
                        maxLength: 128
                        description: >-
                          Entity-attribute target ONLY: people.<attr> or
                          company.<attr> (writable-attribute registries;
                          fill-if-empty at projection); validated at save. No
                          record.<slug> targets: columns pull via extraction
                          formulas (record.<slug>.<path>), never via push
                          mapping.
                    required:
                      - path
                      - target
                  maxItems: 20
                  description: >-
                    Tool result → people/company attributes, fill-if-empty (max
                    20); null = no attribute writes.
              required:
                - tool_sid
                - params
                - output_mapping
            - type: object
              properties:
                prompt:
                  type: string
                  nullable: true
                  maxLength: 2000
                  description: >-
                    Who to find at each company, in words; null = everyone
                    there. With data_source_sid null on create the server births
                    a find_people source; a new text on update births a new
                    search and parks the old. 422 prohibited beside a picked
                    data_source_sid.
                per_company_limit:
                  type: integer
                  minimum: 1
                  maximum: 25
                  description: >-
                    People taken per company, 1..25 (one search page, by
                    relevance). Default 1. Mirrored onto the column's own
                    search; read from a picked one.
                data_source_sid:
                  type: string
                  nullable: true
                  description: >-
                    The find_people source the cells search (ds_sc_). null on
                    create = the server makes one for the column (the sid comes
                    back). A sid = a find_people search of the SAME table, as is
                    (422 other_table elsewhere, relation_not_found when gone).
                    Never null stored.
                qualify:
                  type: object
                  nullable: true
                  properties:
                    'on':
                      type: boolean
                      description: >-
                        The switch. `on` with no criterion is refused (422 on
                        qualify.criterion, rule required_if).
                    criterion:
                      type: string
                      nullable: true
                      minLength: 1
                      maxLength: 2000
                      description: >-
                        Who passes, in the user's words ("a decision maker at a
                        marketing agency, not a freelancer"). Trimmed; null
                        while the check is off.
                  required:
                    - 'on'
                    - criterion
                  additionalProperties: false
                  description: >-
                    Check on save: {on, criterion} the column's own search takes
                    at every save, judging the people the walk finds before they
                    land (data_sources.qualify); null or absent = no check. 422
                    prohibited beside a picked data_source_sid (it has its own
                    gate).
              required:
                - prompt
                - per_company_limit
                - data_source_sid
          description: Full replacement; shape must still match the row's immutable type.
        config:
          type: object
          properties:
            auto_run:
              type: boolean
              description: >-
                Action auto-fires when a row enters the table / the cell is
                empty (paid: empty→queued only). Default false.
            run_condition:
              anyOf:
                - type: object
                  properties:
                    and:
                      type: array
                      items:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Recursive node: the same object shape repeats here. A
                          static OpenAPI document cannot express the cycle, so
                          this level is documented as an open object.
                      minItems: 1
                      maxItems: 20
                  required:
                    - and
                  additionalProperties: false
                - type: object
                  properties:
                    or:
                      type: array
                      items:
                        type: object
                        additionalProperties: {}
                        description: >-
                          Recursive node: the same object shape repeats here. A
                          static OpenAPI document cannot express the cycle, so
                          this level is documented as an open object.
                      minItems: 1
                      maxItems: 20
                  required:
                    - or
                  additionalProperties: false
                - type: object
                  properties:
                    not:
                      type: object
                      additionalProperties: {}
                      description: >-
                        Recursive node: the same object shape repeats here. A
                        static OpenAPI document cannot express the cycle, so
                        this level is documented as an open object.
                  required:
                    - not
                  additionalProperties: false
                - type: object
                  properties:
                    any:
                      type: object
                      properties:
                        path:
                          type: string
                          minLength: 1
                          description: >-
                            Array-valued path - the only way to reach inside an
                            array.
                        where:
                          type: object
                          additionalProperties: {}
                          description: >-
                            Recursive node: the same object shape repeats here.
                            A static OpenAPI document cannot express the cycle,
                            so this level is documented as an open object.
                      required:
                        - path
                        - where
                      additionalProperties: false
                  required:
                    - any
                  additionalProperties: false
                - type: object
                  properties:
                    field:
                      type: string
                      minLength: 1
                      description: >-
                        Namespaced path: record.<slug> or a built-in object
                        attribute; element-relative inside any.where.
                    op:
                      type: object
                      properties:
                        eq:
                          anyOf:
                            - type: string
                            - type: number
                            - type: boolean
                        ne:
                          anyOf:
                            - type: string
                            - type: number
                            - type: boolean
                        in:
                          type: array
                          items:
                            anyOf:
                              - type: string
                              - type: number
                              - type: boolean
                          minItems: 1
                          maxItems: 100
                        nin:
                          type: array
                          items:
                            anyOf:
                              - type: string
                              - type: number
                              - type: boolean
                          minItems: 1
                          maxItems: 100
                        gt:
                          anyOf:
                            - type: number
                            - type: string
                        gte:
                          anyOf:
                            - type: number
                            - type: string
                        lt:
                          anyOf:
                            - type: number
                            - type: string
                        lte:
                          anyOf:
                            - type: number
                            - type: string
                        is_null:
                          type: boolean
                        contains:
                          type: string
                          minLength: 1
                        not_contains:
                          type: string
                          minLength: 1
                        contains_any:
                          type: array
                          items:
                            type: string
                            minLength: 1
                          minItems: 1
                          maxItems: 50
                        not_contains_any:
                          type: array
                          items:
                            type: string
                            minLength: 1
                          minItems: 1
                          maxItems: 50
                        starts_with:
                          type: string
                          minLength: 1
                      additionalProperties: false
                  required:
                    - field
                    - op
                  additionalProperties: false
                - {}
              description: >-
                Per-row filter-AST gate (§4.18 atoms, strict mode); unmet → cell
                status run_condition_not_met; null = always run.
            nl_condition:
              type: string
              nullable: true
              maxLength: 2048
              description: >-
                Natural-language source of truth for run_condition - agents edit
                THIS and regenerate the AST.
            daily_credit_limit:
              type: integer
              nullable: true
              minimum: 0
              exclusiveMinimum: true
              description: >-
                Max credits this field may spend per UTC day (int > 0, enforced
                at run time); null = no cap.
            preset_sid:
              type: string
              nullable: true
              description: >-
                gtm-api preset sid (external) that materializes waterfall steps
                at save; action_waterfall only, mutually exclusive with
                hand-built steps. null otherwise.
          required:
            - auto_run
            - run_condition
            - nl_condition
            - daily_credit_limit
            - preset_sid
          description: >-
            Full replacement; action fields only (non-default on scalar/widget →
            422).
    UpdatePlaytableFieldResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
        operation:
          type: string
          enum:
            - update
        item:
          type: object
          properties:
            sid:
              type: string
            team_sid:
              type: string
            playtable_sid:
              type: string
            object_type:
              type: string
              enum:
                - people
                - company
              description: >-
                Object grid this field belongs to: people or company rows. Fixed
                at create.
            name:
              type: string
              description: Display label, freely editable.
            slug:
              type: string
              description: >-
                Template-variable name ({{record.<slug>}}); unique per
                playtable, IMMUTABLE after create.
            category:
              type: string
              enum:
                - scalar
                - widget
                - action
              description: >-
                scalar = data column (optional free formula) | widget = live CRM
                projection, no cells | action = paid executor. Derived from the
                type prefix - never user-supplied.
            type:
              type: string
              enum:
                - scalar_text
                - scalar_number
                - scalar_currency
                - scalar_date
                - scalar_url
                - scalar_checkbox
                - scalar_select
                - scalar_multiselect
                - scalar_image
                - widget_data_source
                - widget_tags
                - widget_active_workflows
                - widget_notes
                - widget_company
                - widget_linkedin_id
                - widget_linkedin_channel
                - widget_work_email
                - widget_personal_email
                - widget_email_channel
                - widget_phones
                - widget_phone_channel
                - widget_last_touch
                - widget_activity
                - widget_deal_size
                - widget_website
                - widget_people_summary
                - widget_ai_sdr
                - action_ai_research
                - action_waterfall
                - action_gtm_tool
                - action_find_people
              description: >-
                The category derives from the prefix. Scalar and the generic
                action types fit both grids; action_find_people is company-only.
                Widgets: data_source, tags, last_touch, activity on both;
                deal_size, website, people_summary company-only; the rest
                people-only.
            payload:
              anyOf:
                - type: object
                  properties:
                    formula:
                      type: string
                      nullable: true
                      maxLength: 8192
                      description: >-
                        CEL expression, NO {{ }} braces (those are for
                        templates). Reference paths extract typed values:
                        record.<slug>(.<seg>|[N])* - e.g.
                        "record.enrich.contact_info.websites[0].url" (extraction
                        column - the "Add as column" case; backfills all rows on
                        save, re-derives on every source run; absent path →
                        empty cell), and on a people grid
                        company.record.<slug>(.<seg>|[N])* - the linked
                        account's cell in this playtable (a Companies-tab
                        column; on the company grid the account is the row
                        itself). A company.record reference is checked against
                        the Companies tab at save, backfilled the same way, and
                        is NOT re-derived when the account's cell changes later
                        (no cross-object dependency: a snapshot until the
                        column's next recalc). Full CEL computes: operators, ?:
                        conditions, has(), string concat - e.g.
                        'record.employees > 50 ? 100 : 40'. Syntax errors 422 at
                        save; runtime failures land as cell error_msg. Evaluated
                        backend-side; null = manually-entered column.
                        Setting/changing it recomputes EVERY cell including
                        pinned ones. When template is set, this is
                        server-GENERATED from it - send the template instead of
                        hand-writing CEL.
                    template:
                      type: string
                      nullable: true
                      maxLength: 8192
                      description: >-
                        The unified authoring source - prose +
                        {{record.<slug>…}} / {{people.<attr>}} /
                        {{company.<attr>}} / {{company.record.<slug>…}}
                        variables, as in a flow-node message: "Hey
                        {{people.first_name}}, saw {{company.name}}!".
                        record.<slug> is THIS tab's columns only
                        ({{record.full_name}} is refused unless a column has
                        that slug); people.<attr> the person's catalog
                        (full_name, first_name, company_name, ln_nickname,
                        work_email, timezone, pipeline_stage_name...);
                        company.<attr> the linked account's (name, domain,
                        website, ln_nickname, people_count...);
                        company.record.<slug> the company tab's columns. An
                        attribute outside the catalogs is refused at save
                        (unknown template variable people.title); people.role
                        and people.headline are derived (the title and the
                        profile line the enrichment, the search record or the
                        inbox observed), and {{record.data_source.position}}
                        still reads the raw record. Compiled into formula on
                        every save: absent value → empty string; a LONE variable
                        ({{record.enrich.company.employees}}) → the bare typed
                        reference (numbers stay numbers); stray braces → 422 on
                        payload.template. Round-trips verbatim. null = formula
                        authored as CEL; template:"" clears both.
                    nl_formula:
                      type: string
                      nullable: true
                      maxLength: 2048
                      description: >-
                        Natural-language source of truth the formula was
                        compiled from - agents edit THIS and regenerate formula.
                    options:
                      type: array
                      nullable: true
                      items:
                        type: string
                      minItems: 1
                      description: >-
                        Option labels for scalar_select / scalar_multiselect
                        (min 1); null for every other scalar type.
                    currency:
                      type: string
                      nullable: true
                      pattern: ^[A-Z]{3}$
                      description: >-
                        ISO-4217 code (e.g. USD) for scalar_currency only; null
                        = render default USD; null for every other scalar type.
                    option_colors:
                      type: object
                      nullable: true
                      additionalProperties:
                        type: string
                        pattern: ^#[0-9a-f]{6}$
                      description: >-
                        Option name → #rrggbb hex for scalar_select /
                        scalar_multiselect only; keys ⊆ options (min 1 entry -
                        send null instead of an empty map).
                  required:
                    - formula
                    - template
                    - nl_formula
                    - options
                    - currency
                    - option_colors
                - type: object
                  properties: {}
                  additionalProperties: false
                  description: >-
                    Always {} - widget rendering is type-driven
                    (widget_active_workflows and the two channel widgets carry
                    their own knobs, below).
                - type: object
                  properties:
                    workflow_sid:
                      type: string
                      nullable: true
                      minLength: 18
                      maxLength: 18
                      pattern: ^wf_wf_
                      description: >-
                        null = All workflows: a cell counts the lead's live
                        journeys by state. A wf_wf_ sid = Specific workflow: the
                        column is pinned to it, a cell shows the lead's record
                        there, finished too; a live workflow (422
                        relation_not_found). A pin outlives its workflow.
                  required:
                    - workflow_sid
                  additionalProperties: false
                - type: object
                  properties:
                    stats_view:
                      type: string
                      enum:
                        - all
                        - last
                        - select
                      description: >-
                        Whose numbers the cell shows: all = every sender
                        profile's facts summed, no face; last = the sender
                        profile that touched the person on that channel last,
                        its face and counters (the default); select = the one
                        named by sender_profile_sid.
                    sender_profile_sid:
                      type: string
                      nullable: true
                      minLength: 18
                      maxLength: 18
                      pattern: ^ub_sp_
                      description: >-
                        The sender profile of a select view (ub_sp_): required
                        under select, null otherwise (422 validation_failed). It
                        must name a live sender profile of the team (422
                        relation_not_found); a deleted pick is kept until
                        another is set.
                  required:
                    - stats_view
                    - sender_profile_sid
                  additionalProperties: false
                - type: object
                  properties:
                    prompt:
                      type: string
                      minLength: 1
                      maxLength: 8192
                      description: >-
                        Twig-templated research instruction; the template's
                        variables, an unknown one 422. What the source found on
                        a person (the role, the location) is in the Data source
                        cell: {{record.data_source}} (its slug on a new table)
                        reads it whole.
                    model:
                      type: string
                      minLength: 1
                      maxLength: 128
                      description: >-
                        'auto' (gtm-api routes the call) or a concrete gtm-api
                        model id; validated against the gtm-api registry at
                        save.
                    output:
                      type: string
                      enum:
                        - text
                        - number
                        - select
                        - json
                      description: >-
                        Cell shape: text | number (non-numeric model answer →
                        cell error) | select (one of payload.options) | json
                        (extract values into columns via extraction formulas
                        record.<slug>.<path>; push onto people/company
                        attributes via output_mapping).
                    options:
                      type: array
                      nullable: true
                      items:
                        type: string
                      minItems: 1
                      description: Required (min 1) when output=select; null otherwise.
                    output_mapping:
                      type: array
                      nullable: true
                      items:
                        type: object
                        properties:
                          path:
                            type: string
                            minLength: 1
                            maxLength: 512
                            description: >-
                              JSON path into the tool/model result, e.g. $.email
                              or $.techs[0].name.
                          target:
                            type: string
                            minLength: 1
                            maxLength: 128
                            description: >-
                              Entity-attribute target ONLY: people.<attr> or
                              company.<attr> (writable-attribute registries;
                              fill-if-empty at projection); validated at save.
                              No record.<slug> targets: columns pull via
                              extraction formulas (record.<slug>.<path>), never
                              via push mapping.
                        required:
                          - path
                          - target
                      maxItems: 20
                      description: >-
                        Project a 'json' result onto people/company attributes,
                        fill-if-empty (max 20); null = no attribute writes.
                        Columns pull via extraction formulas instead.
                    web_search:
                      type: boolean
                      description: >-
                        Default false: the model answers with the vendor's
                        server-side web search on. A per-model capability: 422
                        relation_not_found at save, and web_search_not_supported
                        on a preview, for a model without it.
                  required:
                    - prompt
                    - model
                    - output
                    - options
                    - output_mapping
                - type: object
                  properties:
                    steps:
                      type: array
                      items:
                        type: object
                        properties:
                          tool_sid:
                            type: string
                            minLength: 1
                            description: >-
                              The step: a gtm-api tool registry sid, an
                              integration-platform step
                              (in:{provider}.{operation}, in:tool.{sid}) or the
                              row itself (row:people.work_email: the row's own
                              address, free, verified unless already ok; people,
                              once). Price validated at save.
                          params:
                            type: object
                            additionalProperties: {}
                            description: >-
                              Tool params; string values may be Twig templates
                              over the same variable namespace.
                        required:
                          - tool_sid
                          - params
                      maxItems: 10
                      description: >-
                        1..10 ordered gtm-api tool steps, first accepted result
                        wins; pass [] when config.preset_sid materializes them
                        server-side (never both).
                    stop_on_first:
                      type: boolean
                      description: >-
                        true (default) = stop at the first step returning a
                        non-empty accepted result; false = run all, first
                        non-empty wins.
                    output_mapping:
                      type: array
                      nullable: true
                      items:
                        type: object
                        properties:
                          path:
                            type: string
                            minLength: 1
                            maxLength: 512
                            description: >-
                              JSON path into the tool/model result, e.g. $.email
                              or $.techs[0].name.
                          target:
                            type: string
                            minLength: 1
                            maxLength: 128
                            description: >-
                              Entity-attribute target ONLY: people.<attr> or
                              company.<attr> (writable-attribute registries;
                              fill-if-empty at projection); validated at save.
                              No record.<slug> targets: columns pull via
                              extraction formulas (record.<slug>.<path>), never
                              via push mapping.
                        required:
                          - path
                          - target
                      maxItems: 20
                      description: >-
                        Winning step's result → people/company attributes,
                        fill-if-empty (max 20); null = no attribute writes.
                    verify:
                      type: object
                      nullable: true
                      properties:
                        tool_sid:
                          type: string
                          minLength: 1
                          description: >-
                            The step: a gtm-api tool registry sid, an
                            integration-platform step
                            (in:{provider}.{operation}, in:tool.{sid}) or the
                            row itself (row:people.work_email: the row's own
                            address, free, verified unless already ok; people,
                            once). Price validated at save.
                        params:
                          type: object
                          additionalProperties: {}
                          description: >-
                            Tool params; string values may be Twig templates
                            over the same variable namespace.
                      required:
                        - tool_sid
                        - params
                      description: >-
                        One in:{provider}.email.verify step on every email a
                        finder returns, no params. valid accepts and ends the
                        chain, so does catch_all while accept_catch_all is on;
                        invalid, unknown or a failure rejects, the next finder
                        runs. null = none, first found wins.
                    accept_catch_all:
                      type: boolean
                      description: >-
                        true (default): a catch-all address is accepted the
                        moment the verifier says so and the chain stops there.
                        false = catch-all emails are rejected like invalid ones
                        (safe to send only) and the next finder runs. Meaningful
                        only with verify set.
                  required:
                    - steps
                    - stop_on_first
                    - output_mapping
                - type: object
                  properties:
                    tool_sid:
                      type: string
                      minLength: 1
                      description: >-
                        gtm-api tool registry sid (external format); existence +
                        price validated at save.
                    params:
                      type: object
                      additionalProperties: {}
                      description: >-
                        Tool params; string values may be Twig templates over
                        the same variable namespace.
                    output_mapping:
                      type: array
                      nullable: true
                      items:
                        type: object
                        properties:
                          path:
                            type: string
                            minLength: 1
                            maxLength: 512
                            description: >-
                              JSON path into the tool/model result, e.g. $.email
                              or $.techs[0].name.
                          target:
                            type: string
                            minLength: 1
                            maxLength: 128
                            description: >-
                              Entity-attribute target ONLY: people.<attr> or
                              company.<attr> (writable-attribute registries;
                              fill-if-empty at projection); validated at save.
                              No record.<slug> targets: columns pull via
                              extraction formulas (record.<slug>.<path>), never
                              via push mapping.
                        required:
                          - path
                          - target
                      maxItems: 20
                      description: >-
                        Tool result → people/company attributes, fill-if-empty
                        (max 20); null = no attribute writes.
                  required:
                    - tool_sid
                    - params
                    - output_mapping
                - type: object
                  properties:
                    prompt:
                      type: string
                      nullable: true
                      maxLength: 2000
                      description: >-
                        Who to find at each company, in words; null = everyone
                        there. With data_source_sid null on create the server
                        births a find_people source; a new text on update births
                        a new search and parks the old. 422 prohibited beside a
                        picked data_source_sid.
                    per_company_limit:
                      type: integer
                      minimum: 1
                      maximum: 25
                      description: >-
                        People taken per company, 1..25 (one search page, by
                        relevance). Default 1. Mirrored onto the column's own
                        search; read from a picked one.
                    data_source_sid:
                      type: string
                      nullable: true
                      description: >-
                        The find_people source the cells search (ds_sc_). null
                        on create = the server makes one for the column (the sid
                        comes back). A sid = a find_people search of the SAME
                        table, as is (422 other_table elsewhere,
                        relation_not_found when gone). Never null stored.
                    qualify:
                      type: object
                      nullable: true
                      properties:
                        'on':
                          type: boolean
                          description: >-
                            The switch. `on` with no criterion is refused (422
                            on qualify.criterion, rule required_if).
                        criterion:
                          type: string
                          nullable: true
                          minLength: 1
                          maxLength: 2000
                          description: >-
                            Who passes, in the user's words ("a decision maker
                            at a marketing agency, not a freelancer"). Trimmed;
                            null while the check is off.
                      required:
                        - 'on'
                        - criterion
                      additionalProperties: false
                      description: >-
                        Check on save: {on, criterion} the column's own search
                        takes at every save, judging the people the walk finds
                        before they land (data_sources.qualify); null or absent
                        = no check. 422 prohibited beside a picked
                        data_source_sid (it has its own gate).
                  required:
                    - prompt
                    - per_company_limit
                    - data_source_sid
              description: >-
                Per-type payload; the discriminator is the row's type column,
                not an inner key - the shape must match type (scalar / widget /
                active_workflows / channel / ai_research / waterfall / gtm_tool
                / find_people branches) or the save fails with 422.
            config:
              type: object
              properties:
                auto_run:
                  type: boolean
                  description: >-
                    Action auto-fires when a row enters the table / the cell is
                    empty (paid: empty→queued only). Default false.
                run_condition:
                  anyOf:
                    - type: object
                      properties:
                        and:
                          type: array
                          items:
                            type: object
                            additionalProperties: {}
                            description: >-
                              Recursive node: the same object shape repeats
                              here. A static OpenAPI document cannot express the
                              cycle, so this level is documented as an open
                              object.
                          minItems: 1
                          maxItems: 20
                      required:
                        - and
                      additionalProperties: false
                    - type: object
                      properties:
                        or:
                          type: array
                          items:
                            type: object
                            additionalProperties: {}
                            description: >-
                              Recursive node: the same object shape repeats
                              here. A static OpenAPI document cannot express the
                              cycle, so this level is documented as an open
                              object.
                          minItems: 1
                          maxItems: 20
                      required:
                        - or
                      additionalProperties: false
                    - type: object
                      properties:
                        not:
                          type: object
                          additionalProperties: {}
                          description: >-
                            Recursive node: the same object shape repeats here.
                            A static OpenAPI document cannot express the cycle,
                            so this level is documented as an open object.
                      required:
                        - not
                      additionalProperties: false
                    - type: object
                      properties:
                        any:
                          type: object
                          properties:
                            path:
                              type: string
                              minLength: 1
                              description: >-
                                Array-valued path - the only way to reach inside
                                an array.
                            where:
                              type: object
                              additionalProperties: {}
                              description: >-
                                Recursive node: the same object shape repeats
                                here. A static OpenAPI document cannot express
                                the cycle, so this level is documented as an
                                open object.
                          required:
                            - path
                            - where
                          additionalProperties: false
                      required:
                        - any
                      additionalProperties: false
                    - type: object
                      properties:
                        field:
                          type: string
                          minLength: 1
                          description: >-
                            Namespaced path: record.<slug> or a built-in object
                            attribute; element-relative inside any.where.
                        op:
                          type: object
                          properties:
                            eq:
                              anyOf:
                                - type: string
                                - type: number
                                - type: boolean
                            ne:
                              anyOf:
                                - type: string
                                - type: number
                                - type: boolean
                            in:
                              type: array
                              items:
                                anyOf:
                                  - type: string
                                  - type: number
                                  - type: boolean
                              minItems: 1
                              maxItems: 100
                            nin:
                              type: array
                              items:
                                anyOf:
                                  - type: string
                                  - type: number
                                  - type: boolean
                              minItems: 1
                              maxItems: 100
                            gt:
                              anyOf:
                                - type: number
                                - type: string
                            gte:
                              anyOf:
                                - type: number
                                - type: string
                            lt:
                              anyOf:
                                - type: number
                                - type: string
                            lte:
                              anyOf:
                                - type: number
                                - type: string
                            is_null:
                              type: boolean
                            contains:
                              type: string
                              minLength: 1
                            not_contains:
                              type: string
                              minLength: 1
                            contains_any:
                              type: array
                              items:
                                type: string
                                minLength: 1
                              minItems: 1
                              maxItems: 50
                            not_contains_any:
                              type: array
                              items:
                                type: string
                                minLength: 1
                              minItems: 1
                              maxItems: 50
                            starts_with:
                              type: string
                              minLength: 1
                          additionalProperties: false
                      required:
                        - field
                        - op
                      additionalProperties: false
                    - {}
                  description: >-
                    Per-row filter-AST gate (§4.18 atoms, strict mode); unmet →
                    cell status run_condition_not_met; null = always run.
                nl_condition:
                  type: string
                  nullable: true
                  maxLength: 2048
                  description: >-
                    Natural-language source of truth for run_condition - agents
                    edit THIS and regenerate the AST.
                daily_credit_limit:
                  type: integer
                  nullable: true
                  minimum: 0
                  exclusiveMinimum: true
                  description: >-
                    Max credits this field may spend per UTC day (int > 0,
                    enforced at run time); null = no cap.
                preset_sid:
                  type: string
                  nullable: true
                  description: >-
                    gtm-api preset sid (external) that materializes waterfall
                    steps at save; action_waterfall only, mutually exclusive
                    with hand-built steps. null otherwise.
              required:
                - auto_run
                - run_condition
                - nl_condition
                - daily_credit_limit
                - preset_sid
            backfill:
              type: object
              nullable: true
              properties:
                status:
                  type: string
                  enum:
                    - queued
                    - running
                    - done
                    - failed
                scanned:
                  type: integer
                  minimum: 0
                  description: Objects the scan has visited so far.
                total:
                  type: integer
                  nullable: true
                  minimum: 0
                  description: >-
                    The scan size, known once the job starts (null while
                    queued).
                queued_at:
                  type: string
                  nullable: true
                  description: 'ISO 8601 UTC: when the column started owing its backfill.'
                started_at:
                  type: string
                  nullable: true
                  description: 'ISO 8601 UTC: when the job took it.'
                finished_at:
                  type: string
                  nullable: true
                  description: 'ISO 8601 UTC: when it ended, done or failed.'
                error:
                  type: string
                  nullable: true
                  description: >-
                    A reason token (backfill_failed) on failed, never an
                    exception message.
              required:
                - status
                - scanned
                - total
                - queued_at
                - started_at
                - finished_at
                - error
              description: >-
                The formula column's backfill ledger (see
                PlaytableFieldBackfill); null on a column with no formula.
            created_by:
              type: object
              properties:
                actor_type:
                  type: string
                  enum:
                    - user
                    - support
                    - api_key
                    - system
                    - agent
                actor_sid:
                  type: string
                  nullable: true
                team_sid:
                  type: string
                actor_name:
                  type: string
                  nullable: true
                  description: >-
                    The OAuth client that acted ("Claude", "n8n"); null for a
                    user, an API key or a system job.
                oauth_client_sid:
                  type: string
                  nullable: true
                  description: The acting OAuth client (id_oc_*); null off the OAuth path.
                reason:
                  type: string
                  nullable: true
                  description: >-
                    Why a system actor wrote the row (snapshot_capture_job,
                    ...); null otherwise.
                permissions:
                  type: object
                  additionalProperties: {}
                  description: >-
                    Internal audit context: the grant set the actor held at
                    write time. Not a contract.
                cluster_id:
                  type: integer
                  nullable: true
                  description: 'Internal audit context: the cluster that served the write.'
                trace_id:
                  type: string
                  nullable: true
                  description: >-
                    Internal audit context: the trace id of the request that
                    wrote the row.
              required:
                - actor_type
                - actor_sid
                - team_sid
                - permissions
            deleted_by:
              type: object
              nullable: true
              properties:
                actor_type:
                  type: string
                  enum:
                    - user
                    - support
                    - api_key
                    - system
                    - agent
                actor_sid:
                  type: string
                  nullable: true
                team_sid:
                  type: string
                actor_name:
                  type: string
                  nullable: true
                  description: >-
                    The OAuth client that acted ("Claude", "n8n"); null for a
                    user, an API key or a system job.
                oauth_client_sid:
                  type: string
                  nullable: true
                  description: The acting OAuth client (id_oc_*); null off the OAuth path.
                reason:
                  type: string
                  nullable: true
                  description: >-
                    Why a system actor wrote the row (snapshot_capture_job,
                    ...); null otherwise.
                permissions:
                  type: object
                  additionalProperties: {}
                  description: >-
                    Internal audit context: the grant set the actor held at
                    write time. Not a contract.
                cluster_id:
                  type: integer
                  nullable: true
                  description: 'Internal audit context: the cluster that served the write.'
                trace_id:
                  type: string
                  nullable: true
                  description: >-
                    Internal audit context: the trace id of the request that
                    wrote the row.
              required:
                - actor_type
                - actor_sid
                - team_sid
                - permissions
            created_at:
              type: string
            updated_at:
              type: string
            deleted_at:
              type: string
              nullable: true
          required:
            - sid
            - team_sid
            - playtable_sid
            - object_type
            - name
            - slug
            - category
            - type
            - payload
            - config
            - backfill
            - created_by
            - deleted_by
            - created_at
            - updated_at
            - deleted_at
        updated_fields:
          type: array
          items:
            type: string
        previous_values:
          type: object
          additionalProperties: {}
        kept_fields:
          type: array
          items:
            type: string
          description: >-
            The fields this write did not change because the person's own value
            stands on them (stamped person); read the item for what landed.
        meta:
          type: object
          properties:
            trace_id:
              type: string
              description: UUID v7; same 128-bit value as the X-Trace-Id header.
            span_id:
              type: string
              pattern: ^[0-9a-f]{16}$
              description: 16 hex chars, root span of this request.
            timestamp:
              type: string
              description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time.
            duration_ms:
              type: integer
              minimum: 0
              description: Server-side wall clock.
            team_sid:
              type: string
              nullable: true
              description: >-
                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:
              type: string
              nullable: true
              description: >-
                user | agent | api_key | system. Null when unauthenticated;
                absent from pre-2026-08-20 backends.
          required:
            - trace_id
            - span_id
            - timestamp
            - duration_ms
      required:
        - success
        - operation
        - item
        - updated_fields
        - previous_values
        - meta
    McpError:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - 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
                - internal_error
                - service_unavailable
                - not_implemented
            message:
              type: string
            recoverable:
              type: boolean
            suggestion:
              type: string
            field_errors:
              type: object
              additionalProperties:
                type: array
                items:
                  type: object
                  properties:
                    rule:
                      type: string
                    message:
                      type: string
                  required:
                    - rule
                    - message
            blockers:
              type: array
              items:
                type: object
                properties:
                  type:
                    type: string
                    description: >-
                      Machine-readable blocker type (active_flow, pending_tasks,
                      …).
                  severity:
                    type: string
                    enum:
                      - hard
                      - soft
                    description: >-
                      hard = external action required; soft = acknowledge is
                      enough.
                  description:
                    type: string
                  entity_sid:
                    type: string
                    nullable: true
                  count:
                    type: integer
                  resolution:
                    type: string
                    description: 'Hard: tool name to call. Soft: code for acknowledge[].'
                  resolution_hint:
                    type: string
                required:
                  - type
                  - severity
                  - description
                  - entity_sid
                  - resolution
                  - resolution_hint
            context:
              type: object
              additionalProperties: {}
          required:
            - code
            - message
            - recoverable
        meta:
          type: object
          properties:
            trace_id:
              type: string
              description: UUID v7; same 128-bit value as the X-Trace-Id header.
            span_id:
              type: string
              pattern: ^[0-9a-f]{16}$
              description: 16 hex chars, root span of this request.
            timestamp:
              type: string
              description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time.
            duration_ms:
              type: integer
              minimum: 0
              description: Server-side wall clock.
            team_sid:
              type: string
              nullable: true
              description: >-
                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:
              type: string
              nullable: true
              description: >-
                user | agent | api_key | system. Null when unauthenticated;
                absent from pre-2026-08-20 backends.
          required:
            - trace_id
            - span_id
            - timestamp
            - duration_ms
      required:
        - success
        - error
  responses:
    McpClientError:
      description: >-
        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.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/McpError'
    McpServerError:
      description: >-
        MCP error envelope with `error.code` internal_error or
        service_unavailable.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/McpError'
  securitySchemes:
    BearerJwt:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Access token issued by gs.service.id. Its `access_identity` claim
        carries `team_sid`, `actor_sid` and `actor_type`, and that team scope is
        authoritative.
    TeamSid:
      type: apiKey
      in: header
      name: Team-SID
      description: >-
        Team scope for tokens that do not carry one. Ignored when the token
        already names a team.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.