Developers

Ruptura

POST /sales/daily

Enviar a venda

Escopo sales.write

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 e source: reenviar o mesmo lote não duplica, e um lote corrigido corrige.
  • complete: false só soma as linhas enviadas, sem substituir o dia; grava a venda, mas não recalcula a ruptura.
  • profiles traz 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

schema string obrigatório

Sempre bix.sales.daily/v1.

Exemplo: bix.sales.daily/v1
source string obrigatório

Quem envia: minúsculas, números e _, de 2 a 30 (ex.: erp). A substituição do complete é por fonte.

Exemplo: erp
sale_date string obrigatório

O dia da venda (AAAA-MM-DD).

Exemplo: 2026-11-09
location object obrigatório

A loja: um destes campos.

integration_code string

Código de integração.

Exemplo: 0012
id integer

Id da loja no BIX.

cnpj string

CNPJ da loja.

complete boolean

true (padrão) substitui o dia; false só soma as linhas.

Exemplo: true
source_ref string

Referência sua do lote (arquivo, execução), para rastreio.

rows array 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_at e last_sale_at (HH:MM).

profiles array

Perfil do dia por código interno: hourly_qty e hourly_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.

Aceita o cabeçalho Idempotency-Key: repetir a chamada com a mesma chave, em 24 horas, devolve a resposta da primeira sem gravar de novo. Ver Envio em lote e idempotência.

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 em rows (index) e o motivo.

Erros possíveis

HTTPcodeQuando
400invalid_parameterParâmetro com valor inválido (o detail diz qual).
401api_key_expiredA chave passou da data de expiração.
401api_key_revokedA chave foi revogada na Configuração Global › API.
401invalid_api_keyA chave não existe neste ambiente ou está errada.
401missing_api_keyA chamada veio sem o cabeçalho "Authorization: Bearer <chave>".
403insufficient_scopeA chave não tem o acesso que este endpoint exige.
403store_not_allowedA chave está restrita a algumas lojas e uma das pedidas não é delas.
409idempotency_key_reusedO Idempotency-Key já foi usado, nas últimas 24 horas, numa chamada com outro corpo.
429rate_limitedLimite de chamadas por minuto da chave atingido. Respeite o Retry-After.
500internal_errorErro 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"}]}'
Corpo da requisição
{
  "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"
    }
  ]
}
200 Resposta
{
  "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"
  }
}
GET /rupture/items

Itens auditados

Escopo rupture.read

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_code string · lista

Código de integração da loja.

Separe por vírgula, até 100 valores. Exemplo: 0012
answer string · lista

rupture, no_rupture, other ou not_here.

Separe por vírgula, até 100 valores. Exemplo: rupture
task_id integer · lista

Id da tarefa.

Separe por vírgula, até 100 valores. Exemplo: 9120
answered_since string (data-hora)

Respondidos a partir desta data/hora.

Exemplo: 2026-11-10T00:00:00-03:00
updated_since string (data-hora)

Só registros alterados a partir desta data/hora (ISO 8601).

Exemplo: 2026-11-10T06:00:00-03:00
page integer

Página, começando em 1.

Padrão: 1 Exemplo: 1
page_size integer

Itens por página. Acima de 100 a chamada é recusada com invalid_parameter (não é cortada em silêncio).

Padrão: 50 Máximo: 100 Exemplo: 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

HTTPcodeQuando
401api_key_expiredA chave passou da data de expiração.
401api_key_revokedA chave foi revogada na Configuração Global › API.
401invalid_api_keyA chave não existe neste ambiente ou está errada.
401missing_api_keyA chamada veio sem o cabeçalho "Authorization: Bearer <chave>".
403insufficient_scopeA chave não tem o acesso que este endpoint exige.
403module_disabledO cliente não tem o módulo deste endpoint habilitado.
403store_not_allowedA chave está restrita a algumas lojas e uma das pedidas não é delas.
429rate_limitedLimite de chamadas por minuto da chave atingido. Respeite o Retry-After.
500internal_errorErro 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"
200 Resposta
{
  "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
  }
}
GET /rupture/signals

Rupturas prováveis

Escopo rupture.read

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_code string · lista

Código de integração da loja.

Separe por vírgula, até 100 valores. Exemplo: 0012
sale_date_from string

Dia avaliado a partir de (AAAA-MM-DD).

Exemplo: 2026-11-01
sale_date_to string

Dia avaliado até (AAAA-MM-DD).

Exemplo: 2026-11-09
rule string · lista

gap ou no_sale.

Separe por vírgula, até 100 valores. Exemplo: gap
checked boolean

true: só os conferidos; false: só os não conferidos.

Exemplo: false
updated_since string (data-hora)

Só registros alterados a partir desta data/hora (ISO 8601).

Exemplo: 2026-11-10T06:00:00-03:00
page integer

Página, começando em 1.

Padrão: 1 Exemplo: 1
page_size integer

Itens por página. Acima de 100 a chamada é recusada com invalid_parameter (não é cortada em silêncio).

Padrão: 50 Máximo: 100 Exemplo: 50

Sobre a resposta

  • Os campos gap_* valem para a regra gap; days_without_sale e expected_days, para no_sale. Os outros vêm null.

Erros possíveis

HTTPcodeQuando
401api_key_expiredA chave passou da data de expiração.
401api_key_revokedA chave foi revogada na Configuração Global › API.
401invalid_api_keyA chave não existe neste ambiente ou está errada.
401missing_api_keyA chamada veio sem o cabeçalho "Authorization: Bearer <chave>".
403insufficient_scopeA chave não tem o acesso que este endpoint exige.
403module_disabledO cliente não tem o módulo deste endpoint habilitado.
403store_not_allowedA chave está restrita a algumas lojas e uma das pedidas não é delas.
429rate_limitedLimite de chamadas por minuto da chave atingido. Respeite o Retry-After.
500internal_errorErro 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"
200 Resposta
{
  "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
  }
}