> ## 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.

# Search deals

> For queries `GET /v1/deals` cannot express: nested and/or, ranges, and conditions across relationships.

Returns the same deal objects in the same envelope, and accepts the same `expand` and `fields`. Both endpoints compile to one query engine, so their results cannot disagree.



## OpenAPI

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


    **Authentication.** Send a scoped token as `Authorization: Bearer
    sk_live_...`.

    Tokens are workspace-scoped; the workspace is implied by the token, so no

    tenant header is needed. A workspace administrator creates and revokes them;

    the secret is shown once at creation and cannot be recovered afterwards.


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

    until it is `null`; treat the cursor as opaque.


    **Errors.** Every non-2xx response is `{"error": {...}}` with a stable
    `code`.

    Quote `error.request_id` when contacting support.


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

    by `field_key`. Read a record to see which keys a workspace uses; a
    dedicated

    field-discovery endpoint is not part of this release.
  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: Message threads with contacts, across every channel.
    name: Conversations
  - description: Outbound campaigns and their participants.
    name: Campaigns
paths:
  /v1/deals/search:
    post:
      tags:
        - Deals
      summary: Search deals
      description: >-
        For queries `GET /v1/deals` cannot express: nested and/or, ranges, and
        conditions across relationships.


        Returns the same deal objects in the same envelope, and accepts the same
        `expand` and `fields`. Both endpoints compile to one query engine, so
        their results cannot disagree.
      operationId: search_deals
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/DealSearchRequest'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DealList'
          description: Successful Response
        '422':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
          description: Validation Error
      security:
        - SailerApiToken: []
