Estoque

O estoque tem três visões do mesmo saldo: o que existe fisicamente, o que está reservado em carrinhos e pedidos abertos, e o que sobra disponível pra nova venda. Este guia cobre como consultar e movimentar cada uma pela API.


Conceitos

CampoO que é
quantityEstoque físico total na sua loja.
reserved_quantityJá comprometido em carrinhos/pedidos em aberto.
available_quantityO que sobra pra venda: quantity - reserved_quantity.

Regra: o catálogo respeita o available_quantity. Se ele zera, o produto deixa de aparecer pra novas compras, mesmo que ainda exista fisicamente.

O objeto que GET /products/{id}/stock devolve (total consolidado + saldo por localização):

{
  "total": 150,                // soma das quantidades em todos os locais
  "stocks": [                  // ← saldo por localização
    {
      "id": 321,               // ID do registro de saldo
      "product_sku": {},      // resumo do produto dono do saldo
      "location_stock": {},   // a localização deste saldo
      "quantity": 100,         // físico
      "reserved_quantity": 5,  // reservado em pedidos abertos
      "available_quantity": 95 // o que sobra pra venda
    }
  ],
  "locations": [{}]           // metadados dos locais (name, status, location_type…)
}

Tipos de movimentação

A rota de movimentação aceita 3 modos, controlados pelas flags booleanas increment e decrement:

Flags enviadasEfeito sobre quantity
nenhumaSobrescreve com o valor enviado. Útil pra acerto de inventário.
increment: trueSoma. Útil pra entrada de fornecedor.
decrement: trueSubtrai. Útil pra baixa manual (perda, avaria, venda fora do canal).

Mandar as duas flags juntas é recusado com 400.

Os 3 modos mexem só em quantity. O reserved_quantity é gerido pela plataforma, que reserva e libera saldo conforme os pedidos abrem e fecham — você cuida apenas do estoque físico.


Consultar saldo

GET/api/products/{id}/stock

{
  "data": {
    "total": 150,
    "stocks": [
      {
        "id": 321,
        "product_sku": {
          "id": "01H81AV32307PVBSV4RXF15EK9",
          "name": "Caneta Esferográfica Azul",
          "sku": "CAN-AZ-01"
        },
        "location_stock": {
          "location_id": "01H81AV32307PVBSV4RXF15LOC",
          "store_id": 42,
          "name": "Matriz - São Paulo",
          "status": "available",
          "location_type": "seller_location",
          "allows_pickup": false,
          "allows_production": false
        },
        "quantity": 100,
        "reserved_quantity": 5,
        "available_quantity": 95
      }
    ],
    "locations": [
      {
        "location_id": "01H81AV32307PVBSV4RXF15LOC",
        "store_id": 42,
        "name": "Matriz - São Paulo",
        "status": "available",
        "location_type": "seller_location",
        "allows_pickup": false,
        "allows_production": false
      }
    ]
  }
}

No exemplo, o product_sku aparece resumido; na prática ele vem com o cadastro completo do produto (preços, thumbnail, dimensões…).


Movimentar

POST/api/products/{id}/stock

O location_id é obrigatório: diz em qual local o saldo se move. Sem flag nenhuma, o valor enviado sobrescreve a quantidade:

{
  "location_id": "01H81AV32307PVBSV4RXF15LOC",
  "quantity": 150
}

Exemplos por cenário

Recebi 40 unidades do fornecedor:

{
  "location_id": "01H81AV32307PVBSV4RXF15LOC",
  "quantity": 40,
  "increment": true
}

Inventário deu 95 (era 100):

{
  "location_id": "01H81AV32307PVBSV4RXF15LOC",
  "quantity": 95
}

Avaria, baixar 3:

{
  "location_id": "01H81AV32307PVBSV4RXF15LOC",
  "quantity": 3,
  "decrement": true
}

Regras do corpo

  • location_id e quantity são obrigatórios.
  • quantity é um inteiro maior ou igual a 1. Não existe envio de 0: para zerar um saldo, use decrement com a quantidade que existe hoje.
  • location_id precisa ser o location_id (ULID) de um local acessível pela loja — os mesmos que aparecem em Locais de estoque.

O que pode dar errado

ErroQuando aconteceComo tratar
400 BAD_REQUESTincrement e decrement enviados juntos.Escolha um dos dois, ou nenhum para sobrescrever.
422O local é do tipo fulfillment.Esse saldo é sincronizado pelo WMS da plataforma e não muda por esta rota.
422 SUBSTORE_CATALOG_READ_ONLYA loja opera em modo espelho.SKU, preço e estoque vêm da matriz; a subloja não movimenta estoque.
422 VALIDATION_ERRORlocation_id inexistente ou quantity menor que 1.Corrija os campos apontados em errors.
404 NOT_FOUNDO produto não existe no catálogo efetivo da loja.Confira o {id} do produto.