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

# Get sales performance

> Counts only business cards with won status.



## OpenAPI

````yaml /api-reference/openapi.en.yaml get /products/{id}/performance
openapi: 3.0.3
info:
  title: Connecta DESK Public API
  version: 1.0.0
  description: >-
    Public API of Connecta DESK, available at `/api/v1`. Access uses a token
    generated in the tokens module. Each token has permissions per **module ×
    method**, and every list read is paginated.


    ## Authentication


    ```

    Authorization: Bearer sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6

    ```


    The token belongs to a **company**, not to a user. The company used is
    always the token's company, so sending `companyId` in the body has no
    effect. A missing, invalid, revoked or expired token gets the same `401`
    response.


    ## Order of checks


    1. **token** → `401`

    2. **active company** → `403`

    3. **API enabled on the plan** → `403 ERR_API_NOT_ENABLED` (does not apply
    to on-premise)

    4. **company rate limit** → `429`

    5. **token permission** → `403 ERR_API_FORBIDDEN_SCOPE`


    ## User ids


    Every user id in the API is the user's id **in this company**, the same one
    `GET /users` returns. This applies to what the API returns (`user.id`,
    `assignedTo.id`, `userCreated.id`) and to what it accepts (`userId`,
    `userIds`, `assignedToUserId` and the `{id}` in user routes).


    The same person can work in several companies, with a different name and
    profile in each one, and has a different id in each company.


    An id that does not belong to this company returns `404`, with the same
    message as an id that does not exist.


    ## Pagination


    Every list `GET` is paginated. The `meta` contains only `page`, `perPage`
    and `hasMore`, without the total number of records. To go through
    everything, keep advancing `page` while `hasMore` is `true`.


    ## Idempotency


    Optional on `POST`/`PUT`, through the `Idempotency-Key` header. If you
    repeat the call with the same key and the same body, you get the stored
    response (with `Idempotent-Replay: true`). With the same key and a different
    body, the response is `409`.
servers:
  - url: https://api.connectadesk.com/api/v1
    description: Production
security:
  - apiToken: []
tags:
  - name: contacts
    description: Contact records, extra fields and marketing source.
  - name: tickets
    x-displayName: Tickets
    description: Opening, transferring, closing and wrap-up of tickets.
  - name: messages
    description: Asynchronous sending and reading of messages.
  - name: tags
    description: Tags and their link to tickets.
  - name: queues
    description: Service queues and their agents.
  - name: wrapups
    description: Wrap-up types.
  - name: users
    description: Agents and administrators.
  - name: schedules
    description: Scheduled messages.
  - name: quick-messages
    description: Quick replies.
  - name: campaigns
    description: Bulk sending.
  - name: crm
    description: Boards, stages, cards and metrics.
  - name: channels
    description: Channels (read only).
  - name: reports
    description: Reports and dashboards.
  - name: products
    description: Product catalog, categories and sales performance.
  - name: custom-fields
    description: Custom fields for contacts and cards, plus company-wide global variables.
  - name: profiles
    description: Company permission profiles (read only).
  - name: webchat
    description: >-
      Native webchat from your own system: open a visitor session, send and read
      messages. The token needs the `webchat` scope (GET and POST).
paths:
  /products/{id}/performance:
    parameters:
      - name: id
        in: path
        required: true
        schema:
          type: integer
    get:
      tags:
        - products
      summary: Get sales performance
      description: Counts only business cards with won status.
      parameters:
        - name: startDate
          in: query
          description: 'Start of the period (default: 12 months ago).'
          schema:
            type: string
            format: date
          example: '2026-09-01'
        - name: endDate
          in: query
          description: >-
            End of the period (default: today). The period can be at most 24
            months long.
          schema:
            type: string
            format: date
          example: '2026-09-30'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/ProductPerformance'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  schemas:
    ProductPerformance:
      type: object
      description: >-
        Sales performance of the product. It counts **only** deal cards with won
        status. The amount used is the product's price at the moment the card
        was closed, so price changes in the catalog do not change the history.
        Months follow the company's time zone.
      properties:
        startDate:
          type: string
          format: date-time
        endDate:
          type: string
          format: date-time
        summary:
          type: object
          properties:
            wonCards:
              type: integer
              description: Deals closed with this product.
            wonValue:
              type: string
              example: '12450.00'
            units:
              type: integer
              description: Quantity of the product sold.
            averageTicket:
              type: string
              example: '1245.00'
            lastWonDate:
              type: string
              format: date-time
              nullable: true
        series:
          type: array
          description: >-
            One item per month in the period. Months with no sales show zero
            values.
          items:
            type: object
            properties:
              month:
                type: string
                example: 2026-08
              cards:
                type: integer
              units:
                type: integer
              value:
                type: string
                example: '3200.00'
      example:
        startDate: '2025-09-01T03:00:00.000Z'
        endDate: '2026-09-01T02:59:59.999Z'
        summary:
          wonCards: 9
          wonValue: '12450.00'
          units: 11
          averageTicket: '1383.33'
          lastWonDate: '2026-08-27T18:22:00.000Z'
        series:
          - month: 2026-07
            cards: 2
            units: 2
            value: '2599.80'
          - month: 2026-08
            cards: 3
            units: 4
            value: '5199.60'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Fixed error code, so your system can handle each case.
              example: ERR_API_FORBIDDEN_SCOPE
            message:
              type: string
            details: {}
  responses:
    BadRequest:
      description: Invalid request body.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ERR_API_VALIDATION
              message: O campo `number` é obrigatório.
    Unauthorized:
      description: Token missing, invalid, revoked or expired.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ERR_API_UNAUTHORIZED
              message: Token de API ausente ou inválido.
    Forbidden:
      description: >-
        Inactive company, API not enabled on the plan, or insufficient
        permission.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ERR_API_FORBIDDEN_SCOPE
              message: >-
                O token não tem permissão para este método neste módulo. A
                mensagem real nomeia os dois.
    NotFound:
      description: >-
        The resource does not exist or belongs to another company. For security,
        the response is the same in both cases.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: ERR_API_NOT_FOUND
              message: Registro não encontrado.
  securitySchemes:
    apiToken:
      type: http
      scheme: bearer
      description: API token in the `sk_live_…` format.

````

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