Como Enviar Seu Catálogo para o SiteChat
Se você usa o SiteChat no seu próprio site (não em uma loja Shopify), pode enviar registros de produtos estruturados para a Shoply para que os compradores possam encontrá-los no chat do SiteChat e na pesquisa de produtos.
Esses endpoints usam o mesmo Configurações → Segredo da API do proprietário da loja que o restante da API de Comerciantes da Shoply, e a página Catálogo de Produtos do admin do SiteChat pode chamá-los com seu token de acesso de admin autenticado. As lojas Shopify continuam sincronizando os dados do catálogo por meio da Shopify; essas rotas de upload estão disponíveis apenas para contas SiteChat que ainda não sincronizam um catálogo Magento.
No admin do SiteChat, Catálogo de Produtos abre uma área no estilo Shopify com Produtos, Coleções e Inventário. Você pode adicionar ou editar produtos, importar CSV/Excel, agrupar produtos em coleções manuais e ajustar quantidades em estoque.
Quais APIs Estão Disponíveis?
| API | Método | O que faz |
|---|---|---|
/merchant/products/batch | POST | Cria ou substitui completamente até 50 produtos em uma única solicitação |
/merchant/products | POST | Cria ou substitui completamente um produto |
/merchant/products | GET | Lê de volta um produto importado por source e external_id |
/merchant/products | PATCH | Atualiza parcialmente um produto; substituir variantes ou metafields exige a versão do GET |
/merchant/products | DELETE | Arquiva temporariamente um produto (status=archived) |
/merchant/products/list | GET | Pagina os produtos importados para tabelas do admin |
/merchant/products/images | POST | Envia uma imagem de produto e recebe uma URL HTTPS pública |
/merchant/collections | GET / POST | Lista ou cria coleções manuais |
/merchant/collections/{id} | GET / PUT / DELETE | Lê, substitui ou arquiva uma coleção |
/merchant/inventory | GET | Lista linhas de estoque (quantidades de produto e variante) |
/merchant/inventory/adjust | POST | Define a quantidade rastreada de um produto ou variante |
Salvamentos de produto bem-sucedidos pedem à Shoply para reconstruir o índice da loja. Até que essa reconstrução termine, as respostas informam index_status: "pending". Produtos publicados então aparecem tanto no índice de produtos quanto no conhecimento usado pelo chat do SiteChat.
Quem Pode Usar Essas APIs?
- Sua loja deve ser uma conta SiteChat (
app_platformé SiteChat). - Chaves de loja Shopify (incluindo qualquer domínio
*.myshopify.com) são rejeitadas. - A autenticação deve usar um segredo válido da API do proprietário da loja ou um token de acesso de admin do SiteChat para o
store_keyexato na solicitação. - Tokens da API Admin da Shopify não podem chamar essas rotas.
Crie ou altere o segredo do proprietário da mesma forma que outras integrações da API de Comerciantes: Como Usar a API de Comerciantes da Shoply. No console de admin do SiteChat, abra Catálogo de Produtos para gerenciar produtos, coleções e inventário — ou importar um arquivo CSV ou Excel — sem precisar gerenciar o segredo por conta própria.
Como Funciona a Autenticação?
A partir de um conector de servidor
Chame a API de um backend confiável via HTTPS. Coloque uma string JSON no cabeçalho Authorization:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"store_owner_api_secrete": "YOUR_STORE_OWNER_API_SECRET"
}store_owner_api_secrete é o nome público do campo, incluindo a grafia histórica. store_owner_api_secret também é aceito. Isso não é um token Bearer.
A partir do admin do SiteChat
A página Catálogo de Produtos envia sua sessão de admin autenticada em vez disso:
{
"store_key": "YOUR_SITECHAT_STORE_KEY",
"admin_auth_token": "YOUR_SITECHAT_ACCESS_TOKEN"
}access_token é aceito como alias para admin_auth_token.
O parâmetro de consulta store_key deve corresponder ao cabeçalho. Mantenha segredos do proprietário apenas em variáveis de ambiente no lado do servidor — nunca em um script da storefront, URL ou repositório público.
export SHOPLY_STORE_KEY="your-sitechat-store-key"
export SHOPLY_STORE_OWNER_API_SECRETE="shoply_owner_key_example123.secret-value"Como Faço Upload de Produtos?
POST https://api.shoplyai.ai/merchant/products/batch?store_key=YOUR_SITECHAT_STORE_KEY
{
"source": "woocommerce-main",
"products": [
{
"external_id": "123",
"title": "Trail shoes",
"description": "Water-resistant hiking shoes.",
"url": "https://example.com/products/trail-shoes",
"currency": "USD",
"price": "49.95",
"original_price": "59.95",
"available": true,
"status": "published",
"images": ["https://example.com/images/trail-shoes.jpg"],
"categories": ["Footwear"],
"metafields": {"material": "Leather"},
"variants": [
{
"external_id": "124",
"title": "Brown / 42",
"sku": "TRAIL-BR-42",
"price": "49.95",
"available": true,
"metafields": {"color": "Brown", "size": "42"}
}
]
}
]
}Campos obrigatórios e regras
- Campos obrigatórios do produto:
external_id,title,url,currency,priceeavailable.statustem como padrãopublished. - Inventário opcional: defina
tracks_inventorycomotruee umaquantitynão negativa no produto ou variante. A Shoply então deriva a disponibilidade do estoque (quantity > 0) e armazenatotal_inventorypara listas do admin. sourcenomeia a conexão do catálogo (não necessariamente uma plataforma). Use um nome estável comowoocommerce-main. Caracteres permitidos: letras minúsculas, números, sublinhados e hífens; até 64 caracteres. Produtos criados por formulário no admin usam por padrão a sourceadmin.- A identidade do produto é a combinação de loja, source e ID externo. Upserts em lote e
POSTindividual são substituições completas, não patches: campos opcionais omitidos são limpos. UsePATCHpara atualizações parciais. - Lotes contêm de 1 a 50 produtos e no máximo 2.000.000 bytes na solicitação. O JSON validado de cada produto é limitado a 128.000 bytes, com no máximo 250 variantes.
- Prefira strings decimais para preços. A moeda é um código em maiúsculas de três letras.
- URLs de produto e imagem devem ser HTTP(S). A importação não busca essas URLs para você.
- Use
metafieldspúblicos para especificações pesquisáveis do produto (o análogo do SiteChat aos metafields de produto da Shopify). Os valores devem ser strings simples. O antigoattributesé aceito como alias.metadataprivado do produto não é mais suportado. - Produtos
draftearchivedsão deixados de fora do próximo índice publicado. Produtos publicados esgotados permanecem indexados com a disponibilidade associada. - Coleções manuais armazenam um título, descrição, status e uma lista de associações de produtos (
source+external_id). Coleções inteligentes/baseadas em regras não são suportadas nesta versão.
Exemplo de resposta de sucesso
{
"results": [
{
"external_id": "123",
"product_id": "sitechat_product::woocommerce-main::<sha256-of-external-id>",
"status": "stored"
}
],
"index_status": "pending",
"index_revision": 1
}A Shoply valida toda a solicitação antes de gravar. Um HTTP 200 ainda pode listar alguns resultados failed com error: "storage_error". Inspecione cada resultado e tente novamente os produtos com falha. Se index_status for request_failed, o armazenamento teve sucesso, mas a indexação não foi agendada — tente novamente também os produtos armazenados.
Exemplo em Python
import json
import os
import requests
store_key = os.environ["SHOPLY_STORE_KEY"]
headers = {
"Authorization": json.dumps({
"store_key": store_key,
"store_owner_api_secrete": os.environ["SHOPLY_STORE_OWNER_API_SECRETE"],
})
}
response = requests.post(
"https://api.shoplyai.ai/merchant/products/batch",
params={"store_key": store_key},
headers=headers,
json={
"source": "custom",
"products": [{
"external_id": "123",
"title": "Trail shoes",
"url": "https://example.com/products/trail-shoes",
"currency": "USD",
"price": "49.95",
"available": True,
}],
},
timeout=60,
)
response.raise_for_status()
result = response.json()
failed = [item["external_id"] for item in result["results"] if item["status"] != "stored"]
if failed:
raise RuntimeError(f"Products need retry: {failed}")
if result["index_status"] == "request_failed":
raise RuntimeError("Products saved, but retry the batch to request indexing")Como Verifico um Produto Importado?
GET https://api.shoplyai.ai/merchant/products?store_key=YOUR_SITECHAT_STORE_KEY&source=woocommerce-main&external_id=123
Use o mesmo cabeçalho Authorization. A resposta inclui schema_version, updated_at, index_status e o product normalizado. Registros ausentes retornam HTTP 404.
Depois que o indexador em segundo plano publica uma reconstrução, o status de leitura por produto passa a ser indexed, excluded (para produtos em rascunho ou arquivados) ou limit_exceeded. Use GET /merchant/products/list para listagem no admin. Faça arquivamento temporário com DELETE /merchant/products (ou defina status como archived / draft) para manter um produto fora do próximo índice publicado; não há exclusão permanente nesta versão.
record = requests.get(
"https://api.shoplyai.ai/merchant/products",
params={
"store_key": store_key,
"source": "woocommerce-main",
"external_id": "123",
},
headers=headers,
timeout=30,
)
record.raise_for_status()
print(record.json()["index_status"], record.json()["product"]["title"])Como Atualizo Variantes ou Metafields com Segurança?
Para um PATCH contendo variants, metafields ou o campo legado attributes, primeiro leia o produto com GET. Monte a edição a partir dessa resposta e inclua o valor updated_at de nível superior como expected_updated_at no corpo do PATCH. Isso também se aplica ao limpar variantes ou metafields.
current_response = requests.get(
"https://api.shoplyai.ai/merchant/products",
params={"store_key": store_key, "source": "woocommerce-main", "external_id": "123"},
headers=headers,
timeout=30,
)
current_response.raise_for_status()
current = current_response.json()
updated_metafields = {**current["product"].get("metafields", {}), "material": "Leather"}
response = requests.patch(
"https://api.shoplyai.ai/merchant/products",
params={"store_key": store_key},
headers=headers,
json={
"source": "woocommerce-main",
"external_id": "123",
"expected_updated_at": current["updated_at"],
"metafields": updated_metafields,
},
timeout=30,
)
response.raise_for_status()HTTP 409 significa que a versão estava ausente ou que outra atualização alterou o produto. Leia o produto mais recente e mescle novamente as alterações pretendidas antes de tentar de novo. Não anexe uma nova versão a uma lista antiga de variantes: isso pode sobrescrever valores de estoque mais recentes.
Integrações existentes que fazem PATCH desses campos sem uma versão precisam ser atualizadas. Solicitações PATCH apenas com escalares, ajustes dedicados de inventário e substituições completas por meio de POST ou importação em lote não exigem esse campo. Substituições completas ainda substituem o produto inteiro.
Posso Enviar Imagens de Produtos?
Sim. Se uma imagem já estiver disponível em uma URL HTTPS pública duradoura, coloque essa URL na lista images do produto ou no campo image de uma variante. URLs HTTPS públicas do S3 funcionam. Caminhos brutos s3:// e URLs assinadas de curta duração não funcionam.
Para fazer a Shoply hospedar o arquivo, envie bytes brutos da imagem a partir do seu backend:
POST https://api.shoplyai.ai/merchant/products/images?store_key=YOUR_SITECHAT_STORE_KEY
Content-Type: image/pngEnvie os bytes brutos do arquivo, não JSON, base64 nem dados de formulário multipart. JPEG, PNG e WebP são aceitos, até 10 MiB e 20 milhões de pixels. Imagens animadas não são suportadas. A Shoply converte a imagem para WebP e remove metadados incorporados.
with open("trail-shoes.png", "rb") as image_file:
response = requests.post(
"https://api.shoplyai.ai/merchant/products/images",
params={"store_key": store_key},
headers={**headers, "Content-Type": "image/png"},
data=image_file,
timeout=60,
)
response.raise_for_status()
image_url = response.json()["url"]HTTP 201 retorna url, content_type, size_bytes, width e height. Enviar apenas uma imagem não a vincula a um produto nem solicita indexação. Inclua a URL retornada em um produto completo e envie-o novamente por /merchant/products/batch.
A mesma imagem enviada novamente para a mesma conta reutiliza sua URL. Uma imagem alterada recebe uma nova URL. Não há endpoint para excluir imagens nesta versão.
Quando os Produtos Aparecem no Chat e na Pesquisa?
Após um salvamento em lote bem-sucedido, a Shoply solicita uma reconstrução de índice em segundo plano. As respostas informam index_status: "pending" até que o worker publique o novo índice. Não há garantia fixa de tempo de conclusão.
- Produtos publicados entram tanto na pesquisa de produtos quanto no conhecimento usado pelo chat do SiteChat.
- Produtos em rascunho e arquivados são excluídos na próxima reconstrução.
- Se a indexação não foi agendada (
index_status: "request_failed"), tente novamente o lote para os produtos que já foram armazenados com sucesso.
Quais Erros Devo Esperar?
| HTTP status | Significado |
|---|---|
403 | Segredo ausente, inválido, expirado ou revogado; loja errada; ou uma conta que não é SiteChat |
404 | O produto importado solicitado não existe |
413 | A solicitação ou imagem excede o limite de tamanho |
415 | O upload da imagem usou um Content-Type não suportado |
422 | Campos inválidos, IDs duplicados, imagens animadas ou grandes demais, ou limites do modelo excedidos |
503 | Falha temporária de armazenamento |
Segredos expiram após 90 dias. Crie uma substituição em Configurações → Segredo da API do proprietário da loja antes do vencimento e revogue qualquer segredo de que você não precise mais. O mesmo segredo também pode chamar endpoints de analytics, conversas e conhecimento documentados no guia da API de Comerciantes.
Para obter ajuda com uma integração, entre em contato com a Shoply AI.
