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

# Close a conversation

> Finishes the conversation with an outcome. `won` also marks the contact as won; `spam` also marks the contact as spam. Nothing is sent to the contact, and if they write again a new conversation opens.

Answers 409 `conversation_closed` if it is already closed.



## OpenAPI

````yaml /api-reference/openapi.json post /v1/conversations/{conversation_id}/close
openapi: 3.1.0
info:
  description: >-
    The Sailer REST API for CRM, conversations, and campaigns.


    **Authentication.** Send a token as `Authorization: Bearer <token>`. A
    workspace

    token (`sk_live_...`) is created by a workspace administrator and its secret
    is

    shown once. An OAuth access token (`oat_live_...`) acts on behalf of the
    person

    who authorized it and sees only what they can see. Either way the workspace
    is

    implied by the token, so no tenant header is needed. Each token carries
    scopes;

    `GET /v1/me` lists them.


    **Pagination.** Collections return `{data, meta, links}`. Pass `links.next`
    back

    as `cursor` until it is `null`. Cursors are opaque and only valid for the
    query

    that produced them.


    **Errors.** Every non-2xx response is `{"error": {...}}` with a coarse
    `type`, a

    stable `code` and the offending `param`. Quote `error.request_id` (also the

    `X-Request-ID` header) when contacting support.


    **Retries.** Send an `Idempotency-Key` header on any write to make retrying
    it

    safe for 24 hours.


    **Rate limits.** Limits are per token. Every response carries

    `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`; a
    `429`

    also carries `Retry-After`.


    **Custom fields.** Workspace-defined fields appear under `custom_fields`,
    keyed

    by field key. `GET /v1/fields` lists every field on a resource, built-in and

    custom.
  title: Sailer API
  version: 1.0.0
servers:
  - url: https://api.chatsailer.com
security:
  - SailerApiToken: []
tags:
  - description: Token introspection and workspace capabilities.
    name: Meta
  - description: >-
      People you talk to. Called *leads* in older Sailer surfaces; `contact` is
      the current name.
    name: Contacts
  - description: Companies that contacts belong to (B2B accounts).
    name: Organizations
  - description: Opportunities moving through a pipeline.
    name: Deals
  - description: Pipelines and their stages.
    name: Pipelines
  - description: Field definitions, including custom fields.
    name: Fields
  - description: Free-text annotations on CRM records.
    name: Notes
  - description: Scheduled and logged CRM activities.
    name: Activities
  - description: Per-entity label catalogs.
    name: Tags
  - description: Members of the workspace, for assigning records.
    name: Users
  - description: Message threads with contacts, across every channel.
    name: Conversations
  - description: Outbound campaigns and their participants.
    name: Campaigns
  - description: Named contact lists campaigns draw from.
    name: Audiences
  - description: The connections you talk to contacts through.
    name: Channels
  - description: Pre-approved WhatsApp message templates.
    name: Templates
  - description: >-
      Keeping another system in step with a workspace: the deletion feed.
      Changes are read from each resource's list with `updated_since`.
    name: Sync
  - description: >-
      Business outcomes your systems report — a sale closed, a meeting held —
      that your agreement may charge a success fee on. Append-only: a refund is
      a reversal, never an edit. Needs the `success_events:read` /
      `success_events:write` scopes.
    name: Success Events
paths:
  /v1/conversations/{conversation_id}/close:
    post:
      tags:
        - Conversations
      summary: Close a conversation
      description: >-
        Finishes the conversation with an outcome. `won` also marks the contact
        as won; `spam` also marks the contact as spam. Nothing is sent to the
        contact, and if they write again a new conversation opens.


        Answers 409 `conversation_closed` if it is already closed.
      operationId: close_conversation
      parameters:
        - in: path
          name: conversation_id
          required: true
          schema:
            description: Unique identifier for a conversation.
            examples:
              - conv_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
            pattern: ^conv_[0-9a-f]{32}$
            title: Conversation Id
            type: string
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        content:
          application/json:
            schema:
              anyOf:
                - $ref: '#/components/schemas/CloseRequest'
                - type: 'null'
              title: Body
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Conversation'
          description: Successful Response
          headers:
            Idempotent-Replay:
              $ref: '#/components/headers/Idempotent-Replay'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '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/UnprocessableContent'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - SailerApiToken: []
