Ruptura
/sales/daily
Enviar a venda
A venda de um dia de uma loja até o momento do envio, agregada por código de barras, no contrato bix.sales.daily/v1. É a base da ruptura por não venda e encerra a rebaixa quando o lote rebaixado é vendido.
Envie na frequência que puder: em tempo real (o ideal), a cada intervalo ou uma vez ao dia. Em todas, mande o acumulado do dia com complete: true e o profiles: cada envio substitui o anterior do dia e a ruptura provável é recalculada na hora.
complete: true(padrão) substitui a venda daquele dia, loja esource: reenviar o mesmo lote não duplica, e um lote corrigido corrige.complete: falsesó soma as linhas enviadas, sem substituir o dia; grava a venda, mas não recalcula a ruptura.profilestraz o perfil do dia de cada produto (venda por hora e intervalos sem venda). Sem ele, a ruptura por não venda não é avaliada.- Até 50.000 linhas por lote. Linha inválida é recusada sozinha (
rejected), e o resto grava.
Sem cupom, cliente ou CPF: só a venda agregada.
Corpo da requisição
-
schemastring obrigatório -
Sempre
bix.sales.daily/v1.Exemplo:bix.sales.daily/v1 -
sourcestring obrigatório -
Quem envia: minúsculas, números e
_, de 2 a 30 (ex.:erp). A substituição docompleteé por fonte.Exemplo:erp -
sale_datestring obrigatório -
O dia da venda (AAAA-MM-DD).
Exemplo:2026-11-09 -
locationobject obrigatório -
A loja: um destes campos.
-
integration_codestring -
Código de integração.
Exemplo:0012 -
idinteger -
Id da loja no BIX.
-
cnpjstring -
CNPJ da loja.
-
-
completeboolean -
true(padrão) substitui o dia;falsesó soma as linhas.Exemplo:true -
source_refstring -
Referência sua do lote (arquivo, execução), para rastreio.
-
rowsarray obrigatório -
Uma linha por código de barras e oferta:
product_code,gtin,on_offer,quantity,amount,full_price_amount,receipts(cupons),first_sale_atelast_sale_at(HH:MM). -
profilesarray -
Perfil do dia por código interno:
hourly_qtyehourly_receipts(24 posições, da 0h às 23h),sale_moments,median_gap_minutes,max_gap_minutes,max_gap_start,max_gap_end,store_open_at,store_close_at.
Sobre a resposta
saved: linhas gravadas (as repetidas no lote são somadas);deleted: linhas do dia substituídas.rejected: as linhas recusadas, com a posição emrows(index) e o motivo.
Erros possíveis
| HTTP | code | Quando |
|---|---|---|
| 400 | invalid_parameter | Parâmetro com valor inválido (o detail diz qual). |
| 401 | api_key_expired | A chave passou da data de expiração. |
| 401 | api_key_revoked | A chave foi revogada na Configuração Global › API. |
| 401 | invalid_api_key | A chave não existe neste ambiente ou está errada. |
| 401 | missing_api_key | A chamada veio sem o cabeçalho "Authorization: Bearer <chave>". |
| 403 | insufficient_scope | A chave não tem o acesso que este endpoint exige. |
| 403 | store_not_allowed | A chave está restrita a algumas lojas e uma das pedidas não é delas. |
| 409 | idempotency_key_reused | O Idempotency-Key já foi usado, nas últimas 24 horas, numa chamada com outro corpo. |
| 429 | rate_limited | Limite de chamadas por minuto da chave atingido. Respeite o Retry-After. |
| 500 | internal_error | Erro interno. Tente de novo; se persistir, fale com o suporte. |
curl -X POST "https://demonstracao.appbix.com.br/external-api/v1/sales/daily" \
-H "Authorization: Bearer $BIX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"schema": "bix.sales.daily/v1", "source": "erp", "sale_date": "2026-11-09", "location": {"integration_code": "0012"}, "complete": true, "rows": [{"product_code": "1001", "gtin": "7891234567890", "on_offer": false, "quantity": 44, "amount": 1227.6, "full_price_amount": 1227.6, "receipts": 39, "first_sale_at": "08:12", "last_sale_at": "21:40"}], "profiles": [{"product_code": "1001", "quantity": 44, "receipts": 39, "hourly_qty": [0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 3, 2, 3, 4, 5, 6, 4, 2, 1, 0, 0, 0], "hourly_receipts": [0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 5, 3, 2, 3, 4, 5, 6, 4, 2, 1, 0, 0, 0], "sale_moments": 39, "median_gap_minutes": 18, "max_gap_minutes": 95, "max_gap_start": "14:10", "max_gap_end": "15:45", "store_open_at": "07:02", "store_close_at": "21:55"}]}'
import os
import uuid
import requests
payload = {
"schema": "bix.sales.daily/v1",
"source": "erp",
"sale_date": "2026-11-09",
"location": {
"integration_code": "0012"
},
"complete": true,
"rows": [
{
"product_code": "1001",
"gtin": "7891234567890",
"on_offer": false,
"quantity": 44,
"amount": 1227.6,
"full_price_amount": 1227.6,
"receipts": 39,
"first_sale_at": "08:12",
"last_sale_at": "21:40"
}
],
"profiles": [
{
"product_code": "1001",
"quantity": 44,
"receipts": 39,
"hourly_qty": [
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
4,
5,
3,
2,
3,
4,
5,
6,
4,
2,
1,
0,
0,
0
],
"hourly_receipts": [
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
4,
5,
3,
2,
3,
4,
5,
6,
4,
2,
1,
0,
0,
0
],
"sale_moments": 39,
"median_gap_minutes": 18,
"max_gap_minutes": 95,
"max_gap_start": "14:10",
"max_gap_end": "15:45",
"store_open_at": "07:02",
"store_close_at": "21:55"
}
]
}
response = requests.post(
"https://demonstracao.appbix.com.br/external-api/v1/sales/daily",
json=payload,
headers={
"Authorization": f"Bearer {os.environ['BIX_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
timeout=60,
)
response.raise_for_status()
for item in response.json()["results"]:
if item["status"] == "error":
print(item["index"], item["code"], item["detail"])
const payload = {
"schema": "bix.sales.daily/v1",
"source": "erp",
"sale_date": "2026-11-09",
"location": {
"integration_code": "0012"
},
"complete": true,
"rows": [
{
"product_code": "1001",
"gtin": "7891234567890",
"on_offer": false,
"quantity": 44,
"amount": 1227.6,
"full_price_amount": 1227.6,
"receipts": 39,
"first_sale_at": "08:12",
"last_sale_at": "21:40"
}
],
"profiles": [
{
"product_code": "1001",
"quantity": 44,
"receipts": 39,
"hourly_qty": [
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
4,
5,
3,
2,
3,
4,
5,
6,
4,
2,
1,
0,
0,
0
],
"hourly_receipts": [
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
4,
5,
3,
2,
3,
4,
5,
6,
4,
2,
1,
0,
0,
0
],
"sale_moments": 39,
"median_gap_minutes": 18,
"max_gap_minutes": 95,
"max_gap_start": "14:10",
"max_gap_end": "15:45",
"store_open_at": "07:02",
"store_close_at": "21:55"
}
]
};
const response = await fetch("https://demonstracao.appbix.com.br/external-api/v1/sales/daily", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BIX_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify(payload),
});
const body = await response.json();
body.results.filter((r) => r.status === "error").forEach((r) => console.log(r));
{
"schema": "bix.sales.daily/v1",
"source": "erp",
"sale_date": "2026-11-09",
"location": {
"integration_code": "0012"
},
"complete": true,
"rows": [
{
"product_code": "1001",
"gtin": "7891234567890",
"on_offer": false,
"quantity": 44,
"amount": 1227.6,
"full_price_amount": 1227.6,
"receipts": 39,
"first_sale_at": "08:12",
"last_sale_at": "21:40"
}
],
"profiles": [
{
"product_code": "1001",
"quantity": 44,
"receipts": 39,
"hourly_qty": [
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
4,
5,
3,
2,
3,
4,
5,
6,
4,
2,
1,
0,
0,
0
],
"hourly_receipts": [
0,
0,
0,
0,
0,
0,
0,
0,
2,
3,
4,
5,
3,
2,
3,
4,
5,
6,
4,
2,
1,
0,
0,
0
],
"sale_moments": 39,
"median_gap_minutes": 18,
"max_gap_minutes": 95,
"max_gap_start": "14:10",
"max_gap_end": "15:45",
"store_open_at": "07:02",
"store_close_at": "21:55"
}
]
}
{
"saved": 1,
"deleted": 0,
"rejected": [
{
"index": 3,
"error": "quantity inválido"
}
],
"profiles": 1,
"sale_date": "2026-11-09",
"source": "erp",
"complete": true,
"store": {
"id": 12,
"code": "0012",
"name": "Loja Centro"
}
}
/rupture/items
Itens auditados
Cada produto das tarefas de ruptura e o que a loja encontrou na gôndola: rupture (faltava), no_rupture (estava lá), other ou not_here (o produto não fica mais naquele lugar). Item ainda não auditado vem com answer: null.
Traz também o saldo da loja e do CD congelados quando a tarefa nasceu, o motivo que o app mostrou, a origem da falta (operacional, logistica, comercial) e quando o produto foi reposto. Use updated_since para sincronizar.
Parâmetros de consulta
-
store_codestring · lista -
Código de integração da loja.
Separe por vírgula, até 100 valores. Exemplo:0012 -
answerstring · lista -
rupture,no_rupture,otherounot_here.Separe por vírgula, até 100 valores. Exemplo:rupture -
task_idinteger · lista -
Id da tarefa.
Separe por vírgula, até 100 valores. Exemplo:9120 -
answered_sincestring (data-hora) -
Respondidos a partir desta data/hora.
Exemplo:2026-11-10T00:00:00-03:00 -
updated_sincestring (data-hora) -
Só registros alterados a partir desta data/hora (ISO 8601).
Exemplo:2026-11-10T06:00:00-03:00 -
pageinteger -
Página, começando em 1.
Padrão:1Exemplo:1 -
page_sizeinteger -
Itens por página. Acima de 100 a chamada é recusada com
invalid_parameter(não é cortada em silêncio).Padrão:50Máximo:100Exemplo:50
Sobre a resposta
found_at: o endereço onde o produto foi achado, quando a tarefa usa o WMS.replenished_at: quando a tarefa de reposição gerada pela ruptura foi concluída.
Erros possíveis
| HTTP | code | Quando |
|---|---|---|
| 401 | api_key_expired | A chave passou da data de expiração. |
| 401 | api_key_revoked | A chave foi revogada na Configuração Global › API. |
| 401 | invalid_api_key | A chave não existe neste ambiente ou está errada. |
| 401 | missing_api_key | A chamada veio sem o cabeçalho "Authorization: Bearer <chave>". |
| 403 | insufficient_scope | A chave não tem o acesso que este endpoint exige. |
| 403 | module_disabled | O cliente não tem o módulo deste endpoint habilitado. |
| 403 | store_not_allowed | A chave está restrita a algumas lojas e uma das pedidas não é delas. |
| 429 | rate_limited | Limite de chamadas por minuto da chave atingido. Respeite o Retry-After. |
| 500 | internal_error | Erro interno. Tente de novo; se persistir, fale com o suporte. |
curl -X GET "https://demonstracao.appbix.com.br/external-api/v1/rupture/items?store_code=0012&answer=rupture&page_size=100" \
-H "Authorization: Bearer $BIX_API_KEY"
import os
import requests
response = requests.request(
"GET",
"https://demonstracao.appbix.com.br/external-api/v1/rupture/items?store_code=0012&answer=rupture&page_size=100",
headers={"Authorization": f"Bearer {os.environ['BIX_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
print(response.json())
const response = await fetch(
"https://demonstracao.appbix.com.br/external-api/v1/rupture/items?store_code=0012&answer=rupture&page_size=100",
{ method: "GET", headers: { Authorization: `Bearer ${process.env.BIX_API_KEY}` } }
);
if (!response.ok) throw new Error((await response.json()).code);
console.log(await response.json());
{
"data": [
{
"id": 77120,
"task": {
"id": 9120,
"status": "finalizado",
"date": "2026-11-10"
},
"store": {
"id": 12,
"code": "0012",
"name": "Loja Centro"
},
"product": {
"internal_code": "1001",
"description": "ARROZ TIPO 1 5KG"
},
"triggers": [
"sales"
],
"reason": "Sem venda desde 14:10 (normal: a cada 18 min)",
"curve": "A",
"store_qty": 48.0,
"cd_qty": 600.0,
"unit_price": 27.9,
"answer": "rupture",
"rupture_origin": "operacional",
"answered_at": "2026-11-10T16:02:00-03:00",
"found_at": "05-003-02",
"replenished_at": "2026-11-10T16:40:00-03:00",
"updated_at": "2026-11-10T16:40:00-03:00"
}
],
"pagination": {
"page": 1,
"page_size": 50,
"total_items": 1,
"total_pages": 1,
"has_next": false
}
}
/rupture/signals
Rupturas prováveis
O que a venda aponta como ruptura provável, antes de alguém ir à gôndola: gap (o produto parou de vender por muito mais tempo que o normal no dia) ou no_sale (dias seguidos sem venda, improváveis para o giro dele). stock_qty é o saldo da loja no fim do dia: positivo indica ruptura de gôndola (há estoque, mas não está saindo).
Quando alguém confere na loja, check_result diz o que achou: exposed, not_exposed ou other.
Parâmetros de consulta
-
store_codestring · lista -
Código de integração da loja.
Separe por vírgula, até 100 valores. Exemplo:0012 -
sale_date_fromstring -
Dia avaliado a partir de (AAAA-MM-DD).
Exemplo:2026-11-01 -
sale_date_tostring -
Dia avaliado até (AAAA-MM-DD).
Exemplo:2026-11-09 -
rulestring · lista -
gapouno_sale.Separe por vírgula, até 100 valores. Exemplo:gap -
checkedboolean -
true: só os conferidos;false: só os não conferidos.Exemplo:false -
updated_sincestring (data-hora) -
Só registros alterados a partir desta data/hora (ISO 8601).
Exemplo:2026-11-10T06:00:00-03:00 -
pageinteger -
Página, começando em 1.
Padrão:1Exemplo:1 -
page_sizeinteger -
Itens por página. Acima de 100 a chamada é recusada com
invalid_parameter(não é cortada em silêncio).Padrão:50Máximo:100Exemplo:50
Sobre a resposta
Os campos
gap_*valem para a regragap;days_without_saleeexpected_days, parano_sale. Os outros vêmnull.
Erros possíveis
| HTTP | code | Quando |
|---|---|---|
| 401 | api_key_expired | A chave passou da data de expiração. |
| 401 | api_key_revoked | A chave foi revogada na Configuração Global › API. |
| 401 | invalid_api_key | A chave não existe neste ambiente ou está errada. |
| 401 | missing_api_key | A chamada veio sem o cabeçalho "Authorization: Bearer <chave>". |
| 403 | insufficient_scope | A chave não tem o acesso que este endpoint exige. |
| 403 | module_disabled | O cliente não tem o módulo deste endpoint habilitado. |
| 403 | store_not_allowed | A chave está restrita a algumas lojas e uma das pedidas não é delas. |
| 429 | rate_limited | Limite de chamadas por minuto da chave atingido. Respeite o Retry-After. |
| 500 | internal_error | Erro interno. Tente de novo; se persistir, fale com o suporte. |
curl -X GET "https://demonstracao.appbix.com.br/external-api/v1/rupture/signals?store_code=0012&sale_date_from=2026-11-01&page_size=100" \
-H "Authorization: Bearer $BIX_API_KEY"
import os
import requests
response = requests.request(
"GET",
"https://demonstracao.appbix.com.br/external-api/v1/rupture/signals?store_code=0012&sale_date_from=2026-11-01&page_size=100",
headers={"Authorization": f"Bearer {os.environ['BIX_API_KEY']}"},
timeout=30,
)
response.raise_for_status()
print(response.json())
const response = await fetch(
"https://demonstracao.appbix.com.br/external-api/v1/rupture/signals?store_code=0012&sale_date_from=2026-11-01&page_size=100",
{ method: "GET", headers: { Authorization: `Bearer ${process.env.BIX_API_KEY}` } }
);
if (!response.ok) throw new Error((await response.json()).code);
console.log(await response.json());
{
"data": [
{
"id": 3301,
"store": {
"id": 12,
"code": "0012",
"name": "Loja Centro"
},
"product_code": "1001",
"sale_date": "2026-11-09",
"rule": "gap",
"gap_start": "14:10",
"gap_end": "21:40",
"gap_minutes": 450,
"baseline_minutes": 18,
"days_without_sale": null,
"expected_days": null,
"last_sale_date": "2026-11-09",
"stock_qty": 48.0,
"checked_at": null,
"check_result": null,
"updated_at": "2026-11-10T06:30:00-03:00"
}
],
"pagination": {
"page": 1,
"page_size": 50,
"total_items": 1,
"total_pages": 1,
"has_next": false
}
}