Documentação da API Paylog Documentação da API Paylog API pública v1
API v1

Produtos

Consulte, cadastre e atualize os produtos do produtor autenticado.

Nesta página 21

A API v1 de produtos consulta o catálogo do produtor autenticado e permite cadastrar e atualizar produtos com nome, tipo, peso unitário e dimensões.

Atenção

Nem todo verbo existe. GET, POST e PATCH estão disponíveis. PUT e DELETE em /api/v1/produtos ou /api/v1/produtos/{id} retornam sempre 405 Method Not Allowed, antes da autenticação, e não há rota para excluir produto nem para ajustar estoque pela API:

json
{
  "errors": "The PUT method is not supported for route api/v1/produtos/489. Supported methods: GET, HEAD, PATCH.",
  "code": 405
}

Endpoints disponíveis

Método Endpoint Permissão do token Resultado
GET /api/v1/produtos listar_produtos_api Lista paginada, até 500 produtos por página
GET /api/v1/produtos/{id} listar_produtos_api Um produto
POST /api/v1/produtos criar_produtos_api Cadastra um produto pendente de aprovação
PATCH /api/v1/produtos/{id} criar_produtos_api Atualiza os campos enviados de um produto
Importante

listar_produtos_api não autoriza escrita. As duas rotas de leitura exigem listar_produtos_api; POST e PATCH exigem criar_produtos_api, uma permissão separada. Um token que só possui a permissão de leitura recebe 403 ao tentar cadastrar ou atualizar.

Importante

Escopo por produtor efetivo. Todas as rotas filtram por produtos.user_id = <id do produtor>. Igual a Clientes: quando o token pertence a uma subconta (funcionário vinculado a um produtor), a API sobe para o produtor pai e retorna os produtos dele, não apenas os cadastrados sob a subconta.

Atenção

POST e PATCH exigem uma conta de produtor ativa. Além da permissão criar_produtos_api, o token precisa pertencer a uma conta com status ativo e papel de produtor. Um token de subconta de funcionário — que consegue ler o catálogo do produtor pai — recebe 403 com { "message": "A conta autenticada não está autorizada a cadastrar produtos." } ao tentar escrever.

Listar produtos

GET

bash
curl --request GET \
  --url 'https://ev.paylog.cash/api/v1/produtos?status=1&page=1' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer SEU_TOKEN'

Parâmetros de consulta

Campo Tipo Obrigatório Comportamento atual
page inteiro Não Página solicitada. Quando omitido, usa 1.
status inteiro Não Filtra pelo código exato: 0 pendente, 1 aprovado ou 2 desabilitado. Quando omitido, usa 1.
data_inicio data Não Inclui produtos com created_at a partir da data. Recomenda-se YYYY-MM-DD.
data_fim data Não Inclui produtos com created_at até o fim da data. Recomenda-se YYYY-MM-DD.
Observação

Os códigos de status estão em Status de pacotes e produtos. data_inicio e data_fim podem ser usados separadamente ou em conjunto; o primeiro considera o início do dia e o segundo, o fim do dia.

Atenção

status é convertido para inteiro antes de filtrar. Qualquer valor não numérico — inclusive ?status= vazio ou ?status=aprovado — vira 0 e a resposta traz apenas produtos pendentes, sem erro de validação. Envie só 0, 1 ou 2, ou omita o parâmetro para receber o padrão 1 (aprovado).

Como um produto recém-cadastrado nasce pendente (status = 0), ele não aparece na listagem padrão. Use ?status=0 para acompanhar a fila de aprovação.

Resposta 200

json
{
  "current_page": 1,
  "data": [
    {
      "id": 489,
      "nome": "Produto Exemplo API",
      "status": 1,
      "estoque": 120
    }
  ],
  "first_page_url": "https://ev.paylog.cash/api/v1/produtos?page=1",
  "from": 1,
  "last_page": 1,
  "last_page_url": "https://ev.paylog.cash/api/v1/produtos?page=1",
  "links": [
    {
      "url": null,
      "label": "&laquo; Anterior",
      "page": null,
      "active": false
    },
    {
      "url": "https://ev.paylog.cash/api/v1/produtos?page=1",
      "label": "1",
      "page": 1,
      "active": true
    },
    {
      "url": null,
      "label": "Próxima &raquo;",
      "page": null,
      "active": false
    }
  ],
  "next_page_url": null,
  "path": "https://ev.paylog.cash/api/v1/produtos",
  "per_page": 500,
  "prev_page_url": null,
  "to": 1,
  "total": 1
}

