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

# Voice Timing

> Report client-side voice session startup timing

A fire-and-forget telemetry beacon. Post client-measured startup marks for a voice session and Trellis forwards them to its observability pipeline. Optional — it has no effect on session behavior, and is only useful if you're instrumenting voice startup latency.

<ParamField header="Authorization" type="string" required>
  Bearer token obtained from the [authenticate](/api-reference/authentication/authenticate) endpoint.
</ParamField>

<ParamField body="client_trace_id" type="string" required>
  The per-session correlation id you passed to [Create Voice Session](/api-reference/voice/create-session), so the marks join up with the rest of that session's telemetry. Must match `[A-Za-z0-9_-]{1,64}`.
</ParamField>

<ParamField body="marks" type="object" required>
  A map of named marks to numeric milliseconds-since-button-press (e.g. `{"first_agent_audio": 1830}`). Names are free-form; at most 64 entries.
</ParamField>

<ParamField body="user_agent" type="string">
  The client user-agent string, for slicing latency by browser. Maximum 512 characters.
</ParamField>

<ParamField body="build_target" type="string">
  Your client build identifier. Maximum 64 characters.
</ParamField>

<ParamField body="network_effective_type" type="string">
  The connection class from `navigator.connection.effectiveType` (e.g. `4g`). Maximum 32 characters.
</ParamField>

## Response

Returns `204 No Content` on success — no response body.

<RequestExample>
  ```bash cURL theme={"theme":{"light":"github-light","dark":"github-dark"}}
  curl -X POST https://api.trellis.sh/v1/voice/timing \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "client_trace_id": "b1f2c3d4e5",
      "marks": {"button_press": 0, "token_received": 420, "first_agent_audio": 1830},
      "user_agent": "TrellisApp/2.1 (iOS 18.2)",
      "build_target": "ios-prod",
      "network_effective_type": "4g"
    }'
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"github-dark"}}
  import requests

  requests.post(
      "https://api.trellis.sh/v1/voice/timing",
      headers={
          "Authorization": "Bearer YOUR_TOKEN",
          "Content-Type": "application/json",
      },
      json={
          "client_trace_id": "b1f2c3d4e5",
          "marks": {"button_press": 0, "first_agent_audio": 1830},
      },
  )
  ```

  ```javascript JavaScript theme={"theme":{"light":"github-light","dark":"github-dark"}}
  await fetch("https://api.trellis.sh/v1/voice/timing", {
    method: "POST",
    headers: {
      Authorization: "Bearer YOUR_TOKEN",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      client_trace_id: "b1f2c3d4e5",
      marks: { button_press: 0, first_agent_audio: 1830 },
    }),
  });
  ```
</RequestExample>

<ResponseExample>
  ```text 204 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  (No Content)
  ```

  ```json 401 theme={"theme":{"light":"github-light","dark":"github-dark"}}
  {
    "detail": "Missing Authorization header"
  }
  ```
</ResponseExample>
