Pular para o conteúdo principal
POST
/
ecommerce
/
v2
/
apps
/
{app_id}
/
batch
/
products
/
upsert_by_sku
curl -X POST "https://gateway.jelou.ai/ecommerce/v2/apps/{app_id}/batch/products/upsert_by_sku" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resources": [
      {
        "sku": "TSHIRT-BLU",
        "name": "Camiseta Básica Azul",
        "description": "Camiseta 100% algodão premium, corte regular",
        "price": 29.99,
        "has_tax": true,
        "tax": 15,
        "status": true,
        "stock_type": "limited",
        "stock": 150,
        "product_url": "https://minha-loja.com/camiseta-basica-azul",
        "discount_type": "percentage",
        "discount": 10,
        "branch": "BRANCH-DOWNTOWN",
        "categories": ["Roupas", "Camisetas"],
        "images": [
          "https://minha-loja.com/images/camiseta-azul-frente.jpg",
          "https://minha-loja.com/images/camiseta-azul-costas.jpg"
        ],
        "variations": [
          {
            "sku": "TSHIRT-BLU-S",
            "price": 29.99,
            "stock_type": "limited",
            "stock": 50,
            "attributes": [
              { "name": "Tamanho", "value": "S" },
              { "name": "Cor", "value": "Azul" }
            ]
          },
          {
            "sku": "TSHIRT-BLU-M",
            "price": 29.99,
            "stock_type": "limited",
            "stock": 60,
            "attributes": [
              { "name": "Tamanho", "value": "M" },
              { "name": "Cor", "value": "Azul" }
            ]
          },
          {
            "sku": "TSHIRT-BLU-L",
            "price": 31.99,
            "stock_type": "limited",
            "stock": 40,
            "attributes": [
              { "name": "Tamanho", "value": "L" },
              { "name": "Cor", "value": "Azul" }
            ],
            "images": [
              "https://minha-loja.com/images/camiseta-azul-L.jpg"
            ]
          }
        ]
      },
      {
        "sku": "PANTS-BLK-M",
        "name": "Calça Preta",
        "price": 49.99,
        "branch": "BRANCH-NORTH",
        "categories": ["Roupas", "Calças"],
        "note_enabled": true,
        "note_label": "Alguma instrução especial?"
      },
      {
        "sku": "PIZZA-FAMILY",
        "name": "Pizza Pepperoni Família",
        "description": "Pizza pepperoni tamanho família com massa artesanal",
        "price": 18.99,
        "stock_type": "unlimited",
        "branch": "BRANCH-NORTH",
        "categories": ["Pizzas", "Promoções"],
        "images": ["https://exemplo.com/pizza-pepperoni.jpg"],
        "modifier_groups": [
          {
            "code": "drinks",
            "name": "Escolha sua Bebida",
            "min_quantity": 1,
            "max_quantity": 1,
            "is_required": true,
            "options": [
              { "code": "coca-1l", "name": "Coca Cola 1L", "price": 0 },
              { "code": "sprite-1l", "name": "Sprite 1L", "price": 0 },
              { "code": "fanta-1l", "name": "Fanta 1L", "price": 0.50 }
            ]
          },
          {
            "code": "extras",
            "name": "Ingredientes Extras",
            "min_quantity": 0,
            "max_quantity": 5,
            "max_per_option": 2,
            "is_required": false,
            "options": [
              { "code": "extra-cheese", "name": "Queijo Extra", "price": 1.50 },
              { "code": "ham", "name": "Presunto", "price": 2.00 },
              { "code": "olives", "name": "Azeitonas", "price": 1.00 }
            ]
          }
        ]
      }
    ]
  }'
{
  "message": "Batch upsert process initiated successfully",
  "count": 3,
  "jobs": 3
}
Você pode criar ou atualizar produtos em massa pelo SKU. Se um produto com o SKU especificado já existir, ele é atualizado; caso contrário, é criado. Os produtos podem ser atribuídos a uma filial, ter múltiplas variações e grupos de modificadores.
app_id
string
obrigatório
O ID da sua loja no Jelou Shop.
resources
object[]
obrigatório
Lista de produtos a criar ou atualizar (máx. 500 por requisição).

Campos do produto