Campos de data[]

Campo Tipo Sempre retornado Descrição
id inteiro Sim ID numérico do produto.
nome string Sim Nome do produto.
status inteiro Sim Código de status do produto.
estoque inteiro Sim Saldo de estoque atual. Pode ser 0.
Importante

O nome correto do campo de saldo é estoque, tanto na listagem quanto na consulta individual. A API não retorna quantidade para produtos — quantidade só existe dentro da composição de um pacote, onde representa quantas unidades daquele produto o kit contém. Veja Pacotes.

Também não existe campo de preço, peso, dimensões ou SKU nesta resposta: o payload de produto tem exatamente quatro chaves (id, nome, status, estoque). Peso, dimensões e codigo_plataforma aparecem apenas nas respostas de POST e PATCH.

Metadados da paginação

Campo Tipo Sempre retornado Descrição
current_page inteiro Sim Página atual.
data array Sim Produtos da página; pode ser [].
first_page_url string Sim URL da primeira página.
from inteiro ou null Sim Posição do primeiro item; null quando vazio.
last_page inteiro Sim Última página disponível.
last_page_url string Sim URL da última página.
links array Sim Links navegáveis da paginação.
links[].url string ou null Sim URL do link; null quando indisponível.
links[].label string Sim Rótulo HTML do link.
links[].page inteiro ou null Sim Página do link.
links[].active booleano Sim Indica a página atual.
next_page_url string ou null Sim Próxima página, quando existir.
path string Sim URL base da coleção.
per_page inteiro Sim Limite fixo de 500 itens por página.
prev_page_url string ou null Sim Página anterior, quando existir.
to inteiro ou null Sim Posição do último item; null quando vazio.
total inteiro Sim Total de produtos encontrados.

Consultar um produto

GET

bash
curl --request GET \
  --url 'https://ev.paylog.cash/api/v1/produtos/489' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer SEU_TOKEN'

Parâmetro de rota

Campo Tipo Obrigatório Descrição
id inteiro Sim ID de um produto pertencente ao produtor autenticado.

Resposta 200

json
{
  "id": 489,
  "nome": "Produto Exemplo API",
  "status": 1,
  "estoque": 120
}
Campo Tipo Sempre retornado Descrição
id inteiro Sim ID numérico.
nome string Sim Nome do produto.
status inteiro Sim Código de status.
estoque inteiro Sim Saldo atual.

Produto ausente ou de outra conta

A implementação atual responde com 204 No Content nos dois casos. Não há corpo JSON e a resposta não revela se o ID existe em outra conta.

Cadastrar um produto

POST

http
POST /api/v1/produtos

Cria um produto vinculado ao produtor autenticado. O produto nasce pendente (status = 0) e entra na fila de aprovação da Paylog, exatamente como um cadastro feito pelo painel.

Importante

A configuração fiscal e a aprovação são feitas pela Paylog, por decisão de projeto. O corpo da requisição não aceita tipo_emissao, notazz_product_code, emite_nota_fiscal nem nicho_id: a Paylog configura o emissor e o enquadramento fiscal no momento da aprovação. É justamente isso que destrava a emissão de NF-e para os pedidos do produtor sem que a sua integração precise conhecer regras fiscais.

Atenção

peso_unitario é em QUILOGRAMAS, por unidade — e o teto é 30 kg. Um valor acima de 30 é recusado com 422. Enviar o peso em gramas é o erro mais comum: um item de 250 g é 0.25, nunca 250.

A API recusa e nunca converte automaticamente. Não há heurística de divisão por 1000, porque ela sub-declararia por 1000× encomendas genuinamente pesadas. Um peso implausível cadastrado no produto contamina toda a operação: acima do teto os Correios simplesmente não devolvem a cotação de frete e o pedido fica travado em Correção com a mensagem enganosa Sem resposta da API — sem indicar o peso como causa.

