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

# Vendas (regime competência)

> Vendas com data de competência no período, paginadas, da mais recente para a mais antiga.

- **Não existe campo `quitada`.** `status` e `recebimento_status` saem crus e podem discordar entre si e da dívida. "Quanto falta receber" é `divida_em_aberto`, que vem `null` em venda cancelada.
- **Não existe taxa em R$.** A taxa sai em % (na venda ou em cada perna); o valor já vem descontado em `valor_liquido`.
- `formas_pagamento` é uma foto da venda e não acompanha as baixas.
- Profissionais saem só como id: o nome está em `/v1/scheduling/professionals`.
- `search` (paciente, número da venda ou procedimento) e os dados do paciente exigem `sensitive:read`.
- Só lançamentos com ao menos um item vendido, como a aba Vendas de `/incomes`.



## OpenAPI

````yaml https://api.controleclinic.com.br/v1/openapi.json get /v1/financial/sales
openapi: 3.0.0
info:
  title: Controle Clinic API
  version: v1
  description: >-
    API de automações e integrações externas do Controle Clinic. Conecte n8n,
    CRMs, ERPs e chatbots à sua clínica.


    ## Comece aqui

    1. Crie a chave em **Configurações → Clínica → Integrações → Tokens de
    API**. Marque só os escopos de que precisa e defina uma validade.

    2. Envie a chave no cabeçalho `X-API-Key` em toda chamada. Para testar por
    aqui, cole a chave no cartão **Sua chave**.

    3. Limite: **60 chamadas por minuto** por chave (plano pro). Os cabeçalhos
    `X-RateLimit-Limit`, `X-RateLimit-Remaining` e `X-RateLimit-Reset` mostram o
    saldo; acima do limite a resposta é `429`.

    4. Toda chamada fica registrada em **Logs de Auditoria**, na mesma tela dos
    tokens.


    ## Integração contínua × migração

    Esta API serve para um sistema externo criar e atualizar pacientes e
    agendamentos **daqui para a frente**.

    Para trazer o **histórico** de outro sistema (pacientes, prontuário, agenda
    passada, financeiro), use a **Central de Migração**, com o time de
    implantação: ela tem prévia, de-para e desfazer, que a API não tem.


    ## Erros comuns a todas as rotas

    - `400` corpo ou parâmetro inválido (o corpo diz qual campo)

    - `401` chave ausente, inválida, revogada ou vencida

    - `403` escopo insuficiente ou clínica com acesso suspenso

    - `429` limite de chamadas

    - `500` erro interno — tente de novo mais tarde; se repetir, abra chamado
    informando o horário


    ⚠️ As rotas `POST`, `PATCH` e `DELETE` gravam **de verdade** na clínica dona
    da chave, inclusive pelo botão de teste desta página.
servers:
  - url: https://api.controleclinic.com.br
    description: Produção
security: []
tags:
  - name: Agendamentos
    description: >-
      **Para agendar um paciente:**

      1. `GET /v1/scheduling/professionals`, `/procedures`, `/rooms` e
      `/technologies` — pegue os `id` (eles não mudam; guarde no seu sistema).

      2. `POST /v1/scheduling/patients` com nome, CPF e telefone. Se voltar
      `409`, o paciente já existe: use `existing.id`.

      3. `POST /v1/scheduling/appointments` com `patient_id`, `professional_id`,
      `start_at` e `end_at`.

      4. Para confirmar, cancelar ou remarcar: `PATCH
      /v1/scheduling/appointments/{id}`.


      Datas em ISO 8601 **com fuso**: `2026-11-10T14:00:00-03:00`. Sem fuso, o
      horário é lido como UTC e aparece 3 horas adiantado na agenda.
  - name: Lookup
    description: >-
      Cadastros da clínica que um agendamento referencia: profissionais,
      procedimentos, salas e tecnologias. Só leitura; traz apenas os ativos.
  - name: Sistema
    description: >-
      Conferência da conexão (`/health`, sem chave) e da chave em uso (`/me`:
      escopos, validade e clínica).
  - name: Pacientes
    description: >-
      Cadastro de pacientes da clínica da chave. A API não apaga paciente. Sem
      `sensitive:read`, CPF, telefone, e-mail e nascimento saem mascarados.
  - name: Financeiro
    description: >-
      Leitura do financeiro da clínica dona da chave (escopo `financial:read`).
      **Nenhuma rota escreve.**


      Toda resposta traz `regime` (`competencia`, `caixa`, `vencimento` ou
      `saldo`): somar números de regimes diferentes dá um total sem sentido
      (ex.: entradas de caixa não são faturamento).


      Nome, CPF, `patient_id` e descrições só existem na resposta com o escopo
      `sensitive:read` (sem ele, o campo não vem, nem como `null`). O nome do
      fornecedor das despesas sai com `sensitive:read` ou `financial:suppliers`.


      Não há rotas de escrita no financeiro. Para trazer receitas e despesas de
      outro sistema, use a **Central de Migração** ou o importador de receitas,
      com o time de implantação.
