# Preview Chat Analysis

`POST /v1/chats/{chat_id}/analysis/preview`

Try an analysis definition against an ended chat. Nothing is saved; costs one model call.

Authenticate with `Authorization: Bearer $TALQING_API_KEY`. Errors use the shared envelope: https://docs.talqing.com/api-reference/errors.md

## OpenAPI

```json
{
 "openapi":"3.1.0",
 "servers":[
  {
   "description":"Talqing API",
   "url":"https://api.talqing.com"
  }
 ],
 "paths":{
  "/v1/chats/{chat_id}/analysis/preview":{
   "post":{
    "description":"Try an analysis definition against an ended chat. Nothing is saved; costs one model call.",
    "operationId":"chats.analysis.preview",
    "parameters":[
     {
      "in":"path",
      "name":"chat_id",
      "required":true,
      "schema":{
       "format":"uuid",
       "title":"Chat Id",
       "type":"string"
      }
     }
    ],
    "requestBody":{
     "content":{
      "application/json":{
       "schema":{
        "$ref":"#/components/schemas/PreviewAnalysisRequest"
       }
      }
     },
     "required":true
    },
    "responses":{
     "200":{
      "content":{
       "application/json":{
        "schema":{
         "$ref":"#/components/schemas/PreviewAnalysisResponse"
        }
       }
      },
      "description":"Successful Response"
     },
     "400":{
      "$ref":"#/components/responses/BadRequest"
     },
     "401":{
      "$ref":"#/components/responses/Unauthorized"
     },
     "403":{
      "$ref":"#/components/responses/Forbidden"
     },
     "404":{
      "$ref":"#/components/responses/NotFound"
     },
     "409":{
      "$ref":"#/components/responses/Conflict"
     },
     "422":{
      "$ref":"#/components/responses/ValidationFailed"
     },
     "default":{
      "$ref":"#/components/responses/Error"
     }
    },
    "security":[
     {
      "BearerAuth":[]
     },
     {
      "SessionCookie":[]
     }
    ],
    "summary":"Preview Chat Analysis",
    "tags":[
     "chats"
    ]
   }
  }
 },
 "components":{
  "responses":{
   "BadRequest":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Well-formed, but rejected by a rule; `detail.errors` lists each problem."
   },
   "Conflict":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"The resource's current state forbids this \u2014 a name already taken, a job already running."
   },
   "Error":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Unexpected error. Every error this API returns carries this body."
   },
   "Forbidden":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Authenticated, but this organization role may not perform the operation."
   },
   "NotFound":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"No such resource in this organization."
   },
   "Unauthorized":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Missing credential, or one that is revoked or no longer a member of this organization."
   },
   "ValidationFailed":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"The request did not match this operation's schema; `detail.errors` lists each field."
   }
  },
  "schemas":{
   "AnalysisField":{
    "additionalProperties":false,
    "description":"One value to pull out of the finished transcript.",
    "properties":{
     "description":{
      "description":"How to find this value in the transcript. Be explicit about the format you want and about what to do when the call never mentions it.",
      "minLength":1,
      "title":"Description",
      "type":"string"
     },
     "name":{
      "description":"Identifier for the extracted value, as it appears in the API and webhook. Lower-case letters, digits and underscores.",
      "pattern":"^[a-z][a-z0-9_]{0,39}$",
      "title":"Name",
      "type":"string"
     },
     "type":{
      "default":"string",
      "description":"The shape of the value. Anything that is not a number or a yes/no is a string.",
      "enum":[
       "string",
       "boolean",
       "integer",
       "number"
      ],
      "title":"Type",
      "type":"string"
     }
    },
    "required":[
     "name",
     "description"
    ],
    "title":"AnalysisField",
    "type":"object"
   },
   "AnalysisResponse":{
    "description":"The analysis of one call, as every reader sees it.\n\nShared verbatim by the calls API and the `session.completed` webhook so an\nintegration that reads one can read the other.",
    "properties":{
     "fields":{
      "additionalProperties":true,
      "title":"Fields",
      "type":"object"
     },
     "outcome":{
      "anyOf":[
       {
        "enum":[
         "success",
         "failure",
         "unknown"
        ],
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Outcome"
     },
     "outcome_rationale":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Outcome Rationale"
     },
     "skip_reason":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Skip Reason"
     },
     "status":{
      "default":"none",
      "enum":[
       "none",
       "pending",
       "completed",
       "failed",
       "skipped"
      ],
      "title":"Status",
      "type":"string"
     },
     "summary":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Summary"
     }
    },
    "required":[
     "status",
     "skip_reason",
     "summary",
     "outcome",
     "outcome_rationale",
     "fields"
    ],
    "title":"AnalysisResponse",
    "type":"object"
   },
   "AnalysisSpec":{
    "additionalProperties":false,
    "description":"What to work out about a call or a chat once it has ended.\n\nOne LLM call per session reads the finished transcript.",
    "properties":{
     "enabled":{
      "default":true,
      "description":"Analyse calls after they end. This runs one extra LLM call per call, billed like any other, and adds roughly 5% to the cost of a call.",
      "title":"Enabled",
      "type":"boolean"
     },
     "fields":{
      "description":"Values to extract from the transcript. These are what a reader inferred afterwards, and are kept apart from the data the agent itself collected during the call.",
      "items":{
       "$ref":"#/components/schemas/AnalysisField"
      },
      "maxItems":25,
      "title":"Fields",
      "type":"array"
     },
     "model":{
      "anyOf":[
       {
        "$ref":"#/components/schemas/LLMModelSpec"
       },
       {
        "type":"null"
       }
      ],
      "description":"The model that reads the transcript. Leave unset to use the platform default, which is picked for accuracy rather than the low latency a live call needs."
     },
     "outcome":{
      "anyOf":[
       {
        "$ref":"#/components/schemas/OutcomeSpec"
       },
       {
        "type":"null"
       }
      ],
      "description":"Judge whether each call achieved its purpose. Unset means calls are not judged and the outcome is left empty."
     },
     "summary":{
      "default":true,
      "description":"Write a short summary of each call, shown on the calls list.",
      "title":"Summary",
      "type":"boolean"
     }
    },
    "title":"AnalysisSpec",
    "type":"object"
   },
   "BuiltinToolSpec":{
    "additionalProperties":false,
    "description":"A capability of the model itself, switched on for that model.\n\n`config` takes only the options that model's catalog entry declares.",
    "properties":{
     "config":{
      "additionalProperties":true,
      "title":"Config",
      "type":"object"
     },
     "type":{
      "title":"Type",
      "type":"string"
     }
    },
    "required":[
     "type"
    ],
    "title":"BuiltinToolSpec",
    "type":"object"
   },
   "ErrorBody":{
    "description":"The structured half of our error contract: a human `message` plus a list\nof individual `errors` (used wherever we surface many problems at once,\nincluding tool publish, op-tree checks, and request validation). The global\nexception handlers normalize every API error to\n`{detail: {message, errors, code}}`, so SDKs can parse one shape consistently.",
    "properties":{
     "code":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "default":null,
      "description":"A stable identifier for this error, when it has one.",
      "title":"Code"
     },
     "errors":{
      "items":{
       "type":"string"
      },
      "title":"Errors",
      "type":"array"
     },
     "message":{
      "title":"Message",
      "type":"string"
     }
    },
    "required":[
     "message",
     "errors"
    ],
    "title":"ErrorBody",
    "type":"object"
   },
   "ErrorResponse":{
    "description":"The body of every error response, at every status code.",
    "properties":{
     "detail":{
      "$ref":"#/components/schemas/ErrorBody"
     }
    },
    "required":[
     "detail"
    ],
    "title":"ErrorResponse",
    "type":"object"
   },
   "LLMModelSpec":{
    "additionalProperties":false,
    "properties":{
     "builtin_tools":{
      "items":{
       "$ref":"#/components/schemas/BuiltinToolSpec"
      },
      "title":"Builtin Tools",
      "type":"array"
     },
     "hosts":{
      "anyOf":[
       {
        "items":{
         "type":"string"
        },
        "type":"array"
       },
       {
        "type":"null"
       }
      ],
      "description":"OpenRouter only: the hosts allowed to serve this model, from list_model_hosts; the fastest of them answers. Unset lets OpenRouter use any host.",
      "title":"Hosts"
     },
     "model":{
      "default":"gpt-5.6-luna",
      "title":"Model",
      "type":"string"
     },
     "priority":{
      "default":false,
      "description":"Run this model in its provider's priority (low-latency) lane, where its catalog entry declares one; on OpenRouter, any model (standard where no host sells one). Steadies the worst case rather than the average, and costs more per token.",
      "title":"Priority",
      "type":"boolean"
     },
     "provider":{
      "default":"openai",
      "title":"Provider",
      "type":"string"
     },
     "reasoning_effort":{
      "anyOf":[
       {
        "enum":[
         "none",
         "minimal",
         "low",
         "medium",
         "high"
        ],
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "description":"How long this model may think before it answers. Must be one of the values the model's catalog entry offers; unset means its fastest. On a voice call the caller hears every second of thinking as silence.",
      "title":"Reasoning Effort"
     }
    },
    "title":"LLMModelSpec",
    "type":"object"
   },
   "OutcomeSpec":{
    "additionalProperties":false,
    "description":"What counts as this call having achieved its purpose.",
    "properties":{
     "prompt":{
      "description":"What a successful call looks like for this agent. Each call is judged against this and comes back as success, failure, or unknown, with the reasoning.",
      "minLength":1,
      "title":"Prompt",
      "type":"string"
     }
    },
    "required":[
     "prompt"
    ],
    "title":"OutcomeSpec",
    "type":"object"
   },
   "PreviewAnalysisRequest":{
    "description":"A spec to try, and the agent whose prompt it should be judged against.\n\n``agent_id`` is optional: without it the call's own recorded agent version\nsupplies the system prompt, which is what you want when tuning a spec for\nan agent that already exists.",
    "properties":{
     "agent_id":{
      "anyOf":[
       {
        "format":"uuid",
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Agent Id"
     },
     "analysis":{
      "$ref":"#/components/schemas/AnalysisSpec"
     }
    },
    "required":[
     "analysis"
    ],
    "title":"PreviewAnalysisRequest",
    "type":"object"
   },
   "PreviewAnalysisResponse":{
    "description":"What the spec found. Nothing was written.",
    "properties":{
     "analysis":{
      "$ref":"#/components/schemas/AnalysisResponse"
     },
     "model":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Model"
     },
     "provider":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Provider"
     }
    },
    "required":[
     "analysis"
    ],
    "title":"PreviewAnalysisResponse",
    "type":"object"
   }
  }
 }
}
```