Cada objeto dentro de resources aceita os seguintes campos:
sku
string
obrigatório
Identificador único do produto (máx. 255 caracteres).
name
string
obrigatório
Nome do produto (máx. 255 caracteres).
price
number
obrigatório
Preço do produto (mín. 0).
description
string
Descrição do produto.
has_tax
boolean
padrão:"true"
Indica se o preço inclui impostos.
tax
number
Taxa de imposto individual do produto (entre 0 e 100). Exemplo: 15 para 15%, 12 para 12%. Aplica-se apenas quando enable_per_product_tax está ativo na configuração da loja. Se não for enviado ou for 0, a taxa global da loja é usada.
status
boolean
padrão:"true"
Status do produto (ativo/inativo).
stock_type
string
padrão:"unlimited"
Tipo de inventário: limited ou unlimited.
stock
number
Quantidade disponível. Aplica-se apenas quando stock_type é limited.
product_url
string
URL do produto na sua loja (máx. 2048 caracteres).
discount_type
string
Tipo de desconto: value (valor fixo) ou percentage.
discount
number
Valor do desconto (mín. 0).
categories
string[]
Lista de nomes de categorias. São criadas automaticamente se não existirem.
images
string[]
Lista de URLs públicas de imagens do produto.
note_enabled
boolean
padrão:"false"
Habilita um campo de nota na página de detalhe do produto, permitindo que o cliente adicione um comentário ao adicionar o produto ao carrinho (ex.: “Sem cebola”, “Embrulhar para presente”).
note_label
string
Texto placeholder exibido no campo de nota (máx. 255 caracteres). Se não especificado, um texto genérico padrão é usado.
branch
string
Código da filial à qual o produto é atribuído. A filial deve já existir.
A filial deve ser criada antes de ser atribuída a um produto. Use o endpoint Criar filial para registrá-la primeiro.
features
object[]
Lista de características (ficha técnica) do produto.
replace_variations
boolean
padrão:"false"
Controla como as variações são sincronizadas. Com false (padrão), as variações são atualizadas ou criadas por SKU e as existentes que não estiverem no payload são mantidas. Com true, as variações que não estiverem no payload são removidas.
variations
object[]
Lista de variações do produto.
modifier_groups
object[]
Grupos de modificadores do produto (adicionais). Comum em delivery de comida (ex.: “Escolha sua Bebida”, “Escolha seus Molhos”). Se o campo estiver ausente, os modificadores existentes são preservados. Se for um array vazio [], todos os modificadores são excluídos. Se tiver dados, os modificadores são completamente substituídos.
Os modificadores são armazenados no produto e retornados automaticamente em todos os endpoints que retornam produtos.

Exemplo completo

Este exemplo cria três produtos: uma camiseta com variações de tamanho, uma calça simples e uma pizza com grupos de modificadores.
curl -X POST "https://gateway.jelou.ai/ecommerce/v2/apps/{app_id}/batch/products/upsert_by_sku" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "resources": [
      {
        "sku": "TSHIRT-BLU",
        "name": "Camiseta Básica Azul",
        "description": "Camiseta 100% algodão premium, corte regular",
        "price": 29.99,
        "has_tax": true,
        "tax": 15,
        "status": true,
        "stock_type": "limited",
        "stock": 150,
        "product_url": "https://minha-loja.com/camiseta-basica-azul",
        "discount_type": "percentage",
        "discount": 10,
        "branch": "BRANCH-DOWNTOWN",
        "categories": ["Roupas", "Camisetas"],
        "images": [
          "https://minha-loja.com/images/camiseta-azul-frente.jpg",
          "https://minha-loja.com/images/camiseta-azul-costas.jpg"
        ],
        "variations": [
          {
            "sku": "TSHIRT-BLU-S",
            "price": 29.99,
            "stock_type": "limited",
            "stock": 50,
            "attributes": [
              { "name": "Tamanho", "value": "S" },
              { "name": "Cor", "value": "Azul" }
            ]
          },
          {
            "sku": "TSHIRT-BLU-M",
            "price": 29.99,
            "stock_type": "limited",
            "stock": 60,
            "attributes": [
              { "name": "Tamanho", "value": "M" },
              { "name": "Cor", "value": "Azul" }
            ]
          },
          {
            "sku": "TSHIRT-BLU-L",
            "price": 31.99,
            "stock_type": "limited",
            "stock": 40,
            "attributes": [
              { "name": "Tamanho", "value": "L" },
              { "name": "Cor", "value": "Azul" }
            ],
            "images": [
              "https://minha-loja.com/images/camiseta-azul-L.jpg"
            ]
          }
        ]
      },
      {
        "sku": "PANTS-BLK-M",
        "name": "Calça Preta",
        "price": 49.99,
        "branch": "BRANCH-NORTH",
        "categories": ["Roupas", "Calças"],
        "note_enabled": true,
        "note_label": "Alguma instrução especial?"
      },
      {
        "sku": "PIZZA-FAMILY",
        "name": "Pizza Pepperoni Família",
        "description": "Pizza pepperoni tamanho família com massa artesanal",
        "price": 18.99,
        "stock_type": "unlimited",
        "branch": "BRANCH-NORTH",
        "categories": ["Pizzas", "Promoções"],
        "images": ["https://exemplo.com/pizza-pepperoni.jpg"],
        "modifier_groups": [
          {
            "code": "drinks",
            "name": "Escolha sua Bebida",
            "min_quantity": 1,
            "max_quantity": 1,
            "is_required": true,
            "options": [
              { "code": "coca-1l", "name": "Coca Cola 1L", "price": 0 },
              { "code": "sprite-1l", "name": "Sprite 1L", "price": 0 },
              { "code": "fanta-1l", "name": "Fanta 1L", "price": 0.50 }
            ]
          },
          {
            "code": "extras",
            "name": "Ingredientes Extras",
            "min_quantity": 0,
            "max_quantity": 5,
            "max_per_option": 2,
            "is_required": false,
            "options": [
              { "code": "extra-cheese", "name": "Queijo Extra", "price": 1.50 },
              { "code": "ham", "name": "Presunto", "price": 2.00 },
              { "code": "olives", "name": "Azeitonas", "price": 1.00 }
            ]
          }
        ]
      }
    ]
  }'
{
  "message": "Batch upsert process initiated successfully",
  "count": 3,
  "jobs": 3
}
Substitua {app_id} pelo ID da sua loja e YOUR_API_KEY pela sua chave de API.