bash
curl --request POST \
  --url 'https://ev.paylog.cash/api/v1/produtos' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer SEU_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "nome": "Erec Prime Frasco",
    "codigo_plataforma": "PRD8H2K9L",
    "tipo_produto": 1,
    "peso_unitario": 0.12,
    "comprimento": 12.5,
    "largura": 6,
    "altura": 6
  }'

Campos da requisição

Campo Tipo Presença Regra
nome string Obrigatório Nome do produto; até 255 caracteres.
codigo_plataforma string Obrigatório O SKU do produto; até 255 caracteres. Único por produtor — veja Reenvio do mesmo SKU.
tipo_produto integer Obrigatório Um dos códigos da tabela de tipos.
peso_unitario number Obrigatório Peso de uma unidade em quilogramas, de 0.001 a 30.
comprimento number Obrigatório Comprimento da embalagem em centímetros, de 0.1 a 200.
largura number Obrigatório Largura da embalagem em centímetros, de 0.1 a 200.
altura number Obrigatório Altura da embalagem em centímetros, de 0.1 a 200.
gtin string Opcional GTIN; até 20 caracteres. Aceita null.
ean string Opcional EAN; até 20 caracteres. Aceita null.
product_barcode string Opcional Código de barras usado na sua operação; até 255 caracteres. Aceita null.
site_oficial string Opcional URL válida da página do produto; até 255 caracteres. Aceita null.
Atenção

O corpo não aceita nenhuma outra chave — nada é ignorado em silêncio. Estas chaves são recusadas com 422, mesmo que o valor enviado esteja correto:

Chave recusada Por quê
status A aprovação é da Paylog. Todo produto nasce 0 (Pendente).
user_id O produtor vem sempre do token, nunca do corpo.
tipo_emissao Configuração fiscal definida pela Paylog na aprovação.
notazz_product_code Configuração fiscal definida pela Paylog.
emite_nota_fiscal Configuração fiscal definida pela Paylog.
nicho_id Classificação interna definida pela Paylog.
estoque Não há ajuste de estoque pela API; o produto é criado com 0.

A recusa é intencional: preferimos que a sua integração descubra na primeira chamada que o campo não é dela a deixá-la acreditar que gravou um valor fiscal que nunca chegou ao banco.

Tipos de produto

Código Tipo
1 Encapsulado
2 Cosmético
3 Roupa
5 Livro
6 Acessórios
7 Chá
8 Líquido
9 Outros
10 Goma
11 Brindes
12 Suplemento em Pó
Observação

A sequência não é contínua: o código 4 não existe. Envie exatamente um dos códigos da tabela; qualquer outro valor retorna 422 em tipo_produto.

Valores definidos pelo servidor

Campo Valor na criação
user_id Produtor efetivo do token.
status 0 (Pendente), até a aprovação da Paylog.
estoque 0.
tipo_emissao Permanece nulo até a Paylog aprovar o produto e configurar a emissão fiscal.

Resposta 201

json
{
  "code": 201,
  "message": "Produto criado com sucesso",
  "produto": {
    "id": 489,
    "nome": "Erec Prime Frasco",
    "codigo_plataforma": "PRD8H2K9L",
    "tipo_produto": 1,
    "peso_unitario": 0.12,
    "comprimento": 12.5,
    "largura": 6,
    "altura": 6,
    "gtin": null,
    "ean": null,
    "product_barcode": null,
    "site_oficial": null,
    "status": 0,
    "status_label": "Pendente",
    "created_at": "2026-08-07T14:03:11+00:00"
  }
}

Reenvio do mesmo SKU

codigo_plataforma é único por produtor, e a criação é idempotente: reenviar o mesmo SKU não duplica nem sobrescreve nada.

