Importar um arquivo
Cria ou atualiza produtos a partir de um arquivo CSV ou XLSX em uma única chamada, e baixa o modelo CSV com as colunas esperadas.
Use esta rota quando você tem uma planilha (de um ERP, de um fornecedor ou de uma migração) e quer carregá-la em uma requisição. Cada linha vira um produto: se já existe um produto com o mesmo SKU ele é atualizado, senão é criado. A chamada é síncrona: responde quando o arquivo foi processado, com as contagens e os problemas linha a linha.
Para arquivos grandes, para mapear colunas com nomes diferentes dos nossos, ou para pré-visualizar antes de gravar, use o Assistente de importação. Os dois leem os mesmos formatos de arquivo.
Baixar o modelo
/api/v1/admin/products/import/templateAdminBaixar o modelo CSV
Devolve um CSV pequeno (Content-Type: text/csv, arquivo produtos_modelo.csv) com o cabeçalho e duas linhas de exemplo. Sem parâmetros.
As colunas do modelo, em ordem:
| Coluna | Significado no exemplo |
|---|---|
product_code | SKU (SKU-001). Apelido de sku. |
name | Nome do produto. |
price | Preço de venda em reais, com vírgula (49,90). |
list_price | Preço "de", opcional (59,90). |
status | A ativo, H oculto, D desativado. |
quantity | Estoque (100). |
weight | Peso em kg (0,500). |
category_id | Categoria (o exemplo mostra um nome). |
vendor_id | Seller (o exemplo mostra um nome, slug, e-mail ou id). |
description | Descrição completa. |
short_description | Resumo curto. |
curl "$BASE_URL/api/v1/admin/products/import/template" \
-H "Authorization: Bearer $TOKEN" -o produtos_modelo.csvproduct_code;name;price;list_price;status;quantity;weight;category_id;vendor_id;description;short_description
SKU-001;Produto Exemplo 1;49,90;59,90;A;100;0,500;Higiene e Beleza;Nome do vendedor (ou slug/e-mail/ID);Descrição completa;Resumo curto
SKU-002;Produto Exemplo 2;129,00;;A;50;1,200;Higiene e Beleza;Nome do vendedor (ou slug/e-mail/ID);Outra descrição;Outro resumoImportar
/api/v1/admin/products/importAdminImportar produtos de CSV ou XLSX em uma chamada
Envie um corpo multipart/form-data. Exige o privilégio manage_catalog.
Colunas (os nomes do cabeçalho não diferenciam maiúsculas; no arquivo só name e price são obrigatórias, mais um seller em toda linha):
| Coluna (apelidos) | Tipo | Observações |
|---|---|---|
sku (product_code) | texto | Identifica o produto. Até 128 caracteres. Se vazio, gera-se um SKU IMP-... e toda importação cria um produto novo para essa linha. |
name | texto | Obrigatório, até 512 caracteres. O HTML é removido. |
slug | texto | Nome na URL. Gerado a partir do nome quando vazio. Se já existir, acrescenta-se um sufixo e vem um aviso. |
price | decimal | Obrigatório. Veja a regra de preço abaixo. |
list_price, cost_price, shipping_freight | decimal | Opcionais. Vazio mantém o valor atual. |
quantity (stock_quantity, qty) | inteiro | Se a coluna não existe, o estoque atual é preservado. |
min_quantity, max_quantity, quantity_step | inteiro | Regras de quantidade de compra. quantity_step vale 1 por padrão. |
status | texto | A, D, H (qualquer caixa) ou active, disabled, hidden. Vazio ou não reconhecido vira ativo. |
category_id | uuid | UUID da categoria. |
vendor_id | uuid | UUID do seller. Obrigatório em toda linha, a menos que você mande o campo de formulário vendor_id. |
description, short_description (short_desc), promo_text | texto | Até 65.535 caracteres na descrição. HTML inseguro é removido. |
weight, length, width, height | número | Kg e cm. |
free_shipping | texto | Y, yes, true, 1, s, sim valem verdadeiro; qualquer outra coisa é falso. |
meta_title (seo_title), meta_description (seo_description), meta_keywords (keywords) | texto | Textos de SEO. |
Regra do preço. Um valor com separador decimal (49.90, 49,90, R$ 49,90) é lido em reais. Um valor sem separador é lido em centavos: 4990 é R$ 49,90, mas 50 é R$ 0,50. Escreva sempre duas casas.
Corpo da requisição (multipart/form-data)
filefileobrigatórioupdate_existingbooleanpadrão: truefalse para pular as linhas cujo SKU já existe (vão para os erros, nada é alterado).skip_errorsbooleanpadrão: truefalse para parar na primeira linha ruim. As linhas anteriores continuam importadas.vendor_iduuidExemplo de requisição
curl -X POST "$BASE_URL/api/v1/admin/products/import" \
-H "Authorization: Bearer $TOKEN" \
-F "file=@produtos.csv" \
-F "update_existing=true"Um arquivo que funciona com as colunas acima:
sku;name;price;quantity;status;category_id;vendor_id
CAM-001;Camiseta Azul;49,90;10;A;345ac33e-4dcd-4d60-bedf-a2c2d47897d9;9d9d9d56-eb43-4719-889d-055632f7c7da
CAN-002;Caneca Branca;4990;20;A;345ac33e-4dcd-4d60-bedf-a2c2d47897d9;9d9d9d56-eb43-4719-889d-055632f7c7daResposta
{
"total": 3,
"created": 3,
"imported": 3,
"updated": 0,
"skipped": 0,
"errors": [],
"warnings": null
}{
"total": 2,
"created": 0,
"imported": 0,
"updated": 0,
"skipped": 2,
"errors": [
{ "row": 2, "message": "db error: pq: invalid input syntax for type uuid: \"Higiene e Beleza\" (22P02)" },
{ "row": 3, "field": "price", "message": "price is required" }
],
"warnings": null
}Campos da resposta
totalintegercreatedintegerimported é o mesmo número, mantido para clientes antigos.updatedintegerskippedintegererrors.errorsarrayrow (número da linha na planilha, o cabeçalho é a linha 1), field (quando conhecido) e message.warningsarrayslug que já estava em uso. null quando vazio.Erros
| Status | Quando | Exemplo de corpo |
|---|---|---|
| 400 | A requisição não é multipart | {"error":"failed to parse multipart form","detail":"request Content-Type isn't multipart/form-data"} |
| 400 | Sem o campo file | {"error":"missing file field in form","detail":"..."} |
| 400 | Arquivo vazio, ou linha vazia no meio dos dados | {"error":"csv_empty","detail":"uploaded file is empty"} ou {"error":"csv_empty_row","detail":"..."} |
| 400 | XLSX malformado | {"error":"invalid spreadsheet","detail":"..."} |
| 401 / 403 | Sem token / sem manage_catalog | {"error":"missing authorization header"} / {"error":"insufficient privileges","required":"manage_catalog"} |
| 413 | Arquivo maior que 100 MiB | {"error":"file too large","detail":"CSV upload exceeds the 100 MiB limit"} |
| 415 | Extensão diferente de .csv, .txt, .xml, .xlsx ou .xlsm | {"error":"unsupported file type","detail":"only CSV, XLSX and XML files are accepted (got \".pdf\")"} |
| 500 | Falta a coluna obrigatória name ou price no cabeçalho | {"error":"import products failed","detail":"missing required column: name"} |