---
title: "Talk to the agent as text (no phone call, no STT/TTS) — either one turn at a time with `session_id`/`message`, or a whole scripted conversation in one call via `messages`, which returns per-turn `first_word_s`/`total_s` latency plus a min/max/avg summary, for benchmarking an agent right after creating it."
method: POST
path: "/api/v1/agents/{id}/test-chat"
tags: ["testing"]
---

# Talk to the agent as text (no phone call, no STT/TTS) — either one turn at a time with \`session_id\`/\`message\`, or a whole scripted conversation in one call via \`messages\`, which returns per-turn \`first_word_s\`/\`total_s\` latency plus a min/max/avg summary, for benchmarking an agent right after creating it.

`POST /api/v1/agents/{id}/test-chat`

## Request

- Base URL: `https://www.callagent.pro`
- URL: `https://www.callagent.pro/api/v1/agents/{id}/test-chat`
- Auth: HTTP bearer

`message` and `messages` are mutually exclusive modes — sending both is rejected with 422 (error: ambiguous_request) rather than silently picking one. The agent must be status=active: a paused agent (this includes one just made by /duplicate, which creates agents paused) answers 409 error: agent_paused — not 404, since the id is real and the fix is to activate it (PUT /agents/{id} with status=active), not to look for a different id.

## Path parameters

- `id` integer, required

## Request body

- union
  - object: Single turn
    - `message` string, required
    - `session_id` string: continue a session started by an earlier call
    - `end` boolean
    - `hangup` boolean: End the session properly — summary + post-call webhook — rather than just dropping it
  - object: Benchmark mode — a whole scripted conversation, scored turn by turn
    - `messages` string[], required

## Response `200`

Two different shapes, one per mode. Sending `message` (single turn) returns ok/session_id/messages — keep the session_id and send it back to continue the thread. Sending `messages` (benchmark mode) runs the whole script in one call and returns ok/ended/transcript/turns/timing_summary/variables instead, with NO session_id. Check which keys you got rather than assuming.

- union
  - object
    - `ok` boolean
    - `session_id` string: Send this back in the next request to continue the conversation
    - `messages` object[]: The thread so far, oldest first
      - `role` 'user' | 'assistant'
      - `text` string
  - object
    - `ok` boolean
    - `ended` boolean: The agent closed the conversation itself
    - `transcript` object[]
      - `role` string
      - `kind` string
      - `text` string
      - `node` string, nullable
      - `label` string, nullable
      - `t` number: Seconds since the script started
    - `turns` object[]
      - `caller` string, nullable: The caller line that opened this turn
      - `first_word_s` number: Seconds from the caller's line to the agent's FIRST word — the latency a caller actually feels
      - `total_s` number: Seconds to the complete answer
      - `utterances` integer
      - `node` string, nullable: Flow node that answered; null for a prompt agent
    - `timing_summary` object
      - `turns` integer
      - `first_word_s` object
        - `min` number
        - `max` number
        - `avg` number
      - `turn_total_s` object
        - `min` number
        - `max` number
        - `avg` number
    - `variables` object: Anything the agent captured during the scripted run, as flat key/value strings. Empty object when nothing was captured.

## Other responses

- `401`: Missing or invalid Bearer key
- `404`: No matching record on this account
- `409`: Agent exists but is paused
- `422`: Both message and messages were sent
- `429`: Too many requests — see the endpoint's rate limit tier (agent-api 120/min, agent-api-heavy 6/min, agent-api-secrets 10/min)

---

[API](https://skmtc.dev/callagent/apis/callagent-pro-agent-api.md) · [All operations](https://skmtc.dev/callagent/apis/callagent-pro-agent-api/llms.txt) · [OpenAPI document](https://skmtc.dev/callagent/apis/callagent-pro-agent-api/revisions/38072cf8a24b?raw)
