{
  "profile": {
    "profile": "public-consultations-v1",
    "audience": "Clientes e integradores externos",
    "reviewedAt": "2026-10-02",
    "availability": "A edição pública cobre somente consultas e validações selecionadas. Confirme a versão e o endereço da sua instância com o administrador."
  },
  "methods": [
    {
      "method": "messages.list",
      "category": "Mensagens",
      "summary": "Listar mensagens",
      "description": "Obtém as mensagens mais recentes de uma conversa da empresa do token, excluindo linhas com deleted=true.",
      "params": [
        {
          "name": "conversation_id",
          "type": "string (UUID)",
          "required": true,
          "description": "ID da conversa.",
          "example": "22222222-2222-4222-8222-222222222222"
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "description": "Máximo de mensagens. Padrão: 50; mínimo 1, máximo 200.",
          "example": 50
        },
        {
          "name": "before",
          "type": "string",
          "required": false,
          "description": "Cursor opaco retornado em next_cursor para buscar a página seguinte. Por compatibilidade, também aceita o UUID de uma mensagem da mesma conversa. Máximo: 2048 caracteres.",
          "example": "eyJ2IjoxLCJpZCI6IjU1NTU1NTU1LTU1NTUtNDU1NS04NTU1LTU1NTU1NTU1NTU1NSIsImF0IjoiMjAyNi0wOS0xOFQxMjowMDowMC4wMDBaIn0"
        }
      ],
      "requestExample": {
        "conversation_id": "22222222-2222-4222-8222-222222222222",
        "limit": 50,
        "before": "eyJ2IjoxLCJpZCI6IjU1NTU1NTU1LTU1NTUtNDU1NS04NTU1LTU1NTU1NTU1NTU1NSIsImF0IjoiMjAyNi0wOS0xOFQxMjowMDowMC4wMDBaIn0"
      },
      "responseExample": {
        "total": 1,
        "total_count": 1,
        "messages": [
          {
            "id": "55555555-5555-4555-8555-555555555555",
            "sender_type": "system",
            "content": "Nota de exemplo",
            "message_type": "note",
            "media_url": null,
            "delivery_status": null,
            "created_at": "2026-09-18T12:00:00.000Z",
            "delivered_at": null,
            "read_at": null
          }
        ],
        "hasMore": false,
        "next_cursor": null
      },
      "errors": [
        {
          "status": 400,
          "code": "BAD_REQUEST",
          "description": "conversation_id ausente/inválido ou cursor before inválido."
        },
        {
          "status": 403,
          "code": "NO_COMPANY",
          "description": "Token sem empresa associada."
        },
        {
          "status": 404,
          "code": "NOT_FOUND",
          "description": "Conversa inexistente/de outra empresa, ou cursor que não pertence ao histórico consultado."
        }
      ],
      "notes": [
        "Ordenação estável por created_at decrescente, com valores null primeiro, e id decrescente para desempate.",
        "total é o tamanho do lote retornado; total_count conta todo o histórico não excluído da conversa. hasMore indica continuação e next_cursor contém o cursor opaco da próxima página ou null.",
        "Reenvie next_cursor em before sem interpretar ou modificar seu conteúdo. O UUID legado de uma mensagem da mesma conversa também é aceito como âncora.",
        "Conversa inexistente/de outra empresa ou cursor ausente desse histórico retorna HTTP 404 NOT_FOUND. Cursor malformado, adulterado ou maior que 2048 caracteres retorna HTTP 400 BAD_REQUEST.",
        "Cada item inclui delivered_at e read_at; ambos podem ser null. Eles representam a primeira evidência persistida pelo SYSLED, não o instante físico exato no aparelho. Em linhas legadas/incompletas, até status delivered/read pode permanecer sem horário até surgir evidência correspondente.",
        "Resposta ilustrativa do campo result; IDs, nomes e valores são fictícios. Campos adicionais podem existir.",
        "Pode retornar conteúdo de conversas e URLs de mídia. Use escopo exclusivo, aplique as regras de proteção de dados da sua empresa e não registre o conteúdo sem necessidade."
      ],
      "group": "messages",
      "groupName": "Mensagens"
    },
    {
      "method": "leads.list",
      "category": "CRM",
      "summary": "Listar leads",
      "description": "Lista leads com total real, contagem por status e paginação.",
      "params": [
        {
          "name": "status",
          "type": "string",
          "required": false,
          "description": "Status: new, converted ou junk. Sem filtro inclui todos.",
          "example": "new"
        },
        {
          "name": "status_in",
          "type": "string[] | string CSV",
          "required": false,
          "description": "Status aceitos; pode combinar com status.",
          "example": [
            "new",
            "converted"
          ]
        },
        {
          "name": "search",
          "type": "string",
          "required": false,
          "description": "Busca parcial em nome, título, telefone e e-mail.",
          "example": "Exemplo"
        },
        {
          "name": "assigned_to",
          "type": "string (uuid)",
          "required": false,
          "description": "ID do responsável.",
          "example": "00000000-0000-4000-8000-000000000001"
        },
        {
          "name": "assigned_to_in",
          "type": "string[] | string CSV",
          "required": false,
          "description": "IDs de responsáveis.",
          "example": [
            "00000000-0000-4000-8000-000000000001"
          ]
        },
        {
          "name": "source_id_in",
          "type": "integer[] | string CSV",
          "required": false,
          "description": "IDs de origens.",
          "example": [
            1,
            2
          ]
        },
        {
          "name": "created_from",
          "type": "string (date/date-time)",
          "required": false,
          "description": "Data inicial inclusiva.",
          "example": "2026-09-01"
        },
        {
          "name": "created_to",
          "type": "string (date/date-time)",
          "required": false,
          "description": "Inclui até o dia final; implementação usa limite menor que data + 1 dia.",
          "example": "2026-09-01"
        },
        {
          "name": "junked_from",
          "type": "string (date/date-time)",
          "required": false,
          "description": "Data inicial inclusiva.",
          "example": "2026-09-01"
        },
        {
          "name": "junked_to",
          "type": "string (date/date-time)",
          "required": false,
          "description": "Inclui até o dia final; implementação usa limite menor que data + 1 dia.",
          "example": "2026-09-01"
        },
        {
          "name": "converted_from",
          "type": "string (date/date-time)",
          "required": false,
          "description": "Data inicial inclusiva.",
          "example": "2026-09-01"
        },
        {
          "name": "converted_to",
          "type": "string (date/date-time)",
          "required": false,
          "description": "Inclui até o dia final; implementação usa limite menor que data + 1 dia.",
          "example": "2026-09-01"
        },
        {
          "name": "opportunity_min",
          "type": "number",
          "required": false,
          "description": "Valor mínimo inclusivo.",
          "example": 100
        },
        {
          "name": "opportunity_max",
          "type": "number",
          "required": false,
          "description": "Valor máximo inclusivo.",
          "example": 2000
        },
        {
          "name": "has_conversation",
          "type": "boolean",
          "required": false,
          "description": "true com conversa; false sem conversa.",
          "example": true
        },
        {
          "name": "page",
          "type": "integer",
          "required": false,
          "description": "Página iniciada em 1; padrão 1.",
          "example": 1
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "description": "Padrão 50; máximo 200. Use valores positivos; limite negativo não é validado corretamente.",
          "example": 50
        },
        {
          "name": "order_by",
          "type": "string",
          "required": false,
          "description": "created_at_desc (padrão), created_at_asc, opportunity_desc, opportunity_asc ou name_asc.",
          "example": "created_at_desc"
        }
      ],
      "requestExample": {
        "status": "new",
        "page": 1,
        "limit": 50
      },
      "responseExample": {
        "rows": [
          {
            "id": 101,
            "name": "Pessoa Exemplo",
            "status": "new",
            "opportunity": "1500.00",
            "phone": [
              {
                "value": "+5585000000000",
                "type": "WORK"
              }
            ],
            "email": [
              {
                "value": "pessoa@example.com",
                "type": "WORK"
              }
            ]
          }
        ],
        "total": 1,
        "by_status": {
          "new": 1,
          "converted": 0,
          "junk": 0
        },
        "page": 1,
        "limit": 50
      },
      "errors": [],
      "notes": [
        "Exemplos ilustrativos e parciais: os registros podem retornar outros campos; não representam dados reais.",
        "total e by_status correspondem a todos os registros que atendem aos filtros, não só à página.",
        "Não existe parâmetro pipeline_id para lead.",
        "Pode retornar dados pessoais e comerciais. Restrinja o token ao método, limite a retenção e aplique as regras de proteção de dados da sua empresa."
      ],
      "group": "leads",
      "groupName": "Leads"
    },
    {
      "method": "pipelines.get",
      "category": "CRM",
      "summary": "Obter funil",
      "description": "Obtém um funil ativo com etapas e agregados.",
      "params": [
        {
          "name": "id",
          "type": "integer",
          "required": true,
          "description": "Identificador numérico do registro.",
          "example": 101
        }
      ],
      "requestExample": {
        "id": 10
      },
      "responseExample": {
        "found": true,
        "pipeline": {
          "id": 10,
          "name": "Funil Exemplo",
          "slug": "funil-exemplo",
          "is_default": false,
          "type": "sales",
          "color": "#2684FF",
          "sort_order": 100,
          "total_deals": 1,
          "total_value": 1500,
          "stages": [
            {
              "id": 11,
              "name": "Em andamento",
              "slug": "em-andamento-exemplo",
              "type": "process",
              "color": "#3b82f6",
              "sort_order": 10,
              "deals_count": 1,
              "open_count": 1,
              "deals_value": 1500
            }
          ]
        }
      },
      "errors": [
        {
          "status": 400,
          "code": "PIPELINE_ID_REQUIRED",
          "description": "id ausente ou diferente de inteiro positivo."
        }
      ],
      "notes": [
        "Exemplos ilustrativos e parciais: os registros podem retornar outros campos; não representam dados reais.",
        "Resposta singular {found,pipeline}, não {total,pipelines}.",
        "Ausente, inativo ou fora da empresa (exceto global): {found:false,pipeline:null}."
      ],
      "group": "pipelines",
      "groupName": "Funis"
    },
    {
      "method": "pipelines.list",
      "category": "CRM",
      "summary": "Listar funis",
      "description": "Lista funis ativos da empresa e globais, com etapas e agregados dos negócios da empresa.",
      "params": [
        {
          "name": "pipeline_id",
          "type": "integer",
          "required": false,
          "description": "Filtro opcional por um funil. Valor inválido é ignorado.",
          "example": 10
        }
      ],
      "requestExample": {
        "pipeline_id": 10
      },
      "responseExample": {
        "total": 1,
        "pipelines": [
          {
            "id": 10,
            "name": "Funil Exemplo",
            "slug": "funil-exemplo",
            "is_default": false,
            "type": "sales",
            "color": "#2684FF",
            "sort_order": 100,
            "total_deals": 1,
            "total_value": 1500,
            "stages": [
              {
                "id": 11,
                "name": "Em andamento",
                "slug": "em-andamento-exemplo",
                "type": "process",
                "color": "#3b82f6",
                "sort_order": 10,
                "deals_count": 1,
                "open_count": 1,
                "deals_value": 1500
              }
            ]
          }
        ]
      },
      "errors": [],
      "notes": [
        "Exemplos ilustrativos e parciais: os registros podem retornar outros campos; não representam dados reais.",
        "Não possui paginação. total é a quantidade de funis retornados.",
        "deals_count inclui negócios abertos e encerrados com archived=false; open_count restringe is_closed=false. Valores archived NULL não entram no agregado atual.",
        "total_value/deals_value são números; total_value arredondado a duas casas."
      ],
      "group": "pipelines",
      "groupName": "Funis"
    },
    {
      "method": "stages.list",
      "category": "CRM",
      "summary": "Listar etapas",
      "description": "Lista as etapas de um funil da empresa, por sort_order e id.",
      "params": [
        {
          "name": "pipeline_id",
          "type": "integer",
          "required": true,
          "description": "Funil pertencente à empresa do token.",
          "example": 10
        }
      ],
      "requestExample": {
        "pipeline_id": 10
      },
      "responseExample": {
        "total": 1,
        "stages": [
          {
            "id": 11,
            "pipeline_id": 10,
            "name": "Em andamento",
            "slug": "em-andamento-exemplo",
            "type": "process",
            "color": "#3b82f6",
            "sort_order": 10
          }
        ]
      },
      "errors": [
        {
          "status": 400,
          "code": "BAD_REQUEST",
          "description": "Parâmetro obrigatório ausente ou valor inválido."
        },
        {
          "status": 404,
          "code": "PIPELINE_NOT_FOUND",
          "description": "Funil não encontrado ou não pertence à empresa do token (inclui funil global)."
        }
      ],
      "notes": [
        "Exemplos ilustrativos e parciais: os registros podem retornar outros campos; não representam dados reais.",
        "Não possui paginação. O método não aceita funil global, mesmo quando pipelines.list o apresenta."
      ],
      "group": "stages",
      "groupName": "Etapas"
    },
    {
      "method": "tasks.get",
      "category": "CRM",
      "summary": "Obter tarefa",
      "description": "Obtém atividade e nome do responsável.",
      "params": [
        {
          "name": "id",
          "type": "integer",
          "required": true,
          "description": "Identificador numérico do registro.",
          "example": 101
        }
      ],
      "requestExample": {
        "id": 401
      },
      "responseExample": {
        "found": true,
        "task": {
          "id": 401,
          "owner_type": "deal",
          "owner_id": 201,
          "type": "todo",
          "subject": "Revisar proposta",
          "completed": false,
          "responsible_id": null,
          "deadline": "2026-09-25T10:00:00",
          "responsible_name": null
        }
      },
      "errors": [
        {
          "status": 400,
          "code": "BAD_REQUEST",
          "description": "Parâmetro obrigatório ausente ou valor inválido."
        }
      ],
      "notes": [
        "Exemplos ilustrativos e parciais: os registros podem retornar outros campos; não representam dados reais.",
        "Ausente/fora da empresa: {found:false,task:null}.",
        "deadline não traz offset de fuso horário em list/get."
      ],
      "group": "tasks",
      "groupName": "Tarefas"
    },
    {
      "method": "tasks.list",
      "category": "CRM",
      "summary": "Listar tarefas",
      "description": "Lista atividades do CRM por dono, conclusão, responsável e atraso.",
      "params": [
        {
          "name": "owner_type",
          "type": "string",
          "required": false,
          "description": "deal (padrão), contact (contato comercial) ou lead.",
          "example": "deal"
        },
        {
          "name": "owner_id",
          "type": "integer",
          "required": false,
          "description": "Obrigatório se owner_type for enviado; se apenas owner_id for enviado, owner_type=deal.",
          "example": 201
        },
        {
          "name": "completed",
          "type": "boolean",
          "required": false,
          "description": "true concluídas; false pendentes. Ausente inclui ambas.",
          "example": false
        },
        {
          "name": "responsible_id",
          "type": "string (uuid) | null",
          "required": false,
          "description": "Usuário com acesso à empresa por vínculo principal ou multifilial.",
          "example": "00000000-0000-4000-8000-000000000001"
        },
        {
          "name": "overdue",
          "type": "boolean",
          "required": false,
          "description": "true: somente pendentes com prazo anterior a NOW().",
          "example": true
        },
        {
          "name": "page",
          "type": "integer",
          "required": false,
          "description": "Página iniciada em 1; padrão 1.",
          "example": 1
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "description": "Padrão 25; mínimo 1, máximo 100.",
          "example": 25
        }
      ],
      "requestExample": {
        "owner_type": "deal",
        "owner_id": 201,
        "completed": false,
        "page": 1,
        "limit": 25
      },
      "responseExample": {
        "total": 1,
        "tasks": [
          {
            "id": 401,
            "owner_type": "deal",
            "owner_id": 201,
            "type": "todo",
            "subject": "Revisar proposta",
            "completed": false,
            "responsible_id": null,
            "deadline": "2026-09-25T10:00:00",
            "responsible_name": null
          }
        ]
      },
      "errors": [
        {
          "status": 400,
          "code": "BAD_REQUEST",
          "description": "Parâmetro obrigatório ausente ou valor inválido."
        },
        {
          "status": 400,
          "code": "INVALID_OWNER_TYPE",
          "description": "owner_type fora de deal, contact, lead."
        }
      ],
      "notes": [
        "Exemplos ilustrativos e parciais: os registros podem retornar outros campos; não representam dados reais.",
        "total é tamanho da página, não total global. page/limit não são devolvidos.",
        "Ordenação: pendentes primeiro, deadline crescente (nulos por último), criação decrescente.",
        "O filtro responsible_id é de igualdade; null não serve para selecionar tarefas sem responsável."
      ],
      "group": "tasks",
      "groupName": "Tarefas"
    },
    {
      "method": "products.brands",
      "category": "Catálogo",
      "summary": "Listar marcas",
      "description": "Marcas ativas com produtos ativos, contagem por marca e ordenação alfabética.",
      "params": [],
      "requestExample": {},
      "responseExample": {
        "marcas": [
          {
            "marca_id": "22222222-2222-4222-8222-222222222222",
            "marca": "Marca exemplo",
            "total": 1
          }
        ]
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "Com Tiny conectado, considera apenas produtos de fonte tiny.",
        "Marcas configuradas como ocultas não são devolvidas.",
        "Use o campo marca, não marca_id, no filtro de products.list/search."
      ],
      "group": "products",
      "groupName": "Catálogo"
    },
    {
      "method": "products.categories",
      "category": "Catálogo",
      "summary": "Listar categorias",
      "description": "Categorias ativas com produtos ativos, contagem por categoria e ordenação alfabética.",
      "params": [],
      "requestExample": {},
      "responseExample": {
        "categorias": [
          {
            "categoria_id": "33333333-3333-4333-8333-333333333333",
            "categoria": "Categoria exemplo",
            "total": 1
          }
        ]
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "Com Tiny conectado, considera apenas produtos de fonte tiny.",
        "Use o campo categoria, não categoria_id, no filtro de products.list/search."
      ],
      "group": "products",
      "groupName": "Catálogo"
    },
    {
      "method": "products.get",
      "category": "Catálogo",
      "summary": "Detalhar produto",
      "description": "Busca um SKU ativo da empresa e acrescenta descricao ao objeto de produto.",
      "params": [
        {
          "name": "codigo",
          "type": "string",
          "required": "um dos dois obrigatório",
          "description": "SKU exato. Informe codigo OU sku; codigo tem precedência quando ambos são preenchidos.",
          "example": "DEMO-01"
        },
        {
          "name": "sku",
          "type": "string",
          "required": "um dos dois obrigatório",
          "description": "Alternativa a codigo. Ao menos um dos dois deve ser informado.",
          "example": "DEMO-01"
        }
      ],
      "requestExample": {
        "codigo": "DEMO-01"
      },
      "responseExample": {
        "product": {
          "id": "11111111-1111-4111-8111-111111111111",
          "nome": "Produto de demonstração",
          "codigo": "DEMO-01",
          "idCatalogo": "100.000001",
          "marca": "Marca exemplo",
          "categoria": "Categoria exemplo",
          "imagemThumb": "https://assets.example.com/produto.png",
          "imagens": [
            "https://assets.example.com/produto.png"
          ],
          "imagensCount": 1,
          "specs": {
            "potencia": "10 W",
            "tensao": "220V"
          },
          "preco_venda": 25,
          "estoque": 12,
          "reservado": 2,
          "disponivel_qtd": 10,
          "disponivel": true,
          "motivo_indisponivel": null,
          "descricao": "Descrição ilustrativa do produto."
        }
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        },
        {
          "status": 400,
          "code": "BAD_REQUEST",
          "description": "codigo/sku não informado."
        },
        {
          "status": 404,
          "code": "NOT_FOUND",
          "description": "Produto ativo não encontrado na empresa."
        }
      ],
      "notes": [
        "Inclui os mesmos campos de estoque e disponibilidade da listagem mais descricao.",
        "Não aplica o filtro fonte=tiny usado na listagem; um SKU conhecido pode ser consultado sem aparecer na grade filtrada.",
        "descricao pode ser string vazia; não assuma HTML seguro para renderização."
      ],
      "group": "products",
      "groupName": "Catálogo"
    },
    {
      "method": "products.list",
      "category": "Catálogo",
      "summary": "Listar produtos",
      "description": "Catálogo ativo da empresa do token com filtros e paginação por deslocamento.",
      "params": [
        {
          "name": "q",
          "type": "string",
          "required": false,
          "description": "Busca tolerante por nome/SKU. Espaços ou * separam até 10 termos combinados com AND; cada termo e os campos comparados são normalizados para minúsculas e caracteres alfanuméricos, ignorando acentos, espaços e pontuação. Termos brutos formados apenas por dígitos e pontos também procuram idCatalogo sem pontos. products.search e products.list usam a mesma função.",
          "example": "produto"
        },
        {
          "name": "marca",
          "type": "string",
          "required": false,
          "description": "Nome exato da marca, não seu UUID.",
          "example": "Marca exemplo"
        },
        {
          "name": "categoria",
          "type": "string",
          "required": false,
          "description": "Nome exato da categoria, não seu UUID.",
          "example": "Categoria exemplo"
        },
        {
          "name": "familia",
          "type": "string",
          "required": false,
          "description": "Família exata do cadastro.",
          "example": "Linha exemplo"
        },
        {
          "name": "tag",
          "type": "string",
          "required": false,
          "description": "Texto contido nas tags de origem do cadastro.",
          "example": "erp"
        },
        {
          "name": "preco_min",
          "type": "number",
          "required": false,
          "description": "Preço mínimo, em reais; valor não numérico é ignorado.",
          "example": 10
        },
        {
          "name": "preco_max",
          "type": "number",
          "required": false,
          "description": "Preço máximo, em reais.",
          "example": 200
        },
        {
          "name": "order",
          "type": "string",
          "required": false,
          "description": "nome (padrão), preco_asc, preco_desc ou estoque. Valor desconhecido usa nome.",
          "example": "preco_asc"
        },
        {
          "name": "offset",
          "type": "integer",
          "required": false,
          "description": "Deslocamento a partir de zero. Passe aqui o next_cursor convertido em número.",
          "example": 0
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "description": "Recomendado de 1 a 60; padrão 24 e teto 60. Use valores positivos; números negativos podem retornar INTERNAL_ERROR.",
          "example": 24
        }
      ],
      "requestExample": {
        "limit": 24,
        "offset": 0
      },
      "responseExample": {
        "items": [
          {
            "id": "11111111-1111-4111-8111-111111111111",
            "nome": "Produto de demonstração",
            "codigo": "DEMO-01",
            "idCatalogo": "100.000001",
            "marca": "Marca exemplo",
            "categoria": "Categoria exemplo",
            "imagemThumb": "https://assets.example.com/produto.png",
            "imagens": [
              "https://assets.example.com/produto.png"
            ],
            "imagensCount": 1,
            "specs": {
              "potencia": "10 W",
              "tensao": "220V"
            },
            "preco_venda": 25,
            "estoque": 12,
            "reservado": 2,
            "disponivel_qtd": 10,
            "disponivel": true,
            "motivo_indisponivel": null
          }
        ],
        "total": 1,
        "next_cursor": null
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "disponivel é a decisão pronta de compra; estoque é o saldo físico, reservado é o saldo comprometido e disponivel_qtd desconta reservas. Valores de estoque e preço podem ser null.",
        "Indisponibilidade: sem_preco, sem_saldo ou esgotado. Produtos indisponíveis continuam na listagem dentro do recorte de fonte.",
        "Com Tiny conectado, listagem, marcas e categorias consideram fonte tiny. products.get consulta SKU ativo da própria empresa sem esse filtro de fonte.",
        "next_cursor é um deslocamento textual, não um cursor opaco: use como offset da próxima chamada até receber null.",
        "Use o escopo exato do método. Escopos amplos não fazem parte deste perfil público.",
        "O parâmetro herdado favoritos depende de usuário e não é utilizável nesta API por token.",
        "A busca q não consulta descrição, ficha técnica nem specs; cada termo precisa aparecer no nome, SKU ou, quando numérico, em idCatalogo."
      ],
      "group": "products",
      "groupName": "Catálogo"
    },
    {
      "method": "products.search",
      "category": "Catálogo",
      "summary": "Buscar produtos",
      "description": "Alias funcional de products.list. q é aceito mas não obrigatório na implementação.",
      "params": [
        {
          "name": "q",
          "type": "string",
          "required": false,
          "description": "Busca tolerante por nome/SKU. Espaços ou * separam até 10 termos combinados com AND; cada termo e os campos comparados são normalizados para minúsculas e caracteres alfanuméricos, ignorando acentos, espaços e pontuação. Termos brutos formados apenas por dígitos e pontos também procuram idCatalogo sem pontos. products.search e products.list usam a mesma função.",
          "example": "produto"
        },
        {
          "name": "marca",
          "type": "string",
          "required": false,
          "description": "Nome exato da marca, não seu UUID.",
          "example": "Marca exemplo"
        },
        {
          "name": "categoria",
          "type": "string",
          "required": false,
          "description": "Nome exato da categoria, não seu UUID.",
          "example": "Categoria exemplo"
        },
        {
          "name": "familia",
          "type": "string",
          "required": false,
          "description": "Família exata do cadastro.",
          "example": "Linha exemplo"
        },
        {
          "name": "tag",
          "type": "string",
          "required": false,
          "description": "Texto contido nas tags de origem do cadastro.",
          "example": "erp"
        },
        {
          "name": "preco_min",
          "type": "number",
          "required": false,
          "description": "Preço mínimo, em reais; valor não numérico é ignorado.",
          "example": 10
        },
        {
          "name": "preco_max",
          "type": "number",
          "required": false,
          "description": "Preço máximo, em reais.",
          "example": 200
        },
        {
          "name": "order",
          "type": "string",
          "required": false,
          "description": "nome (padrão), preco_asc, preco_desc ou estoque. Valor desconhecido usa nome.",
          "example": "preco_asc"
        },
        {
          "name": "offset",
          "type": "integer",
          "required": false,
          "description": "Deslocamento a partir de zero. Passe aqui o next_cursor convertido em número.",
          "example": 0
        },
        {
          "name": "limit",
          "type": "integer",
          "required": false,
          "description": "Recomendado de 1 a 60; padrão 24 e teto 60. Use valores positivos; números negativos podem retornar INTERNAL_ERROR.",
          "example": 24
        }
      ],
      "requestExample": {
        "q": "produto",
        "limit": 24
      },
      "responseExample": {
        "items": [
          {
            "id": "11111111-1111-4111-8111-111111111111",
            "nome": "Produto de demonstração",
            "codigo": "DEMO-01",
            "idCatalogo": "100.000001",
            "marca": "Marca exemplo",
            "categoria": "Categoria exemplo",
            "imagemThumb": "https://assets.example.com/produto.png",
            "imagens": [
              "https://assets.example.com/produto.png"
            ],
            "imagensCount": 1,
            "specs": {
              "potencia": "10 W",
              "tensao": "220V"
            },
            "preco_venda": 25,
            "estoque": 12,
            "reservado": 2,
            "disponivel_qtd": 10,
            "disponivel": true,
            "motivo_indisponivel": null
          }
        ],
        "total": 1,
        "next_cursor": null
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "disponivel é a decisão pronta de compra; estoque é o saldo físico, reservado é o saldo comprometido e disponivel_qtd desconta reservas. Valores de estoque e preço podem ser null.",
        "Indisponibilidade: sem_preco, sem_saldo ou esgotado. Produtos indisponíveis continuam na listagem dentro do recorte de fonte.",
        "Com Tiny conectado, listagem, marcas e categorias consideram fonte tiny. products.get consulta SKU ativo da própria empresa sem esse filtro de fonte.",
        "next_cursor é um deslocamento textual, não um cursor opaco: use como offset da próxima chamada até receber null.",
        "Use o escopo exato do método. Escopos amplos não fazem parte deste perfil público.",
        "O parâmetro herdado favoritos depende de usuário e não é utilizável nesta API por token.",
        "A busca q não consulta descrição, ficha técnica nem specs; cada termo precisa aparecer no nome, SKU ou, quando numérico, em idCatalogo."
      ],
      "group": "products",
      "groupName": "Catálogo"
    },
    {
      "method": "shop.banners.list",
      "category": "Shop",
      "summary": "Listar banners e carrossel",
      "description": "Banners ativos dentro da janela de exibição, em ordem de prioridade e criação; inclui configuração do carrossel.",
      "params": [
        {
          "name": "slot",
          "type": "string",
          "required": false,
          "description": "Posição exata do banner. Sem slot, retorna todas as posições.",
          "example": "home"
        }
      ],
      "requestExample": {
        "slot": "home"
      },
      "responseExample": {
        "banners": [
          {
            "id": "44444444-4444-4444-8444-444444444444",
            "slot": "home",
            "titulo": "Banner de demonstração",
            "imagem_url": "https://assets.example.com/banner.png",
            "link_url": "https://loja.example.com/catalogo",
            "ordem": 0
          }
        ],
        "carrossel": {
          "efeito": "slide",
          "intervalo_ms": 5000,
          "transicao_ms": 600,
          "autoplay": true,
          "laco": true,
          "mostrar_setas": true,
          "mostrar_pontos": true,
          "pausar_no_hover": true
        }
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "carrossel pode ser null quando ausente, inválido ou indisponível. O consumidor deve ter fallback.",
        "Configuração administrativa admite efeitos slide, fade, zoom, cover e none; intervalo de 1000 a 30000 ms e transição de 0 a 3000 ms.",
        "Caminhos de imagem relativos são prefixados pela base pública configurada no servidor."
      ],
      "group": "shop",
      "groupName": "Shop"
    },
    {
      "method": "shop.desconto.validar",
      "category": "Shop",
      "summary": "Validar cupom e descontos automáticos",
      "description": "Calcula descontos com os preços atuais do catálogo. Retorna descontos aplicáveis e eventual recusa do código informado.",
      "params": [
        {
          "name": "codigo",
          "type": "string",
          "required": false,
          "description": "Cupom informado. Normaliza para maiúsculas e remove espaços. Sem código, calcula automáticos.",
          "example": "DEMO10"
        },
        {
          "name": "itens",
          "type": "array<object> | string JSON",
          "required": true,
          "description": "Lista de itens. Aceita array JSON ou string JSON. Preço enviado pelo cliente é ignorado.",
          "example": [
            {
              "sku": "DEMO-01",
              "qtd": 2
            }
          ]
        },
        {
          "name": "itens[].sku",
          "type": "string",
          "required": "um dos dois obrigatório",
          "description": "SKU do produto. Em cada item informado, envie sku OU codigo; sku tem precedência quando ambos são preenchidos.",
          "example": "DEMO-01"
        },
        {
          "name": "itens[].codigo",
          "type": "string",
          "required": "um dos dois obrigatório",
          "description": "Alternativa a itens[].sku. Em cada item informado, é necessário identificar o produto por sku OU codigo.",
          "example": "DEMO-01"
        },
        {
          "name": "itens[].qtd",
          "type": "integer",
          "required": false,
          "description": "Quantidade; quantidade é alias; mínimo efetivo 1.",
          "example": 2
        },
        {
          "name": "frete_cents",
          "type": "integer",
          "required": false,
          "description": "Cotação de frete em centavos, usada somente para estimar o desconto; o valor final deve ser recalculado no fluxo comercial autorizado.",
          "example": 900
        },
        {
          "name": "cliente",
          "type": "object",
          "required": false,
          "description": "CPF/cpf_cnpj ou email para restrições de uso por comprador. Envie objeto JSON, não string.",
          "example": {
            "email": "comprador@example.com"
          }
        }
      ],
      "requestExample": {
        "codigo": "DEMO10",
        "itens": [
          {
            "sku": "DEMO-01",
            "qtd": 2
          }
        ],
        "frete_cents": 900,
        "cliente": {
          "email": "comprador@example.com"
        }
      },
      "responseExample": {
        "descontos": [
          {
            "id": "66666666-6666-4666-8666-666666666666",
            "tipo": "pedido",
            "metodo": "codigo",
            "codigo": "DEMO10",
            "nome": "Desconto de demonstração",
            "valor_cents": 500,
            "valor": 5,
            "skus": [],
            "frete_gratis": false,
            "combina": {
              "produto": false,
              "pedido": false,
              "frete": false
            }
          }
        ],
        "valor_cents": 500,
        "frete_gratis": false,
        "frete_desconto_cents": 0,
        "valor": 5,
        "recusa": null
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "Tipos: produtos, compre_leve, pedido e frete. Esta consulta não registra o uso do cupom.",
        "valor_cents e valor representam desconto nos produtos; frete_desconto_cents é separado. Não some frete grátis ao desconto de produtos duas vezes.",
        "recusa, quando presente, contém codigo, motivo, min_valor_cents, min_itens e texto; é retorno de negócio HTTP 200.",
        "Motivos: nao_encontrado, inativo, ainda_nao_comecou, expirado, esgotado, ja_usado, exige_identificacao, minimo_valor, minimo_itens, sem_itens_no_alvo, combo_nao_atingido, sem_frete, frete_acima_do_teto e tipo_desconhecido.",
        "Item não encontrado ou sem preço positivo é ignorado nesta estimativa; a validação não garante disponibilidade do carrinho.",
        "Pode haver descontos automáticos mesmo quando o cupom explícito é recusado. Um fluxo comercial posterior deve revalidar o resultado."
      ],
      "group": "shop",
      "groupName": "Shop"
    },
    {
      "method": "shop.frete.calcular",
      "category": "Shop",
      "summary": "Calcular opções de frete",
      "description": "Calcula tarifas compatíveis com o carrinho e destino, combinando perfis quando necessário.",
      "params": [
        {
          "name": "cep",
          "type": "string",
          "required": true,
          "description": "CEP de destino; pontuação é normalizada. Envie 8 dígitos.",
          "example": "01001000"
        },
        {
          "name": "itens",
          "type": "array<object> | string JSON",
          "required": true,
          "description": "Lista de SKU e quantidade. Este método aceita array JSON ou string JSON; string inválida vira lista vazia.",
          "example": [
            {
              "sku": "DEMO-01",
              "qtd": 2
            }
          ]
        },
        {
          "name": "itens[].sku",
          "type": "string",
          "required": "um dos dois obrigatório",
          "description": "SKU do produto. Em cada item informado, envie sku OU codigo; sku tem precedência quando ambos são preenchidos.",
          "example": "DEMO-01"
        },
        {
          "name": "itens[].codigo",
          "type": "string",
          "required": "um dos dois obrigatório",
          "description": "Alternativa a itens[].sku. Em cada item informado, é necessário identificar o produto por sku OU codigo.",
          "example": "DEMO-01"
        },
        {
          "name": "itens[].qtd",
          "type": "integer",
          "required": false,
          "description": "Quantidade; quantidade é alias; valores são arredondados para baixo e limitados ao mínimo 1.",
          "example": 2
        }
      ],
      "requestExample": {
        "cep": "01001000",
        "itens": [
          {
            "sku": "DEMO-01",
            "qtd": 2
          }
        ]
      },
      "responseExample": {
        "cep": "01001000",
        "uf": "SP",
        "opcoes": [
          {
            "opcao_ids": [
              "55555555-5555-4555-8555-555555555555"
            ],
            "nome": "Entrega padrão",
            "valor_cents": 900,
            "prazo_min_dias": 2,
            "prazo_max_dias": 4,
            "id": "55555555-5555-4555-8555-555555555555",
            "valor": 9,
            "entrega_estimada": null
          }
        ],
        "retirada": null,
        "entrega_local": null,
        "origem": {
          "cep": "01001000",
          "uf": "SP"
        },
        "motivo": null,
        "itens_sem_frete": [],
        "peso_incompleto": false
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "Respostas sem cotação usam HTTP 200 e motivo cep_invalido, sem_itens, nao_configurado ou sem_cobertura. Não são falhas HTTP.",
        "Use todos os opcao_ids para identificar a composição da opção calculada; id identifica somente a linha.",
        "valor_cents é inteiro em centavos; valor é reais. Valor zero significa frete grátis.",
        "entrega_estimada é null ou {de, ate, processamento_dias}; o cálculo considera dias úteis e processamento configurado.",
        "entrega_local pode ser {ativo:true,elegivel:false} ou elegível com nome, valor_cents, valor, minimo_pedido_cents e instrucoes; zonas por raio podem acrescentar distancia, raio e unidade.",
        "entrega_local pode coexistir com motivo sem_cobertura. Sua presença não garante elegibilidade em um fluxo comercial posterior.",
        "peso_incompleto indica produtos cujo peso foi tratado como zero. O cálculo não é prova de disponibilidade/estoque.",
        "Uma falta de cobertura em qualquer perfil impede cotação parcial do carrinho.",
        "O cálculo por raio pode consultar um serviço de geocodificação e manter um cache técnico do CEP. Ele não cria nem altera pedidos, tarifas ou outras regras comerciais."
      ],
      "group": "shop",
      "groupName": "Shop"
    },
    {
      "method": "shop.frete.config",
      "category": "Shop",
      "summary": "Ler opções gerais de entrega",
      "description": "Resumo para mostrar retirada e entrega local antes do CEP. Zonas e tarifas detalhadas não são expostas.",
      "params": [],
      "requestExample": {},
      "responseExample": {
        "retirada": {
          "ativo": true,
          "prazo": "24h",
          "prazo_label": "Normalmente pronto em 24 horas",
          "mensagem": "Aguarde a confirmação.",
          "instrucoes": "Retirada no balcão."
        },
        "entrega_local": {
          "ativo": true,
          "a_partir_de_cents": 900,
          "a_partir_de": 9,
          "zonas": 2
        },
        "datas_estimadas": true,
        "origem": {
          "cep": "01001000",
          "uf": "SP"
        }
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "retirada e entrega_local podem ser null.",
        "a_partir_de é o menor preço cadastrado, não uma cotação para o cliente.",
        "A filial pode herdar regras da matriz; a origem é resolvida para a filial."
      ],
      "group": "shop",
      "groupName": "Shop"
    },
    {
      "method": "shop.loja.config",
      "category": "Shop",
      "summary": "Ler identidade e aparência da loja",
      "description": "Configuração pública de marca, contatos, políticas, avisos, rodapé, formas de pagamento anunciadas e aparência.",
      "params": [],
      "requestExample": {},
      "responseExample": {
        "nome": "Loja de demonstração",
        "logo_url": "https://assets.example.com/logo.png",
        "logo_quadrada_url": "https://assets.example.com/logo-square.png",
        "descricao": "Descrição ilustrativa.",
        "slogan": null,
        "cores": {
          "principal": "#2684ff",
          "texto": "#0f1621"
        },
        "contato": {
          "whatsapp": null,
          "email": "loja@example.com",
          "endereco": null,
          "telefone": null,
          "cnpj": null
        },
        "busca_placeholder": null,
        "rodape": {
          "colunas": null
        },
        "topbar": {
          "avisos": [],
          "frete_gratis_acima": null,
          "desconto_pix": null,
          "atacado_url": null,
          "atendimento": null
        },
        "pagamentos": [
          "pix"
        ],
        "politicas": {
          "troca": null,
          "privacidade": null,
          "entrega": null
        },
        "aparencia": {
          "cores": {
            "fundo": null,
            "superficie": null,
            "botao": null,
            "botao_texto": null
          },
          "fonte": null,
          "banner": {
            "ativo": false,
            "titulo": null,
            "subtitulo": null,
            "imagem_url": null,
            "cta_texto": null,
            "cta_url": null
          },
          "destaques": {
            "ativo": false,
            "titulo": null,
            "skus": []
          }
        },
        "completa": true
      },
      "errors": [
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "Campos não configurados podem ser null, arrays vazios ou blocos com defaults. completa exige nome e logo própria da loja: a implementação atual não considera a logo herdada da empresa nesse indicador.",
        "Nome e logo podem usar fallback da empresa. URLs de logo devem ser HTTP(S) absolutas.",
        "topbar.avisos é lista resolvida de {texto,destaque?,url?}. rodape.colunas é null ou lista de {titulo,links:[{rotulo,url?}]}. Lista vazia é escolha explícita de não mostrar colunas.",
        "pagamentos descreve meios anunciados: pix, visa, mastercard, elo, amex, hipercard e boleto. Não é consulta da capacidade efetiva do gateway.",
        "Aparência inclui fonte inter, poppins, roboto, lato, playfair ou system (ou null), banner e até 24 SKUs de destaque.",
        "Políticas são conteúdo textual cadastrado pela loja; renderize como texto seguro."
      ],
      "group": "shop",
      "groupName": "Shop"
    },
    {
      "method": "marketing.funnel",
      "category": "Marketing",
      "summary": "Consultar funil de marketing",
      "description": "Agrega leads de mídia paga, oportunidades e vendas por dia em um funil, incluindo dias sem atividade e fotografia atual de oportunidades paradas.",
      "params": [
        {
          "name": "from",
          "type": "string (YYYY-MM-DD)",
          "required": true,
          "description": "Data inicial inclusiva.",
          "example": "2026-09-18"
        },
        {
          "name": "to",
          "type": "string (YYYY-MM-DD)",
          "required": true,
          "description": "Data final inclusiva. Intervalo de 1 a 92 dias.",
          "example": "2026-09-18"
        },
        {
          "name": "pipeline_id",
          "type": "integer",
          "required": true,
          "description": "ID positivo do funil acessível à empresa.",
          "example": 1
        }
      ],
      "requestExample": {
        "from": "2026-09-18",
        "to": "2026-09-18",
        "pipeline_id": 1
      },
      "responseExample": {
        "company_id": "44444444-4444-4444-8444-444444444444",
        "from": "2026-09-18",
        "to": "2026-09-18",
        "generated_at": "2026-09-18T15:00:00.000Z",
        "days": [
          {
            "date": "2026-09-18",
            "leads": {
              "total": 0,
              "google": 0,
              "meta": 0,
              "other": 0,
              "junk": 0,
              "junk_by_reason": []
            },
            "opportunities": {
              "created": 0,
              "value": 0,
              "by_channel": [],
              "by_pipeline": []
            },
            "sales": {
              "won": 0,
              "value": 0,
              "by_channel": [],
              "by_pipeline": [],
              "lost": 0,
              "lost_by_reason": []
            }
          }
        ],
        "stalled": {
          "snapshot_date": "2026-09-18",
          "buckets": [
            {
              "label": "Mais de 15 dias",
              "count": 0,
              "value": 0
            },
            {
              "label": "11 a 15 dias",
              "count": 0,
              "value": 0
            },
            {
              "label": "8 a 10 dias",
              "count": 0,
              "value": 0
            },
            {
              "label": "4 a 7 dias",
              "count": 0,
              "value": 0
            },
            {
              "label": "Até 3 dias",
              "count": 0,
              "value": 0
            }
          ]
        },
        "pipelines": [
          {
            "id": 1,
            "name": "Funil de exemplo"
          }
        ]
      },
      "errors": [
        {
          "status": 400,
          "code": "INVALID_DATE_RANGE",
          "description": "Datas ausentes/inválidas ou intervalo fora de 1 a 92 dias."
        },
        {
          "status": 400,
          "code": "PIPELINE_ID_REQUIRED",
          "description": "pipeline_id ausente ou não inteiro positivo."
        },
        {
          "status": 400,
          "code": "PIPELINE_NOT_FOUND",
          "description": "Funil não encontrado para a empresa."
        },
        {
          "status": 403,
          "code": "TOKEN_NO_COMPANY",
          "description": "Token sem empresa associada."
        }
      ],
      "notes": [
        "Leads são contatos criados no período com sinais de mídia paga no rastreio ou nas classificações configuradas; não equivalem a todos os leads cadastrados no CRM.",
        "Oportunidades/vendas/perdas consideram negócios ligados à coorte de contatos do período e ao pipeline_id; descartes contam a data de junk e podem envolver contatos criados antes do período.",
        "stalled é uma fotografia atual de todos os negócios em processo no funil, não um histórico filtrado por from/to.",
        "by_pipeline pode incluir uma segmentação adicional de tipo de orçamento; by_channel pode conter mais de uma entrada com o mesmo label e exigir soma no consumidor.",
        "As datas da consulta usam o fuso configurado na instância; generated_at e snapshot_date são produzidos em UTC. Não é cálculo de ROAS e não retorna gasto de mídia.",
        "Resposta ilustrativa do campo result; IDs, nomes e valores são fictícios. Campos adicionais podem existir."
      ],
      "group": "marketing",
      "groupName": "Marketing"
    }
  ]
}
