---
title: "Estimate playtable field AI cost"
method: POST
path: "/api/playtable-fields/estimate-ai-cost"
tags: ["playtable_fields"]
---

# Estimate playtable field AI cost

`POST /api/playtable-fields/estimate-ai-cost`

## Request

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

What a Use AI column costs a row of this grid before the save, in credits: the draft's prompt rendered on the grid's first rows, read as tokens, priced per token for every model of the catalog, a range per model (the smallest row to the largest with a typical answer) and a ceiling (the largest row with the model's output cap). No writes, no charges. Use it to quote a column or to pick a model; the run charges each row its real price.

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

## Request body

- EstimatePlaytableFieldAiCostRequest: Request body of `estimate_playtable_field_ai_cost`.
  - `playtable_sid` string, required: Owner playtable sid (pt_tb_…).
  - `object_type` 'people' | 'company', required: The grid the column sits on: people or company.
  - `payload` object, required: The drawer's live draft (prompt, model, output, options, web_search), validated exactly like create_playtable_field's. The prompt is rendered on the rows, so a {{record.<slug>}} that pulls a whole enrichment cell is priced at its size.
    - `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.

## Response `200`

`action` success envelope.

- EstimatePlaytableFieldAiCostResponse
  - `success` true, required
  - `operation` 'action', required
  - `action` string, required: kebab-case verb; matches the route segment.
  - `item` unknown, required
  - `result` object, required
    - `rows_sampled` integer, required: Rows the prompt was rendered on (the grid's first rows, up to 20); 0 when the grid has none and the prompt's own words were read.
    - `rows_skipped` integer, required: Rows of the sample the run would skip for an empty context (every variable resolved to nothing): free.
    - `rows_total` integer, required: Rows of the grid the sample stands for.
    - `tokens_in` object, required: The rendered prompt with the answer instruction, in tokens by the platform's estimate (2.6 bytes a token).
      - `min` integer, required
      - `avg` integer, required
      - `max` integer, required
    - `tokens_out_expected` integer, required: The answer a typical row gets: the response, its reasoning and a confidence word.
    - `prices` object[], required: One price per model of the catalog; pick payload.model's (or the default for auto).
      - `provider` string, required
      - `model` string, required
      - `name` string, required
      - `default` boolean, required: The model payload.model auto resolves to.
      - `web_search` boolean, required: The model can run web research.
      - `price_min` number, required: Credits: the smallest sampled row with a typical answer.
      - `price_expected` number, required: Credits: the average row with a typical answer, what one row is expected to cost.
      - `price_max` number, required: Credits: the largest sampled row with a typical answer; min to max is the range a drawer shows.
      - `price_cap` number, required: Credits: the largest row with the model's whole output cap, what a run's max_budget is set from.
      - `price_with_web_search_min` number, nullable, required: The same four with web research on (the search tool's overhead on every prompt, then none, one, one and the cap of searches); null when the model cannot search.
      - `price_with_web_search_expected` number, nullable, required
      - `price_with_web_search_max` number, nullable, required
      - `price_with_web_search_cap` number, nullable, 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)