Situação Status Corpo
SKU ainda não cadastrado 201 message: "Produto criado com sucesso"
SKU já cadastrado nesta conta 200 message: "Produto já cadastrado para este código de plataforma"
json
{
  "code": 200,
  "message": "Produto já cadastrado para este código de plataforma",
  "produto": {
    "id": 489,
    "nome": "Erec Prime Frasco",
    "codigo_plataforma": "PRD8H2K9L",
    "tipo_produto": 1,
    "peso_unitario": 0.12,
    "comprimento": 12.5,
    "largura": 6,
    "altura": 6,
    "gtin": null,
    "ean": null,
    "product_barcode": null,
    "site_oficial": null,
    "status": 0,
    "status_label": "Pendente",
    "created_at": "2026-08-07T14:03:11+00:00"
  }
}
Importante

O 200 devolve o produto inalterado. Se o corpo reenviado trouxer um peso, uma dimensão ou um nome diferente do que está gravado, esses valores são descartados — nenhuma alteração silenciosa é aplicada. Para editar um produto existente, use PATCH /api/v1/produtos/{id}. Trate 201 e 200 como sucesso e leia o produto.id retornado nos dois casos.

Atualizar um produto

PATCH

http
PATCH /api/v1/produtos/{id}

Atualiza somente os campos enviados de um produto do produtor autenticado.

bash
curl --request PATCH \
  --url 'https://ev.paylog.cash/api/v1/produtos/489' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer SEU_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "peso_unitario": 0.25,
    "altura": 7
  }'

Parâmetro de rota

Campo Tipo Obrigatório Descrição
id inteiro Sim ID de um produto pertencente ao produtor autenticado.

Campos da requisição

Os campos são os mesmos de Cadastrar um produto, com as mesmas regras de validação, e todos são opcionais: nome, tipo_produto, peso_unitario, comprimento, largura, altura, gtin, ean, product_barcode e site_oficial.

Regra Comportamento
Ao menos um campo enviado Um corpo vazio ({}) retorna 422 na chave produto.
Campo omitido Permanece com o valor atual; não é apagado.
Campo enviado Precisa satisfazer a mesma regra do cadastro — inclusive o teto de 30 kg.
Atenção

codigo_plataforma é imutável aqui. Ele identifica o produto nas integrações e no mapeamento de SKU, então PATCH recusa a chave com 422 em vez de reescrevê-la. Também são recusados status, user_id e as chaves fiscais (tipo_emissao, notazz_product_code, emite_nota_fiscal, nicho_id) e estoque — os mesmos motivos descritos no cadastro.

Observação

Corrigir peso e dimensões de um produto já aprovado é permitido. A edição não depende do status: um produtor que cadastrou 250 g como 250 e só percebeu depois da aprovação corrige com um PATCH, e os pesos derivados passam a usar o valor corrigido nos próximos cálculos de frete. O status continua sendo alterado apenas pela Paylog.

Resposta 200

json
{
  "code": 200,
  "message": "Produto atualizado com sucesso",
  "produto": {
    "id": 489,
    "nome": "Erec Prime Frasco",
    "codigo_plataforma": "PRD8H2K9L",
    "tipo_produto": 1,
    "peso_unitario": 0.25,
    "comprimento": 12.5,
    "largura": 6,
    "altura": 7,
    "gtin": null,
    "ean": null,
    "product_barcode": null,
    "site_oficial": null,
    "status": 0,
    "status_label": "Pendente",
    "created_at": "2026-08-07T14:03:11+00:00"
  }
}

Produto de outro produtor

Um id inexistente e um id pertencente a outro produtor recebem exatamente a mesma resposta 404, sem revelar que o produto existe em outra conta:

json
{
  "message": "Produto não encontrado."
}
Importante

Atenção à assimetria entre os verbos do mesmo recurso: GET /api/v1/produtos/{id} responde 204 No Content para produto inexistente ou de outra conta, enquanto PATCH /api/v1/produtos/{id} responde 404 com corpo JSON. Trate os dois como "não encontrado".

O objeto produto de POST e PATCH

As duas rotas de escrita devolvem o mesmo objeto.

