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

# Registra uma venda

> Cria a venda e move o lead para a etapa de ganho.

**Um lead pode ter várias vendas.** Recompra é uma chamada nova, não uma
atualização da anterior.

**Idempotência:** mande `external_source` + `external_id` (o id da transação
na origem, ex. `HP2346486658`). O reenvio do mesmo par devolve `200` com
`duplicate: true` em vez de criar outra — é o que torna o replay de um
webhook de pagamento inofensivo. Sem `external_id` não há idempotência e
duas chamadas viram duas vendas.




## OpenAPI

````yaml /openapi.yaml post /sales
openapi: 3.1.0
info:
  title: Metricaas API
  version: 1.0.0
  description: >
    API do Metricaas para automatizar o CRM de fora dele — registrar vendas de
    uma

    plataforma de pagamento, ler leads e conferir a atribuição de origem.


    **Base:** `https://app.metricaas.com.br/v1`


    Todo endpoint é server-to-server. Não há CORS: um token de API nunca deve ir

    para o navegador.
servers:
  - url: https://app.metricaas.com.br/v1
security:
  - bearerAuth: []
tags:
  - name: Sessão
  - name: Leads
  - name: Vendas
paths:
  /sales:
    post:
      tags:
        - Vendas
      summary: Registra uma venda
      description: >
        Cria a venda e move o lead para a etapa de ganho.


        **Um lead pode ter várias vendas.** Recompra é uma chamada nova, não uma

        atualização da anterior.


        **Idempotência:** mande `external_source` + `external_id` (o id da
        transação

        na origem, ex. `HP2346486658`). O reenvio do mesmo par devolve `200` com

        `duplicate: true` em vez de criar outra — é o que torna o replay de um

        webhook de pagamento inofensivo. Sem `external_id` não há idempotência e

        duas chamadas viram duas vendas.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - lead_id
                - value
                - sold_at
              properties:
                lead_id:
                  type: string
                  format: uuid
                value:
                  type: number
                  exclusiveMinimum: 0
                  example: 67
                sold_at:
                  type: string
                  example: '2026-08-07T11:49:12-03:00'
                  description: >
                    Quando o cliente **comprou**, não quando você está lançando.


                    **O offset é obrigatório.** O Metricaas grava em UTC; se
                    você

                    mandar `2026-08-07T00:52:14` sem fuso, a compra da madrugada

                    vira o dia anterior em todo relatório. Sem offset a API

                    responde `422` em vez de adivinhar.
                currency:
                  type: string
                  default: BRL
                product_id:
                  type: string
                  format: uuid
                  nullable: true
                external_source:
                  type: string
                  example: hotmart
                external_id:
                  type: string
                  example: HP2346486658
      responses:
        '200':
          description: Já existia (mesmo `external_source` + `external_id`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VendaCriada'
        '201':
          description: Venda criada
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VendaCriada'
        '404':
          $ref: '#/components/responses/NaoEncontrado'
        '422':
          $ref: '#/components/responses/Invalido'
components:
  schemas:
    VendaCriada:
      type: object
      properties:
        id:
          type: string
          format: uuid
        lead_id:
          type: string
          format: uuid
        value:
          type: number
        sold_at:
          type: string
          format: date-time
        stage:
          type: string
        duplicate:
          type: boolean
          description: '`true` quando o par external_source+external_id já existia.'
    Problema:
      type: object
      description: Erros seguem RFC 7807.
      properties:
        type:
          type: string
        title:
          type: string
        status:
          type: integer
        detail:
          type: string
        errors:
          type: array
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string
  responses:
    NaoEncontrado:
      description: >
        Não existe **ou** é de outra empresa. A API responde `404` nos dois
        casos

        de propósito: um `403` confirmaria que o id existe.
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problema'
    Invalido:
      description: Validação — veja `errors[]`
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Problema'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >
        `Authorization: Bearer mcp_…` — gere em **Configurações → Tokens de
        API**.


        O token tem modo `read` ou `write`. Um token `read` responde `403` a

        qualquer verbo que não seja `GET`. As capacidades do token são a

        **interseção** com as da pessoa que o emitiu: se ela perder acesso na

        grade de Equipe, o token perde junto, sem ninguém revogar nada.

````