components:
  parameters:
    IdempotencyKey:
      description: >-
        A unique value (a UUID works) that makes retrying this request safe. A
        repeat with the same key and body within 24 hours returns the original
        response instead of acting twice; the same key with a different body is
        a `409 idempotency_key_reused`.
      in: header
      name: Idempotency-Key
      required: false
      schema:
        maxLength: 255
        type: string
  schemas:
    CloseRequest:
      additionalProperties: false
      description: Body for closing a conversation.
      properties:
        outcome:
          $ref: '#/components/schemas/ConversationOutcome'
          default: resolved
        won_reason:
          anyOf:
            - $ref: '#/components/schemas/ConversationWonReason'
            - type: 'null'
          description: 'Only with `outcome: won`. Defaults to `other`.'
      title: CloseRequest
      type: object
    Conversation:
      description: One thread with one contact on one channel.
      properties:
        channel:
          anyOf:
            - $ref: '#/components/schemas/ChannelPlatform'
            - type: 'null'
          description: Platform this thread runs on, e.g. `whatsapp`.
        channel_id:
          anyOf:
            - description: Unique identifier for a channel.
              examples:
                - chn_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
              pattern: ^chn_[0-9a-f]{32}$
              type: string
            - type: 'null'
          description: The channel this thread runs on.
          title: Channel Id
        contact_id:
          anyOf:
            - description: Unique identifier for a contact.
              examples:
                - con_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
              pattern: ^con_[0-9a-f]{32}$
              type: string
            - type: 'null'
          description: The person on the other end, when known.
          title: Contact Id
        created_at:
          format: date-time
          title: Created At
          type: string
        handler:
          anyOf:
            - $ref: '#/components/schemas/Owner'
            - type: 'null'
          description: >-
            Who is handling it now: the AI agent (`kind: agent`) or a teammate
            (`kind: user`). Null while it waits in a queue for a teammate, and
            once it is closed.
        id:
          description: Unique identifier for a conversation.
          examples:
            - conv_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
          pattern: ^conv_[0-9a-f]{32}$
          title: Id
          type: string
        last_message_at:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          title: Last Message At
        needs_human:
          anyOf:
            - type: boolean
            - type: 'null'
          description: >-
            Whether a person has been asked for: the AI agent asked for one, or
            a teammate was assigned or took it over. It does not say who has the
            conversation — one routed straight to a teammate can read `false` —
            so use `handler` for that. Null once closed.
          title: Needs Human
        object:
          const: conversation
          default: conversation
          title: Object
          type: string
        queue_name:
          anyOf:
            - type: string
            - type: 'null'
          description: The queue it is in while open.
          title: Queue Name
        status:
          $ref: '#/components/schemas/ConversationStatus'
        updated_at:
          description: >-
            When anything about the conversation last changed, including who
            handles it and whether it is open.
          format: date-time
          title: Updated At
          type: string
      required:
        - id
        - status
        - created_at
        - updated_at
      title: Conversation
      type: object
    ConversationOutcome:
      description: >-
        How a conversation ended.


        `resolved` closes it and changes nothing else. `won` also marks the
        contact

        as won. `spam` also marks the contact as spam, which keeps the AI agent
        from

        replying to them in future.
      enum:
        - resolved
        - won
        - spam
      title: ConversationOutcome
      type: string
    ConversationWonReason:
      description: Why a conversation closed as won.
      enum:
        - hiring_sale_success
        - appointment_completed
        - proposal_accepted
        - contract_signed
        - payment_confirmed
        - service_completed
        - other
      title: ConversationWonReason
      type: string
    ChannelPlatform:
      description: >-
        The messaging platform a channel runs on.


        `whatsapp_api` is the official WhatsApp Business Platform, the only one
        that

        supports message templates. `whatsapp` is a number connected through the

        WhatsApp app. `botconversa` is a channel fed by an external chatbot

        integration.
      enum:
        - whatsapp_api
        - whatsapp
        - instagram
        - slack
        - web_widget
        - botconversa
      title: ChannelPlatform
      type: string
    Owner:
      description: |-
        Whoever is responsible for a record: a teammate (`kind: user`) or an AI
        agent (`kind: agent`).
      properties:
        id:
          description: Prefixed id — `usr_…` for a teammate, `agt_…` for an agent.
          title: Id
          type: string
        kind:
          enum:
            - user
            - agent
          title: Kind
          type: string
        name:
          anyOf:
            - type: string
            - type: 'null'
          title: Name
        object:
          const: owner
          default: owner
          title: Object
          type: string
      required:
        - kind
        - id
      title: Owner
      type: object
    ConversationStatus:
      description: |-
        Where a conversation stands.

        `waiting`: open, and nobody has picked it up yet — it is in a queue, or
        assigned to a teammate who has not accepted it. `active`: open and being
        handled, by the AI agent or by a teammate. `closed`: finished.
      enum:
        - waiting
        - active
        - closed
      title: ConversationStatus
      type: string
    ApiErrorResponse:
      description: Every non-2xx response on the public API has this body.
      properties:
        error:
          $ref: '#/components/schemas/ApiError'
      required:
        - error
      title: ApiErrorResponse
      type: object
    ApiError:
      properties:
        code:
          description: Stable, machine-readable identifier.
          title: Code
          type: string
        detail:
          anyOf:
            - items:
                $ref: '#/components/schemas/ErrorDetail'
              type: array
            - type: 'null'
          default: null
          description: Per-field errors for validation failures.
          title: Detail
        documentation_url:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          title: Documentation Url
        message:
          description: Human-readable explanation.
          title: Message
          type: string
        param:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          description: Request field the error refers to, if any.
          title: Param
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          description: >-
            Echoes the X-Request-ID response header. Quote it in support
            requests.
          title: Request Id
        type:
          $ref: '#/components/schemas/ErrorType'
      required:
        - type
        - code
        - message
      title: ApiError
      type: object
    ErrorDetail:
      properties:
        code:
          anyOf:
            - type: string
            - type: 'null'
          default: null
          title: Code
        field:
          description: Dotted path to the offending field.
          title: Field
          type: string
        message:
          title: Message
          type: string
      required:
        - field
        - message
      title: ErrorDetail
      type: object
    ErrorType:
      description: Coarse class of failure. Stable; new codes may appear under a type.
      enum:
        - invalid_request_error
        - authentication_error
        - permission_error
        - not_found_error
        - conflict_error
        - rate_limit_error
        - api_error
      title: ErrorType
      type: string
  headers:
    Idempotent-Replay:
      description: >-
        `true` when this response is a stored replay of an earlier request with
        the same `Idempotency-Key`.
      schema:
        enum:
          - 'true'
        type: string
    X-RateLimit-Limit:
      description: Requests allowed in the current window on this token.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests left in the current window.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Seconds until the window resets and the allowance refills.
      schema:
        type: integer
    X-Request-ID:
      description: Unique id for this request. Quote it to support.
      schema:
        type: string
    Retry-After:
      description: Seconds to wait before retrying.
      schema:
        type: integer
  responses:
    BadRequest:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: A query parameter, path segment or header is invalid.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
    Unauthorized:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: The token is missing, unknown, revoked or expired.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
    Forbidden:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: >-
        The token lacks a required scope, or the workspace's CRM write policy
        does not allow this change.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
    NotFound:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: No such record in this workspace.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
    Conflict:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: >-
        The request conflicts with current state, or its `Idempotency-Key` was
        reused with a different body or is still being processed.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
    UnprocessableContent:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: The request body failed validation.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
    RateLimited:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: Too many requests on this token. Retry after the delay.
      headers:
        Retry-After:
          $ref: '#/components/headers/Retry-After'
        X-RateLimit-Limit:
          $ref: '#/components/headers/X-RateLimit-Limit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/X-RateLimit-Remaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/X-RateLimit-Reset'
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
    InternalError:
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
      description: Something went wrong on our side. Quote `error.request_id` to support.
      headers:
        X-Request-ID:
          $ref: '#/components/headers/X-Request-ID'
  securitySchemes:
    SailerApiToken:
      description: >-
        A workspace API token (`sk_live_...`) or an OAuth access token
        (`oat_live_...`). Create workspace tokens in Settings > API. Send either
        as `Authorization: Bearer <token>`.
      scheme: bearer
      type: http

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.