Fluxos e eventos
O Bruxel vê o que acontece dentro: a ficha, o envio do fornecedor, a descrição publicada. O que acontece fora —seu middleware chamou o SAP, o armazém cadastrou o material, a loja publicou— ele só sabe se o seu sistema informar.
O scope
Informar exige uma chave com o scope events:write. Ler o percurso de um produto exige catalog:read. A organização sempre vem da chave: o corpo nunca a informa.
Informar eventos
Envie até 100 eventos por chamada, dos produtos que quiser. Cada evento é de um produto (por sku ou product_id) e diz qual sistema, qual tipo, como foi (started, ok, error ou info) e quando aconteceu.
curl -X POST https://bruxel.ai/api/public/v1/events \
-H "Authorization: Bearer $BRUXEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"id": "mw-000123",
"sku": "BTL-1001",
"system": "sap",
"type": "material.created",
"status": "ok",
"occurred_at": "2026-10-05T18:04:11Z",
"duration_ms": 1840,
"summary": "Material creado: 4500012345",
"in_reply_to": "6f1c0e9a-7d2b-4c11-a4f0-91be2d07c3aa",
"request": { "method": "POST", "url": "https://sap.ejemplo/odata/A_Product", "body": { "Product": "BTL-1001" } },
"response": { "status": 201, "body": { "Product": "4500012345" } },
"link": "https://sap.ejemplo/material/4500012345",
"data": { "sap_code": "4500012345" }
}
]
}'A resposta traz uma linha por evento, na mesma ordem: accepted (gravado), duplicate (você já o tinha: é o resultado original) ou rejected (não gravado, com o motivo).
{
"accepted": 1,
"duplicates": 0,
"rejected": 0,
"results": [
{
"index": 0,
"id": "mw-000123",
"outcome": "accepted",
"event_id": "…",
"product_id": "…",
"reason": null,
"detail": null,
"truncated": false
}
]
}Regras do contrato
- Idempotência: o id é seu e único por sistema. Repetir o mesmo evento é seguro (duplicate); o mesmo id com outro conteúdo volta rejected com id_conflict.
- Cada evento indica o produto com sku ou product_id. Se enviar os dois, devem ser o mesmo produto. Um produto excluído ou de outra organização dá product_not_found.
- system vai em minúsculas (sap, wms, loja). Se não for enviado, usa-se o sistema conectado ao qual a chave está ligada (Conta → Geral → Sistemas conectados) ou, se ela não estiver ligada, o nome da chave em minúsculas: “SAP middleware” vira sap_middleware, a menos que esse sistema tenha sua própria chave. Qualquer chave com events:write pode informar por qualquer sistema que nomear: use uma chave por sistema.
- occurred_at é a hora do fato, com fuso (ISO 8601), e quem define é você; o Bruxel grava à parte a hora em que recebeu. Aceita-se até 5 minutos no futuro e 30 dias no passado. Tudo é ordenado por occurred_at.
- Só se acrescenta: um evento não é editado nem excluído. Corrige-se um erro enviando outro evento com o novo resultado.
- Até 16 KB por corpo (request.body e response.body), 4 KB de data e 300 caracteres de summary. O excedente é cortado e o evento fica marcado como truncated. O link deve ser https.
- Não envie números de cartão nem dados pessoais. O que parecer uma credencial (Authorization, token, password, api_key, um formato de chave conhecido) é ocultado antes de gravar, mas essa é a última rede, não a primeira. Os corpos ficam 90 dias; o evento, 13 meses.
Por que um evento é rejeitado
invalid— falta um campo obrigatório, há um campo que não existe ou um valor tem outro formato (a mensagem diz qual).product_not_found— o produto não está no seu catálogo ou está na lixeira.id_conflict— você já informou um evento com esse id e outro conteúdo.occurred_at_future— occurred_at está mais de 5 minutos no futuro.occurred_at_too_old— occurred_at tem mais de 30 dias.system_required— system não foi enviado e a chave não o indica: ela não está ligada a nenhum sistema conectado, e o nome dela não serve como sistema ou é o de um sistema que tem sua própria chave.link_invalid— link não é um endereço https.retry— não foi possível gravar agora (um conflito passageiro no banco): reenvie o MESMO evento.
O que isso move num fluxo
Uma etapa de um fluxo pode ser concluída quando um sistema informa certo evento. A etapa é concluída com o último evento ok desse sistema e tipo:
"done_when": { "event": { "system": "sap", "type": "material.created" } }Se o último evento desse tipo for error, a etapa fica com erro e o percurso para até chegar outro ok. Os eventos started e info vão para o registro, mas não concluem nem param nada.
O percurso de um produto
GET /v1/products/:id/journey retorna, para cada fluxo ativo em que o produto está, o estado de cada etapa e desde quando, o registro do percurso e os eventos informados pelos sistemas. É recalculado a cada pedido.
curl https://bruxel.ai/api/public/v1/products/$PRODUCT_ID/journey \
-H "Authorization: Bearer $BRUXEL_API_KEY"
{
"product_id": "…",
"computed_at": "2026-10-05T18:05:02Z",
"runs": [
{
"flow_slug": "alta-producto",
"flow_name": "Alta de producto",
"status": "in_progress",
"steps": [
{ "key": "maestros", "name": "Datos maestros", "lane": "maestros", "state": "done", "since": "…", "late": false, "out_of_order": false },
{ "key": "sap_alta", "name": "Alta en SAP", "lane": "sap", "state": "done", "since": "2026-10-05T18:04:11Z", "late": false, "out_of_order": false },
{ "key": "tienda", "name": "Publicado", "lane": "tienda", "state": "active", "since": "2026-10-05T18:04:11Z", "late": false, "out_of_order": false }
],
"events": [ { "kind": "step", "step_key": "sap_alta", "to_state": "done", "cause": "event", "event_system": "sap", "event_type": "material.created", … } ],
"events_truncated": false
}
],
"reported": [ { "id": "mw-000123", "system": "sap", "type": "material.created", "status": "ok", … } ],
"reported_truncated": false
}O Bruxel avisa: sua vez, parou, terminou
Inscreva seu endpoint (Configurações → Webhooks, ou seu sistema em Sistemas conectados) em flow.step.ready, flow.run.blocked ou flow.run.completed. Chegam agrupados: um por etapa ou por fluxo cada vez que o motor move produtos, com quantos foram e uma amostra de até 20 com o SKU. Enquanto um não é entregue, o que chega depois não cria outro.
{
"event": "flow.step.ready",
"occurred_at": "2026-10-08T18:04:11Z",
"data": {
"flow": "alta-producto",
"step": "sap_alta",
"lane": "sap",
"system": "sap",
"count": 37,
"products": [ { "product_id": "…", "sku": "BTL-1001" }, … ]
}
}A amostra é uma pista. Ao receber o aviso, leia a lista completa: a fila da etapa (os produtos que estão nela, os que esperam há mais tempo primeiro) ou os percursos parados ou terminados do fluxo, com cursor. Guarde o next_cursor e continue dali na próxima vez.
curl "https://bruxel.ai/api/public/v1/flows/alta-producto/steps/sap_alta/products?limit=200" \
-H "Authorization: Bearer $BRUXEL_API_KEY"
curl "https://bruxel.ai/api/public/v1/flows/alta-producto/runs?status=completed&cursor=$CURSOR" \
-H "Authorization: Bearer $BRUXEL_API_KEY"