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

# Cancel a pending interaction

> Cancel a pending interaction — WITHDRAW one specific ask without answering it and
without deleting its conversation thread.

The mirror of ``answer_interaction`` for the terminal-without-an-answer case: it
tears the pending question down via the store's status-gated ``prune_pending`` (the
same primitive the timeout path and the thread-delete cascade use), so NO continuation
fires — a parked async flow is never resumed — and the removed event rides tagged
``reason="cancelled"`` so a live operator surface tells a deliberate withdrawal apart
from a timeout/expiry removal.

Status-gated exactly like the answer door: only a PENDING (or parked) question cancels.
A question already ``answered`` (its state retained) is a loud ``409`` conflict; a
question whose state is GONE — expired, already cancelled, or never existed (all
leave no distinguishable tombstone, the same limit the answer door has) — is a ``404``.
Idempotent at the store seam: ``prune_pending`` re-run on a withdrawn question is a
clean no-op, so a re-cancel simply reports the question gone (``404``) rather than
double-tearing anything down. Unlike the answer door it is answer-format-AGNOSTIC: an
EXTERNAL ask is a pending ask an operator may withdraw, so it is cancellable too.

Channel-blind by construction: a channel-side pending correlation is NOT proactively
torn down. A later participant reply forwarded to the callback door finds the state gone and
the door answers ``404``, which the inbound ladder maps to a fresh bridged turn — the
identical path a timeout/expiry removal already takes.

Audience gate identical to ``answer_interaction`` (after the existence/status guards):
a question's ``audience`` identity OR any unrestricted caller (the operator can always
withdraw a stuck question) may cancel; every other restricted caller is a loud ``403``.



## OpenAPI

````yaml /openapi.json post /api/interactions/{interaction_id}/cancel
openapi: 3.1.0
info:
  description: The operator HTTP surface served under /api/*.
  title: tai42-skeleton API
  version: 14.0.2
servers: []
security: []
paths:
  /api/interactions/{interaction_id}/cancel:
    post:
      tags:
        - interactions
      summary: Cancel a pending interaction
      description: >-
        Cancel a pending interaction — WITHDRAW one specific ask without
        answering it and

        without deleting its conversation thread.


        The mirror of ``answer_interaction`` for the terminal-without-an-answer
        case: it

        tears the pending question down via the store's status-gated
        ``prune_pending`` (the

        same primitive the timeout path and the thread-delete cascade use), so
        NO continuation

        fires — a parked async flow is never resumed — and the removed event
        rides tagged

        ``reason="cancelled"`` so a live operator surface tells a deliberate
        withdrawal apart

        from a timeout/expiry removal.


        Status-gated exactly like the answer door: only a PENDING (or parked)
        question cancels.

        A question already ``answered`` (its state retained) is a loud ``409``
        conflict; a

        question whose state is GONE — expired, already cancelled, or never
        existed (all

        leave no distinguishable tombstone, the same limit the answer door has)
        — is a ``404``.

        Idempotent at the store seam: ``prune_pending`` re-run on a withdrawn
        question is a

        clean no-op, so a re-cancel simply reports the question gone (``404``)
        rather than

        double-tearing anything down. Unlike the answer door it is
        answer-format-AGNOSTIC: an

        EXTERNAL ask is a pending ask an operator may withdraw, so it is
        cancellable too.


        Channel-blind by construction: a channel-side pending correlation is NOT
        proactively

        torn down. A later participant reply forwarded to the callback door
        finds the state gone and

        the door answers ``404``, which the inbound ladder maps to a fresh
        bridged turn — the

        identical path a timeout/expiry removal already takes.


        Audience gate identical to ``answer_interaction`` (after the
        existence/status guards):

        a question's ``audience`` identity OR any unrestricted caller (the
        operator can always

        withdraw a stuck question) may cancel; every other restricted caller is
        a loud ``403``.
      operationId: post_api_interactions_interaction_id_cancel
      parameters:
        - in: path
          name: interaction_id
          required: true
          schema:
            type: string
      responses:
        '200':
          content:
            application/json:
              schema:
                properties:
                  data:
                    $ref: '#/components/schemas/InteractionActionResult'
                required:
                  - data
                type: object
          description: Success.
        '401':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Missing or invalid api key.
        '403':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Forbidden.
        '404':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Resource not found.
        '409':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          description: Conflict with the current resource state.
      security:
        - ApiKeyAuth: []
components:
  schemas:
    InteractionActionResult:
      description: |-
        A single interaction terminal result: the id and its new ``status``
        (``answered`` for the answer door, ``cancelled`` for the cancel door).
      properties:
        interaction_id:
          title: Interaction Id
          type: string
        status:
          title: Status
          type: string
      required:
        - interaction_id
        - status
      title: InteractionActionResult
      type: object
    Error:
      properties:
        code:
          description: >-
            Stable machine-readable reason a client keys a dedicated error state
            on, present on refusals that opt in (e.g. a 501 not-configured
            refusal). Optional: absent when the error carries only a
            human-readable message.
          type: string
        error:
          type: string
      required:
        - error
      type: object
  securitySchemes:
    ApiKeyAuth:
      in: header
      name: x-api-key
      type: apiKey

````