Campo Tipo Sempre retornado Descrição
id inteiro Sim ID interno do produto. Guarde-o para as chamadas seguintes.
nome string Sim Nome do produto.
codigo_plataforma string Sim O SKU gravado.
tipo_produto inteiro Sim Código do tipo do produto.
peso_unitario número Sim Peso de uma unidade, em quilogramas.
comprimento número Sim Comprimento em centímetros.
largura número Sim Largura em centímetros.
altura número Sim Altura em centímetros.
gtin string ou null Sim GTIN, quando informado.
ean string ou null Sim EAN, quando informado.
product_barcode string ou null Sim Código de barras, quando informado.
site_oficial string ou null Sim URL da página do produto, quando informada.
status inteiro Sim 0 pendente, 1 aprovado ou 2 desabilitado.
status_label string Sim Rótulo do status: Pendente, Aprovado ou Desabilitado.
created_at string Sim Data e hora da criação, em ISO 8601.
Observação

O objeto não traz estoque, campos fiscais nem preço. O saldo de estoque continua disponível em GET /api/v1/produtos.

Erros

Status Corpo atual Quando ocorre
204 Sem conteúdo Produto inexistente ou de outro produtor, em GET /produtos/{id}.
401 { "message": "Unauthenticated." } Token ausente ou inválido.
403 { "errors": "User does not have the right permissions.", "code": 403 } Token sem a permissão da rota: listar_produtos_api nos GET, criar_produtos_api no POST e no PATCH.
403 { "message": "A conta autenticada não está autorizada a cadastrar produtos." } Token válido e com a permissão, mas a conta não é um produtor ativo. Só em POST e PATCH.
404 { "message": "Produto não encontrado." } PATCH /produtos/{id} de um produto inexistente ou de outro produtor.
405 { "errors": "The PUT method is not supported for route api/v1/produtos/489. Supported methods: GET, HEAD, PATCH.", "code": 405 } PUT ou DELETE. Ocorre antes da autenticação.
422 { "message": "Os dados fornecidos são inválidos.", "errors": { "campo": ["mensagem"] } } Campo obrigatório ausente, valor fora das faixas, tipo inexistente, chave recusada ou corpo vazio no PATCH.
500 { "message": "Não foi possível cadastrar o produto." } · { "message": "Não foi possível atualizar o produto." } Falha inesperada em POST e PATCH, respectivamente.
500 Texto Algo deu errado! (não é JSON) Falha capturada pelos GET legados — tipicamente data_inicio ou data_fim que o interpretador de datas não consegue converter.

Exemplo de 422 ao enviar o peso em gramas e uma chave fiscal:

json
{
  "message": "Os dados fornecidos são inválidos.",
  "errors": {
    "peso_unitario": [
      "O peso unitário deve ser informado em quilogramas e não pode exceder 30 kg."
    ],
    "tipo_emissao": [
      "A configuração fiscal é definida pelo Paylog e não pode ser enviada."
    ]
  }
}

Exemplo de 422 em PATCH sem nenhum campo atualizável — o erro vem na chave produto, não em um campo. Enviar apenas campos imutáveis produz o erro do próprio campo recusado (abaixo), não este:

json
{
  "message": "Os dados fornecidos são inválidos.",
  "errors": {
    "produto": [
      "Informe ao menos um campo para atualizar."
    ]
  }
}

Ao tentar alterar o SKU:

json
{
  "message": "Os dados fornecidos são inválidos.",
  "errors": {
    "codigo_plataforma": [
      "O código de plataforma não pode ser alterado após o cadastro."
    ]
  }
}
Atenção

204 não é um erro para a maioria dos clientes HTTP. GET /api/v1/produtos/{id} de um produto inexistente ou de outra conta responde 204 No Content, e não 404. Bibliotecas que só tratam 4xx como falha vão considerar a chamada bem-sucedida e receber um corpo vazio. Verifique explicitamente status === 204 antes de desserializar.

Importante

Os envelopes de erro não são uniformes neste recurso. O 500 dos GET devolve texto puro (Algo deu errado!); os 403 e 405 do tratador global usam as chaves errors (string) e code; POST e PATCH usam message (e errors como objeto por campo no 422). Trate cada status pelo código HTTP, nunca pelo formato do corpo.

Atualizado em 07/08/2026