Comportamento

O endpoint retorna 202 Accepted imediatamente. Os produtos são processados em segundo plano.
Envie o header X-Sync: true para processar de forma síncrona e receber o resultado por produto na mesma resposta (200 OK). Nesse modo o máximo é de 50 produtos por requisição.
200 OK
{
  "message": "Batch upsert processed synchronously",
  "count": 2,
  "succeeded": 1,
  "failed_count": 1,
  "failed": [
    { "sku": "CAM-BLU", "status": "failed", "error": "..." }
  ],
  "results": [
    { "sku": "PAN-NEG-M", "status": "success" },
    { "sku": "CAM-BLU", "status": "failed", "error": "..." }
  ]
}
Se o código da filial não corresponder a nenhuma filial da loja, o produto é criado sem atribuição de filial. Nenhum erro é produzido.
Se uma categoria não existir, ela é criada automaticamente dentro da loja e da filial correspondente.
As imagens são baixadas e processadas em segundo plano após a criação do produto.
As variações são identificadas pelo SKU. Se uma variação com esse SKU já existir, ela é atualizada em vez de criar uma nova. Por padrão, as variações existentes que não estiverem no payload são mantidas; envie replace_variations: true para removê-las.
Se modifier_groups estiver ausente no payload, os modificadores existentes são preservados. Se for um array vazio [], todos os modificadores são excluídos. Se tiver dados, os modificadores são completamente substituídos.

Erros de validação

Se os dados não atenderem às regras de validação, a API responde com 422 e detalha os campos com erros.
{
  "message": "The resources field is required.",
  "errors": {
    "resources": ["The resources field is required."]
  }
}
CampoMensagem
resourcesAt least one product is required.
resourcesCannot process more than 500 products at once.
resources.*.skuEach product must have a SKU.
resources.*.nameEach product must have a name.
resources.*.priceEach product must have a price. / Price cannot be negative.
resources.*.stock_typeStock type must be either limited or unlimited.
resources.*.images.*Each image must be a valid URL.
resources.*.variations.*.stock_typeVariation stock type must be either limited or unlimited.
resources.*.variations.*.stockVariation stock must be an integer. / Cannot be negative.
resources.*.modifier_groups.*.codeEach modifier group must have a code.
resources.*.modifier_groups.*.nameEach modifier group must have a name.
resources.*.modifier_groups.*.optionsEach modifier group must have at least one option.
resources.*.modifier_groups.*.options.*.codeEach modifier option must have a code.
resources.*.modifier_groups.*.options.*.nameEach modifier option must have a name.
resources.*.taxTax rate must be a number. / cannot be negative. / cannot exceed 100.
resources.*.replace_variationsReplace variations flag must be true or false.
resources.*.features.*.labelEach feature must have a label. / cannot exceed 255 characters.
resources.*.features.*.valueEach feature must have a value. / cannot exceed 200 characters.
As mensagens da coluna Mensagem são retornadas pela API em inglês (não são localizadas), portanto aparecem aqui exatamente como a API responde.

Limites

  • Máximo de 500 produtos por requisição no modo assíncrono (padrão), ou 50 no modo síncrono (X-Sync: true).
  • Máximo de 10.000 produtos por janela de 60 segundos por loja (rate limit). Se excedido, a API responde com 429 Too Many Requests.
  • Todos os produtos são validados antes de serem processados.