---
title: "Set My Chat Spend Limit"
method: PUT
path: "/api/chats/{chat_id}/my-spend-limit"
tags: ["chats"]
---

# Set My Chat Spend Limit

`PUT /api/chats/{chat_id}/my-spend-limit`

## Request

- Base URL: `https://app.thinqos.com` (the document declares no server; this is the origin it was published from)
- URL: `https://app.thinqos.com/api/chats/{chat_id}/my-spend-limit`
- Auth: none declared

Set the CALLER's own per-chat spend cap - or, with a `null` body
value, set it to EXPLICIT "no cap" (TOS-2393; review finding #2).

A `null` value does NOT clear the caller's entry - it is a durable
statement that this payer has opted out of any cap, and it beats the
legacy room-wide scalar fallback (unlike an absent entry). To remove the
entry entirely and revert to "no preference stated" (falls back to
whatever the room's legacy scalar says), use
`DELETE .../my-spend-limit` instead - the two routes are deliberately
NOT equivalent any more. See `ChatService.set_my_chat_spend_limit`'s
docstring for the full rationale.

The payer is always `identity.id` - the request's resolved principal,
which `get_identity` (not `get_real_identity`) allows to be an
AUTHORIZED IMPERSONATION target via `X-Impersonate-Identity-Id`, not only
the human at the keyboard. There is no field on this route through which
a caller could freely NAME a payer (see
`ChatService.set_my_chat_spend_limit`'s docstring for why that is an
authorization guarantee, not an impossibility one). Requires ACTIVE
participation (``ChatService.get_chat``'s gate), not the relaxed
any-status membership check ``get_chat_detail`` uses, so a removed
participant cannot set a budget in a room they no longer belong to.

## Path parameters

- `chat_id` string, uuid, required

## Headers

- `x-impersonate-identity-id` string, nullable

## Request body

- UpdateMySpendLimitRequest: Body for `PUT /api/chats/{chat_id}/my-spend-limit` (TOS-2393). No payer field, ever - the write always targets the AUTHENTICATED-OR- IMPERSONATED caller's own identity (`identity.id`, resolved server-side from `get_identity`), and impersonation is gated by `check_can_impersonate` (see `set_my_chat_spend_limit`'s docstring for why this is an authorization claim, not an impossibility claim - a platform admin or agent owner CAN write a different person's/agent's key via `X-Impersonate-Identity-Id`, authorized, not absent). A `null` value does NOT clear the caller's own cap - it sets an explicit, durable "no cap" that beats the legacy room-wide scalar fallback (review finding #2). Use `DELETE` on the same route to remove the entry entirely and revert to "no preference stated" - the two are deliberately NOT equivalent any more.
  - `max_chat_spend_usd` number, nullable

## Response `200`

Successful Response

- ChatDetail
  - `id` string, uuid, required
  - `title` string, nullable, required
  - `container_kind` string, required
  - `status` string, required
  - `description` string, nullable
  - `default_agent_identity_id` string, uuid, nullable
  - `participants` ParticipantData[]
    - `identity_id` string, uuid, required
    - `display_name` string, required
    - `kind` string, required
    - `role` string, required
    - `status` string, required
    - `avatar_url` string, nullable
    - `joined_at` string, date-time, nullable
    - `left_at` string, date-time, nullable
    - `archived_at` string, date-time, nullable
    - `is_pinned` boolean
  - `messages` MessageData[]
    - `id` string, uuid, required
    - `chat_id` string, uuid, required
    - `sender_id` string, uuid, nullable, required
    - `sender` SenderSummary: Minimal identity info for attribution on a message or participant.
      - `id` string, uuid, required
      - `display_name` string, required
      - `kind` string
    - `role` string
    - `content` string
    - `model` string, nullable
    - `provider` string, nullable
    - `duration_ms` integer, nullable
    - `is_deleted` boolean
    - `has_attachments` boolean
    - `metadata` object, nullable
    - `created_at` string, date-time, nullable
    - `revised_at` string, date-time, nullable
    - `attachments` AttachmentData[]
      - `id` string, uuid, required
      - `file_name` string, required
      - `file_type` string, required
      - `mime_type` string, required
      - `file_size_bytes` integer, nullable, required
      - `created_at` string, date-time, nullable, required
    - `compression_summary` CompressionSummary: Structured marker for a `role="system"` compaction-summary message. Surfaced on `MessageData.compression_summary` so the UI can render the "earlier conversation summarized" divider without parsing raw metadata.
      - `messages_compressed` integer, required
      - `summary_model` string, required
  - `started_at` string, date-time, nullable
  - `updated_at` string, date-time, nullable
  - `extraction_excluded` boolean
  - `mind_context_disabled` boolean
  - `capture_disposition` CaptureDispositionSummary: TOS-3758: this viewer's capture mailbox state for one captured conversation. ``using_connection_default`` is the field the UI renders. False means this conversation has diverged from the capture connection's archive/read policy and will no longer follow changes to it - a state that existed before this ticket but was completely invisible, and had no undo. ``can_reset`` is separate from ``not using_connection_default`` on purpose: an unbound source capture can only be handed back to a default when the caller can supply that source's policy, so the client must not offer a control that would no-op.
    - `source` string, required
    - `using_connection_default` boolean, required
    - `can_reset` boolean, required
    - `override_reason` string, nullable
  - `facilitation_mode` 'natural' | 'facilitated'
  - `facilitator_identity_id` string, uuid, nullable
  - `alternate_facilitator_identity_ids` string[]
  - `max_responders` integer
  - `max_chain_depth` integer
  - `top_k_claimants` integer
  - `max_concurrent_generations` integer
  - `max_concurrent_generations_per_provider` integer
  - `max_root_container_spend_usd` number, nullable
  - `viewer_max_chat_spend_usd` number, nullable
  - `viewer_chat_spend_usd` number, nullable
  - `viewer_model_spend_usd` number, nullable
  - `viewer_agent_fees_usd` number, nullable
  - `has_active_recipients` boolean
  - `lifecycle` 'live' | 'concluded'
  - `source` string, nullable
  - `source_display_name` string, nullable
  - `source_icon_url` string, nullable
  - `source_recognized` boolean, nullable

## Other responses

- `422`: Validation Error

## Changes

- **2026-10-20** `5387b4ded614`: 1 warning
  - removed the optional property `hidden_before_message_id` from the response with the `200` status

[Operation history](https://skmtc.dev/thinqos/apis/thinqos-api/changes/api/chats/:chat_id/my-spend-limit/put.md)

---

[API](https://skmtc.dev/thinqos/apis/thinqos-api.md) · [All operations](https://skmtc.dev/thinqos/apis/thinqos-api/llms.txt) · [OpenAPI document](https://skmtc.dev/thinqos/apis/thinqos-api/revisions/5387b4ded614?raw)