paths:
  /v1/financial/sales:
    get:
      tags:
        - Financeiro
      summary: Vendas (regime competência)
      description: >-
        Vendas com data de competência no período, paginadas, da mais recente
        para a mais antiga.


        - **Não existe campo `quitada`.** `status` e `recebimento_status` saem
        crus e podem discordar entre si e da dívida. "Quanto falta receber" é
        `divida_em_aberto`, que vem `null` em venda cancelada.

        - **Não existe taxa em R$.** A taxa sai em % (na venda ou em cada
        perna); o valor já vem descontado em `valor_liquido`.

        - `formas_pagamento` é uma foto da venda e não acompanha as baixas.

        - Profissionais saem só como id: o nome está em
        `/v1/scheduling/professionals`.

        - `search` (paciente, número da venda ou procedimento) e os dados do
        paciente exigem `sensitive:read`.

        - Só lançamentos com ao menos um item vendido, como a aba Vendas de
        `/incomes`.
      parameters:
        - schema:
            type: string
            description: Data AAAA-MM-DD
            example: '2026-10-01'
          required: true
          name: from
          in: query
        - schema:
            type: string
            description: Data AAAA-MM-DD
            example: '2026-10-01'
          required: true
          name: to
          in: query
        - schema:
            type: string
            enum:
              - all
              - em_aberto
              - recebido
            default: all
          required: false
          name: status
          in: query
        - schema:
            type: string
            enum:
              - 'true'
              - 'false'
            default: 'false'
          required: false
          name: include_cancelled
          in: query
        - schema:
            type: string
            maxLength: 200
            description: Só com o escopo sensitive:read
          required: false
          name: search
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 1000000
            default: 1
          required: false
          name: page
          in: query
        - schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
          required: false
          name: limit
          in: query
      responses:
        '200':
          description: Vendas
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        numero_venda:
                          type: number
                          nullable: true
                        data_competencia:
                          type: string
                          nullable: true
                        valor_bruto:
                          type: number
                          nullable: true
                        desconto:
                          type: number
                          nullable: true
                          description: Desconto da venda, em R$.
                        valor_liquido:
                          type: number
                          nullable: true
                          description: >-
                            Já descontada a taxa de cartão. Não existe campo
                            "taxa em R$".
                        forma_pagamento:
                          type: string
                          nullable: true
                        taxa_percentual:
                          type: number
                          nullable: true
                          description: >-
                            Taxa em %. `null` quando a forma é 'Múltiplos': a
                            taxa vem em cada perna de `formas_pagamento`.
                        bandeira:
                          type: string
                          nullable: true
                        parcelas:
                          type: number
                          nullable: true
                        profissional_venda_id:
                          type: string
                          nullable: true
                        conta_id:
                          type: string
                          nullable: true
                        centro_custo_id:
                          type: string
                          nullable: true
                        status:
                          type: string
                          nullable: true
                          description: >-
                            Cru (`pending`/`paid`). Pode discordar de
                            `recebimento_status` e da dívida.
                        recebimento_status:
                          type: string
                          nullable: true
                        cancelada:
                          type: boolean
                        divida_em_aberto:
                          type: number
                          nullable: true
                          description: >-
                            Quanto falta receber (régua do card "Em aberto" de
                            /incomes). `null` em venda cancelada.
                        formas_pagamento:
                          type: array
                          items:
                            type: object
                            properties:
                              forma:
                                type: string
                                nullable: true
                              valor:
                                type: number
                                nullable: true
                              parcelas:
                                type: number
                                nullable: true
                              taxa_percentual:
                                type: number
                                nullable: true
                              bandeira:
                                type: string
                                nullable: true
                              conta_id:
                                type: string
                                nullable: true
                            required:
                              - forma
                              - valor
                              - parcelas
                              - taxa_percentual
                              - bandeira
                              - conta_id
                          description: >-
                            Foto da venda, não é atualizada nas baixas. `[]`
                            quando a venda não tem pernas: vale
                            `forma_pagamento`.
                        itens:
                          type: array
                          items:
                            type: object
                            properties:
                              procedure_id:
                                type: string
                                nullable: true
                              procedimento:
                                type: string
                                nullable: true
                              categoria:
                                type: string
                                nullable: true
                              quantidade:
                                type: number
                                nullable: true
                              valor_cobrado:
                                type: number
                                nullable: true
                              desconto:
                                type: number
                                nullable: true
                                description: Desconto do item, sempre em R$.
                              vendido:
                                type: boolean
                              profissional_execucao_id:
                                type: string
                                nullable: true
                            required:
                              - procedure_id
                              - procedimento
                              - categoria
                              - quantidade
                              - valor_cobrado
                              - desconto
                              - vendido
                              - profissional_execucao_id
                        patient_id:
                          type: string
                          nullable: true
                          description: Só com o escopo sensitive:read
                        paciente_nome:
                          type: string
                          nullable: true
                          description: Só com o escopo sensitive:read
                        paciente_cpf:
                          type: string
                          nullable: true
                          description: Só com o escopo sensitive:read
                        descricao:
                          type: string
                          nullable: true
                          description: Só com o escopo sensitive:read
                      required:
                        - id
                        - numero_venda
                        - data_competencia
                        - valor_bruto
                        - desconto
                        - valor_liquido
                        - forma_pagamento
                        - taxa_percentual
                        - bandeira
                        - parcelas
                        - profissional_venda_id
                        - conta_id
                        - centro_custo_id
                        - status
                        - recebimento_status
                        - cancelada
                        - divida_em_aberto
                        - formas_pagamento
                        - itens
                  count:
                    type: number
                  page:
                    type: number
                  limit:
                    type: number
                  regime:
                    type: string
                    enum:
                      - competencia
                  periodo:
                    type: object
                    properties:
                      from:
                        type: string
                      to:
                        type: string
                    required:
                      - from
                      - to
                required:
                  - data
                  - count
                  - page
                  - limit
                  - regime
                  - periodo
        '400':
          description: Parâmetro inválido
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
        '401':
          description: Chave ausente, inválida ou expirada
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
        '403':
          description: Escopo insuficiente ou clínica suspensa
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Insufficient scope
                  code:
                    type: string
                    description: '`acesso_suspenso` quando a clínica está suspensa.'
                required:
                  - error
        '500':
          description: Erro interno
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                required:
                  - error
      security:
        - ApiKeyAuth: []
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        Token de API no formato cc_live_<64 chars hex>. Obtido em Minha Clínica
        → Integrações.

````

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