Produtos, preços e estoque
A loja é a fonte da verdade do catálogo, dos preços e do estoque. ERPs e outros apps leem e escrevem pelos endpoints padrão; cada escrita é atribuída ao app, fica no histórico da loja e gera eventos para os demais apps.
O SKU é a chave
O SKU é único por loja e liga a loja ao ERP. Use GET /variants?sku=A,B,C (até 100) para encontrar as variantes; preços e estoque são sempre escritos por SKU.
Produtos
POST /products cria (o ERP pode fornecer os dados iniciais), PATCH /products/{product_id} edita e DELETE arquiva. Fotos, categorias e textos de vitrine continuam com o lojista no painel; o SEO é gerado automaticamente.
Preços
POST /prices/batch define price e compare_at_price (preço “de”) por SKU, em centavos. Cupons, desconto no Pix e promoções continuam na loja e não são alterados.
curl -X POST https://api.tfshop.cloud/v1/prices/batch \
-H "Authorization: Bearer $TFSHOP_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 2a7d4c1e-9b8f-4e6a-a3c5-7f1e2d3c4b5a" \
-d '{ "items": [
{ "sku": "VLT-GAN65W", "price": 16990, "compare_at_price": 21990 },
{ "sku": "VLT-CHARGER20", "price": 6490, "compare_at_price": null }
] }'Estoque: definir ou ajustar
Cada SKU tem on_hand (em mãos), reserved (reservado por pedidos ainda não pagos) e available = on_hand − reserved.
Definir (set)
Envia a quantidade absoluta em mãos. Use depois de uma contagem, ou quando o ERP controla o estoque físico. Reenviar o mesmo valor não muda nada.
Ajustar (adjust)
Soma ou subtrai unidades (delta) com um motivo em texto (reason, como “Recebimento NF 88213”). Não sobrescreve vendas feitas nesse meio-tempo; sempre envie Idempotency-Key para não aplicar o mesmo ajuste duas vezes.
# Absolute on-hand quantity after a stock count
curl -X POST https://api.tfshop.cloud/v1/inventory_levels/set \
-H "Authorization: Bearer $TFSHOP_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 5d2c8e1a-4b7f-4c9d-8e6a-1f2a3b4c5d6e" \
-d '{ "items": [
{ "sku": "VLT-GAN65W", "on_hand": 42 },
{ "sku": "VLT-CHARGER20", "on_hand": 130 }
] }'# Goods received: +24 units (never applied twice thanks to the key)
curl -X POST https://api.tfshop.cloud/v1/inventory_levels/adjust \
-H "Authorization: Bearer $TFSHOP_TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8f4e2a6c-1d3b-4f7a-9c2e-6b5a4d3c2e1f" \
-d '{ "items": [
{ "sku": "VLT-GAN65W", "delta": 24, "reason": "Recebimento NF 88213" }
] }'Lotes de até 100
Os endpoints em lote aceitam até 100 itens por chamada e contam como uma requisição no limite. O lote é aplicado inteiro ou nada: se um item for inválido, nada muda e errors aponta o item (items[2].sku). Para sincronizar milhares de SKUs, divida em lotes de 100 e respeite Retry-After.
Evite o eco
product.updated, inventory.updated) para os assinantes, inclusive você. O evento traz actor.type = "app" e actor.app_id: ignore os que têm o seu app_id para não criar um ciclo ERP → loja → ERP.// Ignore events caused by your own writes (no ERP → store → ERP loop)
function isOwnEcho(event) {
return event.actor?.type === "app" && event.actor.app_id === process.env.TFSHOP_APP_ID;
}