components:
  schemas:
    DealSearchRequest:
      additionalProperties: false
      description: |-
        Body for ``POST /v1/deals/search``, and arguments for the MCP
        ``search_records`` tool.
      properties:
        cursor:
          anyOf:
            - type: string
            - type: 'null'
          title: Cursor
        expand:
          anyOf:
            - type: string
            - type: 'null'
          title: Expand
        fields:
          anyOf:
            - type: string
            - type: 'null'
          title: Fields
        filter:
          anyOf:
            - $ref: '#/components/schemas/FilterGroup'
            - $ref: '#/components/schemas/FilterCondition'
            - type: 'null'
          description: Condition tree. Groups may nest and mix and/or.
          title: Filter
        limit:
          default: 50
          maximum: 200
          minimum: 1
          title: Limit
          type: integer
        q:
          anyOf:
            - type: string
            - type: 'null'
          description: Free text across the deal title, contact name and organization name.
          title: Q
        sort:
          anyOf:
            - type: string
            - type: 'null'
          description: Same syntax as the `sort` query parameter.
          title: Sort
      title: DealSearchRequest
      type: object
    DealList:
      description: |-
        A page of deals.

        A named subclass purely so the generated SDK type is ``DealList`` rather
        than the ``Page_Deal_`` FastAPI derives from the generic.
      properties:
        data:
          items:
            $ref: '#/components/schemas/Deal'
          title: Data
          type: array
        links:
          $ref: '#/components/schemas/PageLinks'
        meta:
          $ref: '#/components/schemas/PageMeta'
      required:
        - data
        - meta
        - links
      title: DealList
      type: object
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          title: Detail
          type: array
      title: HTTPValidationError
      type: object
    FilterGroup:
      additionalProperties: false
      description: A set of conditions combined with `and` / `or`. Groups may nest.
      properties:
        conditions:
          items:
            anyOf:
              - $ref: '#/components/schemas/FilterCondition'
              - $ref: '#/components/schemas/FilterGroup'
          title: Conditions
          type: array
        join:
          default: and
          enum:
            - and
            - or
          title: Join
          type: string
      title: FilterGroup
      type: object
    FilterCondition:
      additionalProperties: false
      description: One comparison against a field.
      properties:
        field:
          description: Public field name, or `custom.<key>` for a custom field.
          examples:
            - status
          title: Field
          type: string
        operator:
          $ref: '#/components/schemas/OperatorType'
          default: equals
          description: Comparison to apply. Valid operators depend on the field type.
        value:
          anyOf:
            - {}
            - type: 'null'
          description: Value to compare against. Omitted for `is_empty`/`is_not_empty`.
          title: Value
      required:
        - field
      title: FilterCondition
      type: object
    Deal:
      description: A negotiation in a pipeline, with a contact and/or an organization.
      properties:
        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 this deal is with, if any.
          title: Contact Id
        created_at:
          format: date-time
          title: Created At
          type: string
        custom_fields:
          additionalProperties: true
          description: >-
            Every custom field defined on deals in this workspace, keyed by
            field key and typed from its definition. Unset fields are `null`.
          title: Custom Fields
          type: object
        expected_close_date:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          title: Expected Close Date
        id:
          description: Unique identifier for a deal.
          examples:
            - deal_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
          pattern: ^deal_[0-9a-f]{32}$
          title: Id
          type: string
        lost_justification:
          anyOf:
            - type: string
            - type: 'null'
          title: Lost Justification
        lost_reason:
          anyOf:
            - type: string
            - type: 'null'
          description: Name of the reason, when `status` is `lost`.
          title: Lost Reason
        object:
          const: deal
          default: deal
          title: Object
          type: string
        organization:
          anyOf:
            - $ref: '#/components/schemas/Organization'
            - type: 'null'
          description: Populated only when `organization` is in `expand`.
        organization_id:
          anyOf:
            - description: Unique identifier for an organization.
              examples:
                - org_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
              pattern: ^org_[0-9a-f]{32}$
              type: string
            - type: 'null'
          title: Organization Id
        owner:
          anyOf:
            - $ref: '#/components/schemas/Owner'
            - type: 'null'
          description: >-
            Whoever is responsible for this deal — a teammate or an AI agent.
            Always populated when the deal has an owner.
        owner_id:
          anyOf:
            - description: Unique identifier for an user.
              examples:
                - usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
              pattern: ^usr_[0-9a-f]{32}$
              type: string
            - type: 'null'
          deprecated: true
          description: >-
            Deprecated: use `owner` instead, which also covers AI-owned records.
            Null for a deal owned by an agent. Will be removed in a future
            release.
          title: Owner Id
        pipeline_id:
          description: Unique identifier for a pipeline.
          examples:
            - pipe_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
          pattern: ^pipe_[0-9a-f]{32}$
          title: Pipeline Id
          type: string
        probability:
          anyOf:
            - type: integer
            - type: 'null'
          description: >-
            Close probability override, 0-100. `null` means the deal inherits
            its current stage's default — read the stage to see it.
          title: Probability
        score:
          anyOf:
            - $ref: '#/components/schemas/OpportunityScore'
            - type: 'null'
        stage_changed_at:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          description: When the deal last moved between stages.
          title: Stage Changed At
        stage_id:
          description: Unique identifier for a stage.
          examples:
            - stg_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
          pattern: ^stg_[0-9a-f]{32}$
          title: Stage Id
          type: string
        status:
          $ref: '#/components/schemas/OpportunityStatus'
          default: open
        tags:
          items:
            $ref: '#/components/schemas/Tag'
          title: Tags
          type: array
        title:
          title: Title
          type: string
        updated_at:
          format: date-time
          title: Updated At
          type: string
        value:
          anyOf:
            - pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
              type: string
            - type: 'null'
          description: Monetary value. The workspace sets the currency.
          title: Value
        visibility:
          $ref: '#/components/schemas/RecordVisibility'
          description: >-
            Governs who sees this record in the Sailer UI. API tokens are
            workspace-scoped and are not filtered by it.
      required:
        - id
        - title
        - pipeline_id
        - stage_id
        - visibility
        - created_at
        - updated_at
      title: Deal
      type: object
    PageLinks:
      properties:
        next:
          anyOf:
            - type: string
            - type: 'null'
          description: Opaque cursor for the following page; null on the last page.
          title: Next
      title: PageLinks
      type: object
    PageMeta:
      properties:
        has_more:
          description: True when a next page exists.
          title: Has More
          type: boolean
        limit:
          description: Maximum items requested for this page.
          title: Limit
          type: integer
      required:
        - limit
        - has_more
      title: PageMeta
      type: object
    ValidationError:
      properties:
        ctx:
          title: Context
          type: object
        input:
          title: Input
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          title: Location
          type: array
        msg:
          title: Message
          type: string
        type:
          title: Error Type
          type: string
      required:
        - loc
        - msg
        - type
      title: ValidationError
      type: object
    OperatorType:
      enum:
        - equals
        - not_equals
        - is_empty
        - is_not_empty
        - contains
        - not_contains
        - starts_with
        - ends_with
        - greater_than
        - less_than
        - greater_than_or_equal_to
        - less_than_or_equal_to
        - is_relative_to_today
        - is_between
        - is_one_of
        - is_not_one_of
      title: OperatorType
      type: string
    Organization:
      description: A company a contact belongs to.
      properties:
        created_at:
          format: date-time
          title: Created At
          type: string
        custom_fields:
          additionalProperties: true
          description: >-
            Every custom field defined on organizations in this workspace, keyed
            by field key and typed from its definition. Unset fields are `null`,
            so reading any organization shows the full set of keys in use.
          title: Custom Fields
          type: object
        id:
          description: Unique identifier for an organization.
          examples:
            - org_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
          pattern: ^org_[0-9a-f]{32}$
          title: Id
          type: string
        name:
          title: Name
          type: string
        object:
          const: organization
          default: organization
          title: Object
          type: string
        owner:
          anyOf:
            - $ref: '#/components/schemas/Owner'
            - type: 'null'
          description: >-
            Whoever is responsible for this record. Always populated when the
            record has an owner — this is not an `expand` target.
        owner_id:
          anyOf:
            - description: Unique identifier for an user.
              examples:
                - usr_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
              pattern: ^usr_[0-9a-f]{32}$
              type: string
            - type: 'null'
          deprecated: true
          description: >-
            Deprecated: use `owner` instead, which also covers AI-owned records.
            Still populated for teammate-owned records; will be removed in a
            future release.
          title: Owner Id
        tags:
          items:
            $ref: '#/components/schemas/Tag'
          title: Tags
          type: array
        updated_at:
          format: date-time
          title: Updated At
          type: string
        visibility:
          $ref: '#/components/schemas/RecordVisibility'
          description: >-
            Governs who sees this record in the Sailer UI. API tokens are
            workspace-scoped and are not filtered by it.
        website:
          anyOf:
            - type: string
            - type: 'null'
          title: Website
      required:
        - id
        - name
        - visibility
        - created_at
        - updated_at
      title: Organization
      type: object
    Owner:
      description: >-
        Whoever is responsible for a record — a teammate or an AI agent.


        One nested object rather than a spread of ``owner_id`` /

        ``owner_user_id`` / ``owner_agent_id`` / ``owner_kind`` columns. Those
        exist

        internally because ownership by an AI was added to a schema that assumed
        a

        human, and a partner should not have to reconstruct "who owns this" from

        four fields and a rule about which take precedence.


        ``kind`` is the discriminator and ``id`` is prefixed accordingly, so the
        two

        can never disagree: an ``agt_…`` id is an agent by construction.
      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
    OpportunityScore:
      description: Temperature/score of an opportunity.
      enum:
        - cold
        - warm
        - hot
      title: OpportunityScore
      type: string
    OpportunityStatus:
      description: Status of an opportunity in the sales pipeline.
      enum:
        - open
        - won
        - lost
      title: OpportunityStatus
      type: string
    Tag:
      description: A CRM label. The catalogue is per entity type.
      properties:
        color:
          anyOf:
            - type: string
            - type: 'null'
          description: Hex colour used by the Sailer UI, e.g. `#FFAA00`.
          title: Color
        id:
          description: Unique identifier for a tag.
          examples:
            - tag_9f2ac41d8b7e4a51b0d3e6f7a1c2d3e4
          pattern: ^tag_[0-9a-f]{32}$
          title: Id
          type: string
        name:
          title: Name
          type: string
        object:
          const: tag
          default: tag
          title: Object
          type: string
      required:
        - id
        - name
      title: Tag
      type: object
    RecordVisibility:
      description: >-
        CRM record visibility levels; resolved live against the owner's current
        teams.
      enum:
        - private
        - team
        - team_and_subteams
        - company
      title: RecordVisibility
      type: string
  securitySchemes:
    SailerApiToken:
      description: >-
        A workspace API token. Create one in Settings → API. Send it as
        `Authorization: Bearer sk_live_...`.
      scheme: bearer
      type: http

````