Últimas mudanças
Novidades da API pública.
Vídeo: ai_model_id e extra_ref_ids foram retirados
POST /v1/products/{id}/ai-video e o seu roteiro não aceitam mais ai_model_id nem extra_ref_ids («o modelo nas tomadas»): o fornecedor recusa o rosto do modelo. Enviá-los responde 422 (X-Bruxel-Reason: params) sem reservar créditos. O vídeo por tomadas, o que aceita o modelo, por enquanto só existe no aplicativo.
Os relatórios, também pela API
Com o novo scope reports:read o seu BI lê os mesmos relatórios da seção: GET /v1/reports dá o catálogo com quantas linhas cada um tem no período, GET /v1/reports/:id/rows uma página em JSON (até as primeiras 10.000 linhas) e GET /v1/reports/:id.csv o arquivo completo. O período vai com from, to e tz; brand e status filtram onde o relatório os usa.
Os fluxos avisam: sua vez, parou, terminou
Três eventos de webhook novos: flow.step.ready (produtos que chegaram a uma etapa), flow.run.blocked (percursos que pararam com um erro) e flow.run.completed (percursos que terminaram). Chegam agrupados, um por etapa ou por fluxo, com a contagem e uma amostra de até 20; a lista completa vem de GET /v1/flows/:slug/steps/:key/products e de GET /v1/flows/:slug/runs, com cursor. Ativar um fluxo acorda você uma vez por etapa que tem produtos.
As etapas dos seus sistemas: avisos e chamadas
Uma etapa de um fluxo também é dada como feita quando o Bruxel entrega um aviso a um sistema (um webhook respondido com um 2xx) ou quando a chave desse sistema lê ou escreve a ficha (consultar o percurso ou o histórico não conta). Em GET /v1/products/:id/journey, `cause` pode ser `delivery` ou `api_call`, e `event_system` e `event_type` dizem o sistema e o que foi: o aviso ou a operação (`read` ou `write`). Um evento sem `system` usa o sistema conectado ao qual a chave está ligada.
Informe o que acontece fora e leia o percurso de um produto
POST /v1/events (scope `events:write`) recebe até 100 eventos por chamada: qual sistema, o que aconteceu, se deu certo e quando. Uma etapa de um fluxo pode ser concluída com esse evento. GET /v1/products/:id/journey (scope `catalog:read`) mostra onde o produto está em cada fluxo e o que os sistemas informaram sobre ele.
Atributos derivados: `derived` e o 422 `derived`
`GET /v1/attributes` traz `derived`: `true` quando o sistema põe o valor a partir de outro dado (outro atributo, a categoria ou a marca) segundo uma regra do cliente. Num produto onde a derivação se aplica, `PUT /v1/products/{id}/attributes/{code}` responde 422 com `X-Bruxel-Reason: derived` e não escreve nada: muda-se a origem e o derivado é recalculado na mesma escrita.
Listas compartilhadas: `value_list` em cada atributo
`GET /v1/attributes` traz `value_list`: o código da lista compartilhada de onde vêm as opções do atributo, ou `null`. As opções de um atributo vinculado são lidas e atribuídas como sempre; o que muda é que são editadas na lista, pelo app.
Kits: a composição de um produto, por SKU
`GET` e `PUT /v1/products/{product_id}/components` (scopes `catalog:read`/`catalog:write`) leem e escrevem a composição de um kit: os produtos que o formam, com sua quantidade e em ordem, mais `part_of` (em quantos kits o produto está). Um SKU desconhecido é 422 que o nomeia; um kit tem um só nível. O upsert e o import também montam kits a partir de `associated_skus` ou `kit_components` (`sku=quantidade`), e os canais os emitem com a coluna `kit.components`.
Um valor próprio por canal: `is_channel_scoped` e `channel`
`GET /v1/attributes` diz quais atributos têm um valor próprio por canal (`is_channel_scoped`). Neles, `PUT /v1/products/{id}/attributes/{code}` aceita `channel` (o `slug` do canal) para escrever o valor DESSE canal sem tocar no mestre, e `GET …/attributes?channel=` o lê com fallback para o mestre: o mesmo valor que sai no CSV do canal. Um atributo que não é por canal ou um canal que não existe dão 422.
O valor de cada opção em cada canal: `map` e `strict`
`GET /v1/channels` traz, por coluna, `map` (o valor que ESSE arquivo escreve para cada opção de uma lista: «Rojo» → «Red» na Amazon, «001» no ERP) e `strict` (uma opção sem valor para o canal sai vazia e o produto conta como incompleto em `readiness`). A chave é o texto que a célula teria sem o mapeamento, no idioma do canal. Com `null`/`false` a célula sai como sempre.
Este produto sai completo no canal? — por produto
`GET /v1/products/{id}/channels/readiness` (scope `channels:read`) diz, para cada canal configurado, se o produto sairia completo no seu CSV: `published` (há ficha publicada no idioma do canal), `ready` e `missing` com cada coluna que falta e sua fonte (`output.{campo}`, `attribute.{code}`, `media.*`). É o que um middleware olha antes de criar o produto na loja. Mesmo resolvedor do arquivo; não cobra.
Enviar e vincular imagens pela API (media:write)
Novo scope `media:write` e quatro rotas: `POST /v1/media/presign` reserva cota e devolve o POST assinado do S3; `POST /v1/media/{asset_id}/complete` confirma por assinatura binária e peso real; `POST /v1/products/{id}/media` vincula o asset com seu papel e `DELETE /v1/products/{id}/media/{asset_id}` o desvincula. É a mesma porta do DAM que o app usa: o servidor nunca vê os bytes, a cota é reservada antes de assinar e um arquivo que mente sobre seu tipo é descartado.
Escrever o valor de um atributo em um idioma
`PUT /v1/products/{id}/attributes/{code}` aceita `language`: escreve o valor NESSE IDIOMA de um atributo localizável; sem ele, o valor vai para o slot global como sempre. `GET /v1/attributes` diz de antemão quem aceita (`is_localizable`). Um idioma não suportado, ou um atributo não localizável, é 422 nomeando o código — e `GET …/attributes?language=xx` também é 422 agora, em vez de um 200 com os valores globais.
Grupos de atributos em GET /v1/attributes
Cada atributo traz `group`: o código do grupo (a seção da ficha) ao qual pertence, ou `null`. É o código e não um id porque esta API fala em códigos: um integrador que monta a linha de uma equipe filtra por ele sem uma segunda viagem. Os grupos são definidos no app ou com a coluna `group` do CSV de definições.
Filtrar o catálogo pelo valor de um atributo
`GET /v1/products` aceita `attr=codigo:valor` (repetível, até cinco, em AND): o texto da opção numa lista, Sim/Não num booleano, texto exato, número ou data; um `codigo:` vazio deixa os produtos SEM valor. É a mesma pergunta que a fila de uma equipe faz no app — por exemplo `attr=ready_to_master_data:Sí&attr=ready_to_sap:` — e o que não dá para aplicar é 422 com a causa, nunca uma lista vazia.
O feed de mudanças da ficha, e um `product.updated` que diz o que mudou
`GET /v1/products/deltas` percorre o histórico de todas as suas fichas com um cursor retomável: para cada versão diz o produto, o motivo e O QUE mudou (campos, códigos de atributo, categorias, família), nunca os valores; com `attribute=` e `reason=` você escuta só uma bandeira ou um motivo. E o webhook `product.updated` agora sai de qualquer mudança real da ficha — inclusive ao escrever o valor de um atributo, que antes não avisava — com `version`, `reason` e `changed`. É um despertador: releia a ficha ou o feed, não confie só em `changed`.
O histórico da ficha registra as mudanças do catálogo
O histórico de cada ficha agora registra o que acontece com ela quando o catálogo muda: excluir um atributo, uma opção, uma categoria ou uma família, ou renomear uma opção ou um code, deixa uma versão com `reason` `structure`. E `changes` pode trazer duas chaves novas: `replaced` (o code agora é de outro atributo) e `recoded` (o mesmo atributo com outro code).
Unidades de medida em atributos e canais
Um atributo de medida agora diz de que medida é e quais unidades aceita: `GET /v1/attributes` traz `dimension` e `accepted_units`, e o `PUT` de um valor aceita «1.7 fl oz» num atributo em ml (converte sozinho). E cada coluna de canal pode pedir outra unidade, outras casas decimais ou o número sem a unidade: `GET /v1/channels` expõe isso em `columns[]` para você saber ler a célula.
Produtos relacionados por API
Agora você pode ler e escrever com quais outros produtos cada um é oferecido — relacionados, venda cruzada e venda superior — por SKU, e baixá-los no CSV do seu canal com os nomes de coluna que sua loja espera.
Publicar, aprovar e despublicar por API
Três endpoints novos com o próprio escopo `content:manage`: publicar uma versão específica, aprovar o candidato do fluxo editorial e parar de servir uma ficha. O escopo é separado de `catalog:write` de propósito — escrever a ficha e decidir o que sua loja serve são coisas diferentes.
Histórico da ficha: o que mudou em um produto e quando
GET /v1/products/{product_id}/revisions devolve as versões de uma ficha, da mais recente à mais antiga, com o que mudou em cada uma: campos, atributos (por código e idioma), categorias e família. Dos dados importados são reportados os nomes das colunas que mudaram, nunca o seu conteúdo. Para o integrador que sincroniza e quer saber o que olhar sem baixar a ficha inteira de novo.
Canais: quais colunas são obrigatórias e quantos produtos estão prontos
GET /v1/channels agora traz `columns[].required` e `skip_incomplete` (se o canal omite as linhas incompletas do seu CSV e do seu feed). E GET /v1/channels/{slug}/readiness diz quantos produtos sairiam completos no canal, quantos não têm ficha publicada e quais colunas obrigatórias faltam mais — com o mesmo critério do ficheiro.
O objeto 3D do produto, no mesmo endpoint de mídias
GET /v1/products/{id}/media pode trazer um quarto papel: model_3d. Sua url é o GLB e o campo novo usdz_url é o mesmo modelo em USDZ, a única coisa que o Quick Look abre no iPhone; numa imagem ou num vídeo é null. Aditivo: se você já integra, seu contrato não muda — mas escolha a imagem base por role, não pelo índice 0.
O código do atributo na sua loja
GET /v1/attributes devolve external_code: o attribute_code pelo qual o Adobe Commerce conhece cada atributo, informado no Bruxel. Quando existe, /v1/export/catalog.csv nomeia a coluna assim em vez de code. null = sem código externo; nada muda.
Vídeo por API: clipes de até 30 segundos, com roteiro
POST /v1/products/{id}/ai-video inicia um clipe a partir de uma imagem já salva do produto: cinco segundos com tarifa fixa, ou até 30 com áudio cobrados por segundo × qualidade. Com ai_model_id a mesma modelo aparece em todas as tomadas. POST /v1/products/{id}/ai-video/script escreve o roteiro por tomadas com IA (3 créditos, no sucesso).
O visual de cada foto: penteado, maquiagem e roupa
POST /v1/products/{id}/ai-media aceita hairstyle, makeup e outfit para dirigir como a modelo aparece NAQUELA foto, sem tocar na identidade dela. Os três abrem em as_model e com esse valor nada muda em relação a antes; o job os devolve em look.
Roupa e expressão na geração de imagens
POST /v1/products/{id}/ai-media aceita subject (product | garment) para que a modelo vista a peça em vez de segurá-la, e expression (natural, smile, laugh, neutral, serious, playful) para escolher o rosto dela. Os dois são opcionais e o padrão deles reproduz o comportamento anterior; o job os devolve em subject e expression.
Imagens: feed de mudanças, webhook e geração por API
GET /v1/media/deltas diz quais produtos mudaram a galeria (exclusões incluídas); o evento media.updated avisa em tempo real; GET /v1/products/{id}/media traz o papel real (swatch aparece), a posição e a procedência (origin, synthetic_performer); e com o novo scope media:generate você abre sessões de fotos com IA a partir do seu sistema (POST /v1/products/{id}/ai-media, GET /v1/ai-media/jobs/{id}, GET /v1/ai-models).
Chaves de API por organização
Novas chaves bxk_ com permissões por scope (catalog:read, generate, export…), entrega única e revogação imediata pelo console.
Lotes assíncronos com idempotência
O endpoint POST /v1/batches para geração em volume: reserva de créditos, Idempotency-Key obrigatória e cobrança por resultado na leitura.
Exportação de catálogo por idioma
GET /v1/export/catalog.csv?language=es retorna seu catálogo gerado no idioma solicitado, no formato Adobe Commerce.