---
title: "Preview playtable field run"
method: POST
path: "/api/playtable-fields/preview-run"
tags: ["playtable_fields"]
---

# Preview playtable field run

`POST /api/playtable-fields/preview-run`

## Request

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

Run an unsaved action_ai_research column against ONE row and answer what its cell would hold: before the column exists, or with the edited prompt of one that does (the drawer's per-row Preview). The same gate, model resolution and output coercion as the paid run, so a preview never promises what the run refuses. PRICED AS ONE ROW: the platform's charge comes back in credits_charged; a row the gate skips (will_run false, skip_reason run_condition_not_met or empty_context) costs nothing. Writes nothing: no cell, no run, no ledger receipt. Every call asks the model again with a fresh key, so a repeat may answer differently and is charged again. Read value, reasoning and confidence; error_code names a refusal before any charge (model_not_in_catalog, web_search_not_supported), a failed call, or an answer that could not be coerced to payload.output (the model ran and was paid). Show the user the sample and its cost; the whole column is create_playtable_run after estimate_playtable_run.

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

## Request body

- PreviewPlaytableFieldRunRequest: Request body of `preview_playtable_field_run`.
  - `playtable_sid` string, required: Owner playtable sid (pt_tb_…).
  - `object_sid` string, required: The one row to try the draft on (cr_pp_… or cr_co_…), of this table and this team.
  - `type` 'action_ai_research', required: What the draft column is. Only action_ai_research runs inline today: waterfall and tool columns run through the queued executor and have no preview.
  - `payload` object, required: The drawer's live draft (prompt, model, output, options, output_mapping, web_search), validated exactly like create_playtable_field's: a payload that previews is a payload that saves.
    - `prompt` string, required: 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` string, required: 'auto' (gtm-api routes the call) or a concrete gtm-api model id; validated against the gtm-api registry at save.
    - `output` 'text' | 'number' | 'select' | 'json', required: 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` string[], nullable, required: Required (min 1) when output=select; null otherwise.
    - `output_mapping` object[], nullable, required: Project a 'json' result onto people/company attributes, fill-if-empty (max 20); null = no attribute writes. Columns pull via extraction formulas instead.
      - `path` string, required: JSON path into the tool/model result, e.g. $.email or $.techs[0].name.
      - `target` string, required: 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.
    - `web_search` boolean: 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.
  - `run_condition` union: The draft gate; a row it skips costs nothing and answers will_run false. null or absent = no gate.
    - object
      - `and` object[], required
    - object
      - `or` object[], required
    - object
      - `not` object, required: 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.
    - object
      - `any` object, required
        - `path` string, required: Array-valued path - the only way to reach inside an array.
        - `where` object, required: 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.
    - object
      - `field` string, required: Namespaced path: record.<slug> or a built-in object attribute; element-relative inside any.where.
      - `op` object, required
        - `eq` union
          - string
          - number
          - boolean
        - `ne` union
          - string
          - number
          - boolean
        - `in` union[]
          - union
            - string
            - number
            - boolean
        - `nin` union[]
          - union
            - string
            - number
            - boolean
        - `gt` union
          - number
          - string
        - `gte` union
          - number
          - string
        - `lt` union
          - number
          - string
        - `lte` union
          - number
          - string
        - `is_null` boolean
        - `contains` string
        - `not_contains` string
        - `contains_any` string[]
        - `not_contains_any` string[]
        - `starts_with` string
    - unknown

## Response `200`

`action` success envelope.

- PreviewPlaytableFieldRunResponse
  - `success` true, required
  - `operation` 'action', required
  - `action` string, required: kebab-case verb; matches the route segment.
  - `item` unknown, required
  - `result` object, required
    - `object_sid` string, required
    - `will_run` boolean, required: false = the gate or the empty-context rule skipped the row: no call, no charge, skip_reason says which.
    - `skip_reason` string, nullable, required: run_condition_not_met (the gate) or empty_context (every row reference of the prompt resolved to nothing); null when the row ran.
    - `value` string, nullable, required: What the cell would hold; null when the row was skipped, the call failed or the answer could not be coerced to payload.output.
    - `error_code` string, nullable, required: model_not_in_catalog or web_search_not_supported (refused before any charge), a lane code (the call failed), or the coercion failure of an answer the model gave and the team paid for; null on success.
    - `error_message` string, nullable, required
    - `reasoning` string, nullable, required: The model's reasoning when it gave one.
    - `confidence` string, nullable, required
    - `model` string, nullable, required: The model that answered (the resolved one when payload.model is auto); null when nothing was called.
    - `credits_charged` number, required: The platform's own charge for this one row, in credits; 0 on a skip or a refusal before the call.
    - `duration_ms` integer, required
  - `meta` object, required
    - `trace_id` string, required: UUID v7; same 128-bit value as the X-Trace-Id header.
    - `span_id` string, required: 16 hex chars, root span of this request.
    - `timestamp` string, required: ISO 8601 UTC (Y-m-dTH:i:sZ), response time.
    - `duration_ms` integer, required: Server-side wall clock.
    - `team_sid` string, nullable: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends.
    - `actor_type` string, nullable: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends.

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