Pular para o conteúdo principal

Integração de dados

Visão geral

O Sipru é um copiloto de vendas para o balconista: durante o atendimento, ele sugere substitutos, cross-sell e upsell, e recompensa o vendedor em Sipru Points pelos produtos de maior margem e giro.

Este guia cobre o envio de dados — como o seu catálogo, as suas lojas e o seu histórico de venda chegam até a Sipru. É o que alimenta as recomendações: sem dado não há o que sugerir.

Para a integração em que o vendedor sai da cotação do seu ERP e cai no catálogo Sipru já autenticado, veja Integração ERP.

O que é preciso antes de começar

O onboarding com o time da Sipru entrega três coisas, e nenhuma delas está nesta documentação porque são específicas do seu parceiro:

  1. o bucket de destino;
  2. a Service Account com permissão de escrita nele;
  3. o seu identificador de parceiro, que nomeia a sua pasta.

Ver Suporte para iniciar.

Arquitetura

Os dados do parceiro chegam por quatro caminhos. Todos convergem para o mesmo pipeline de processamento e enriquecimento.

Os quatro caminhos

Arquivo CSV no Cloud Storage. Você deposita arquivos em um bucket dedicado e eles são processados assim que chegam. É o caminho padrão e o mais usado.

Envio por arquivo CSV · Dicionário de dados

Conector dedicado. Se você não tem equipe para montar a exportação, o time da Sipru constrói e opera um extrator ligado direto ao seu sistema.

Conector dedicado

API REST. Envio e consulta por HTTP, em tempo real, direto do seu ERP.

Integração via API RESTainda não disponível

Webhook. Grandes volumes em tempo real, com persistência automática e particionada no Cloud Storage.

Integração via Webhookainda não disponível

Dois dos quatro ainda não existem

A API REST e o Webhook estão documentados porque o desenho está definido, mas nenhum endpoint deles responde hoje. Cada uma dessas páginas repete o aviso no topo.

Qual método escolher

Se você…usedisponível
já consegue exportar CSV do seu sistemaarquivo CSVsim
precisa de carga completa periódicaarquivo CSVsim
exporta em outro formato, ou só tem o bancoconector dedicadosim
não tem equipe técnica disponívelconector dedicadosim
quer atualização em tempo real via HTTPAPI RESTnão
tem grande volume de eventos em tempo realwebhooknão
Você não precisa renomear suas colunas

O dicionário desta seção descreve os nomes canônicos que o Sipru usa internamente. Se o seu ERP exporta com outros nomes, o time configura um mapeamento de colunas específico para o seu parceiro no momento do onboarding — você manda o CSV do jeito que o seu sistema já gera. O que não pode faltar é o dado; o nome da coluna a gente resolve.

Estrutura de pastas

Você deposita arquivos no bucket do Cloud Storage entregue no onboarding, e eles são processados assim que chegam. Não há chamada de API, agendamento nem confirmação a fazer.

Formato do arquivo

  • CSV em UTF-8, com a primeira linha trazendo o cabeçalho das colunas.
  • Uma entidade por arquivo — não misture lojas e produtos no mesmo CSV.

O que o validador aceita sem você precisar ajustar

Boa parte do trabalho de "arrumar o CSV" é desnecessária. O validador é tolerante nestes pontos:

Separadorvírgula, ponto e vírgula, tabulação ou barra vertical — detectado sozinho pelo cabeçalho
Decimal47.90 e 47,90 valem o mesmo
BOMum BOM no início do arquivo é ignorado; não precisa removê-lo
Booleanostrue/false, 1/0, yes/no, sim/não — maiúsculas ou minúsculas
Colunas extrasignoradas; você não precisa recortar o seu export

Onde ele é exigente

Colunas obrigatóriasprecisam existir no cabeçalho, com o nome canônico ou o mapeado para você
Campos dataestritamente YYYY-MM-DD
Campos data e horaqualquer formato ISO reconhecível
Nome do arquivoprecisa começar pela entidade — ver abaixo

O nome do arquivo importa

A entidade é deduzida do nome do arquivo, não da pasta. O nome precisa começar pelo nome da entidade, seguido de _, -, ou nada:

Nome do arquivoResultado
orders_22052026.csvreconhecido como orders
produtos-2026.csvreconhecido como produtos
inventory.csvreconhecido como inventory
posicao_estoque.csvnão reconhecido — o arquivo é ignorado

Um arquivo cujo nome não comece por uma das entidades não é processado, e não gera erro visível para você. Se um envio "sumiu", o nome é o primeiro lugar para olhar.

As entidades são lojas, produtos, precos, sellout, orders, inventory e campaigns — ver Dicionário de dados.

Onde depositar

Dentro do bucket, a convenção é uma pasta por parceiro e, se você atende mais de uma rede, uma subpasta por rede:

{seu_parceiro}/
└── {sua_rede}/
├── lojas_20260413.csv
├── produtos_20260413.csv
├── sellout_20260413.csv
├── orders_20260413.csv
├── inventory_20260413.csv
└── campaigns_20260413.csv

A data no nome deve ser a do período dos dados, não a do envio — é ela que o time usa para investigar uma carga.

O caminho é convenção, e serve para você se organizar. Quem determina a entidade é sempre o nome do arquivo.

Envio manual via WinSCP

Para quem prefere arrastar e soltar em vez de automatizar. Qualquer cliente que fale com o Cloud Storage serve — Cyberduck ou o próprio console do Google Cloud —, mas o WinSCP é o mais usado pelos parceiros.

1. Instale o WinSCP. Baixe em winscp.net.

2. Configure o protocolo. Na tela de login, mude o protocolo de arquivo para Amazon S3 — é compatível com o Cloud Storage.

3. Defina o host. Preencha com storage.googleapis.com.

4. Insira as credenciais. O Access Key ID e a Secret Key são entregues pelo time no onboarding.

5. Configure o diretório remoto. Em Avançado → Ambientes → Diretórios, preencha "Diretório Remoto" com {bucket}/{seu_parceiro}.

6. Salve, conecte e envie. Arraste os CSV para a pasta da rede correspondente.

Vale a mesma regra de nome de arquivo: ele precisa começar pela entidade.

Envio via SDK Python

Autentique com a Service Account entregue no onboarding:

export GOOGLE_APPLICATION_CREDENTIALS="$HOME/credenciais-sipru.json"
pip install google-cloud-storage
from datetime import datetime
from pathlib import Path

from google.cloud import storage

BUCKET = "..." # entregue no onboarding
PARCEIRO = "..." # seu identificador de parceiro
REDE = "..." # a rede/cliente a que os dados pertencem
ENTIDADE = "orders" # lojas | produtos | sellout | orders | inventory | campaigns

data = datetime.now().strftime("%Y%m%d")
origem = Path(f"dados/{ENTIDADE}_{data}.csv")
destino = f"{PARCEIRO}/{REDE}/{ENTIDADE}_{data}.csv"

bucket = storage.Client().bucket(BUCKET)
bucket.blob(destino).upload_from_filename(str(origem))

print(f"Enviado: gs://{BUCKET}/{destino}")

Dicionário de dados

Abaixo estão os schemas das entidades aceitas. Todos os arquivos devem ser enviados no formato CSV com encoding UTF-8 e separador vírgula.

Os nomes das colunas são combinados no onboarding

A ingestão usa nomes canônicos próprios e aceita um mapeamento de colunas por parceiro. Confirme com o time quais nomes valem para você antes da primeira carga — você não precisa mudar o seu export, mas o mapeamento precisa existir.

Lojas

CampoTipoObrig.DescriçãoExemplo
location_nameTextoSimNome/descrição da lojaLoja Shopping SP
location_codeTextoSimCódigo único (CNPJ ou ID comercial)S74
is_activeBooleanoSimStatus da loja (true / false)true
categoryTextoNãoRamo de atuaçãoAlimentação
cepNuméricoNãoCEP da loja81000-000
ufTextoNãoUF do estadoSP
cityTextoNãoCidadeSão Paulo
segmentTextoNãoSegmento da lojaAlimentação
channelTextoNãoCanal de vendas (varejo, atacado)Varejo

Produtos

CampoTipoObrig.DescriçãoExemplo
product_nameTextoSimNome/descrição do produtoBateria p/Celular
product_codeTextoSimCódigo único (SKU)P123
is_activeBooleanoSimStatus do produto (true / false)true
categoryTextoSimCategoriaSmartphones
sub_categoryTextoNãoSubcategoriaAndroid
master_productTextoNãoProduto principal/agrupadorGalaxy
multipleNuméricoNãoMúltiplos de venda (padrão: 1)5.0
ean_codeTextoNãoCódigo de barras internacional (GTIN/EAN)7891000001234
ncm_codeTextoNãoNomenclatura Comum do Mercosul (8 dígitos)2523.29.10
base_priceDecimalNãoPreço base líquido unitário do produto — referência única para todas as lojas58.90

Preços

CampoTipoObrig.DescriçãoExemplo
location_codeTextoSimCódigo da loja (deve existir em Lojas)L01
product_codeTextoSimCódigo do produto (deve existir em Produtos)P123
price_nameTextoSimNome da condição comercial. Identifica a linha e é referenciado em OrdersATACADO
unit_cost_priceDecimalSimCusto unitário do produto (CMV) associado a esta condição25.00
unit_sale_priceDecimalSimValor líquido unitário de venda desta condição47.90

Inventory

Posição de estoque. Idealmente o fechamento de D-1.

CampoTipoObrig.DescriçãoExemplo
location_codeTextoSimCódigo da loja (deve existir em Lojas)L01
product_codeTextoSimCódigo do produto (deve existir em Produtos)P123
dateDataSimData de fechamento do estoque (YYYY-MM-DD)2026-04-14
quantityNuméricoSimQuantidade em estoque na data60.0

Orders

Cada item do pedido é um registro individual.

CampoTipoObrig.DescriçãoExemplo
order_codeTextoSimCódigo único do pedidoPED-20260414-001
location_codeTextoSimCódigo da loja (deve existir em Lojas)L01
product_codeTextoSimCódigo do produto (deve existir em Produtos)P123
dateDataSimData do pedido (YYYY-MM-DD)2026-04-14
quantityNuméricoSimQuantidade solicitada no pedido15.0
unit_sale_priceDecimalSimValor líquido unitário de venda do item (já deduzidos descontos do item e impostos de saída)40.00
unit_cost_priceDecimalSimCusto unitário do produto em estoque (CMV) associado a este pedido25.00
order_statusTextoSimStatus do pedido (pending / confirmed / shipped / delivered / cancelled)confirmed
price_nameTextoNãoCondição comercial aplicada no item (deve existir em Preços)ATACADO
customer_codeTextoNãoCódigo do cliente que fez o pedidoCLI-0472
delivery_dateDataNãoData prevista de entrega (YYYY-MM-DD)2026-04-21
freight_priceDecimalNãoValor total do frete cobrado ou atribuído ao pedido150.00
discount_priceDecimalNãoDesconto global aplicado no fechamento do carrinho (valor rateado entre os itens)50.00
notesTextoNãoObservações adicionais do pedidoEntrega urgente

Sellout

Venda unitária — o que saiu, quando e de qual loja. É o insumo dos algoritmos de substituto, cross-sell e upsell.

CampoTipoObrig.DescriçãoExemplo
location_codeTextoSimCódigo da loja (deve existir em Lojas)L01
product_codeTextoSimCódigo do produto (deve existir em Produtos)P123
dateDataSimData da venda (YYYY-MM-DD)2026-04-14
quantityNuméricoSimQuantidade vendida12.0
gross_amountDecimalNãoValor bruto da venda418.80

Campaigns

CampoTipoObrig.DescriçãoExemplo
campaign_idTextoSimCódigo único da campanhaCAMP-2026-04
nameTextoSimNome da campanhaSemana do Cimento
starts_atData e horaNãoInício da campanha2026-04-14T00:00:00Z
ends_atData e horaNãoFim da campanha2026-04-21T23:59:59Z
budgetDecimalNãoVerba da campanha15000.00

Visão geral da API REST

A API REST ainda não existe

Nenhum endpoint desta seção responde hoje — não há API de ingestão em nenhum ambiente. Para integrar agora, use Cloud Storage ou conector dedicado.

A API REST permite que parceiros enviem lojas, produtos, preços, pedidos e estoque em tempo real, direto do ERP ou do sistema interno.

Base URL

https://api.sipru.ai/v1

Todas as requisições usam HTTPS; requisições HTTP são rejeitadas. O Content-Type esperado é application/json e o encoding é UTF-8.

Se a API REST é bloqueante para o seu caso, diga a sipru@sipru.ai — saber quem depende dela define a ordem de construção.

Autenticação da API

Autenticação por API Key no header de cada requisição. As credenciais são fornecidas pela equipe de integração durante o onboarding.

Header de autenticação

Authorization: Bearer {sua_api_key}
Content-Type: application/json
X-Partner-ID: {seu_partner_id}

Exemplo com cURL

curl -X POST https://api.sipru.ai/v1/locations \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-H "X-Partner-ID: {seu_partner_id}" \
-d '{ "data": [] }'

Exemplo com Python

import requests

BASE_URL = "https://api.sipru.ai/v1"
HEADERS = {
"Authorization": "Bearer sk_live_...",
"Content-Type": "application/json",
"X-Partner-ID": "{seu_partner_id}",
}

response = requests.post(f"{BASE_URL}/locations", headers=HEADERS, json={"data": []})
print(response.json())

Endpoints

Cada entidade tem endpoint próprio para envio e consulta. Todos aceitam envio unitário ou em lote — um array de objetos no campo data.

MétodoEndpointO que faz
POST/v1/locationsEnvia lojas
POST/v1/productsEnvia produtos
POST/v1/pricesEnvia tabela de preços
POST/v1/inventoryEnvia posição de estoque
POST/v1/ordersEnvia pedidos e itens
POST/v1/campaignsCria ou atualiza campanhas
GET/v1/{entidade}Consulta o que foi enviado

Lojas (locations)

{
"data": [
{
"location_name": "Loja Shopping São Paulo",
"location_code": "S74",
"is_active": true,
"category": "Material de construção",
"cep": "81000-000",
"uf": "SP",
"city": "São Paulo",
"segment": "Varejo",
"channel": "Varejo"
}
]
}

Produtos (products)

{
"data": [
{
"product_name": "Argamassa AC-III 20kg",
"product_code": "P123",
"is_active": true,
"category": "Argamassas",
"sub_category": "Assentamento",
"master_product": "AC-III",
"multiple": 5.0,
"ean_code": "7891000001234",
"base_price": 34.90,
"ncm_code": "3824.50.00"
}
]
}

Preços (prices)

Tabela de preço por loja e condição comercial. Os valores são unitários.

{
"data": [
{
"location_code": "L01",
"product_code": "P123",
"price_name": "ATACADO",
"unit_cost_price": 25.00,
"unit_sale_price": 47.90
}
]
}

Estoque (inventory)

Posição de estoque, idealmente o fechamento de D-1.

{
"data": [
{ "location_code": "L01", "product_code": "P123", "date": "2026-04-14", "quantity": 60.0 }
]
}

Pedidos (orders)

Cada item do pedido é um registro individual.

{
"data": [
{
"order_code": "PED-20260414-001",
"location_code": "L01",
"product_code": "P123",
"date": "2026-04-14",
"quantity": 15.0,
"unit_sale_price": 40.00,
"unit_cost_price": 25.00,
"order_status": "confirmed",
"price_name": "ATACADO",
"customer_code": "CLI-0472",
"delivery_date": "2026-04-21",
"freight_price": 150.00,
"discount_price": 50.00,
"notes": "Entrega urgente"
}
]
}

Consultas (GET)

Também é possível consultar o status dos dados enviados:

GET /v1/locations
GET /v1/products?category=Argamassas
GET /v1/prices?location_code=L01
GET /v1/inventory?location_code=L01
GET /v1/orders?date_from=2026-04-01&order_status=confirmed

Paginação. Respostas com mais de 100 registros são paginadas. Use page e per_page (máximo 500). O header X-Total-Count indica o total de registros.

Erros e respostas

Resposta de sucesso

{
"status": "success",
"message": "3 registros processados com sucesso.",
"processed": 3,
"errors": 0,
"request_id": "req_8f2a4b6c..."
}

Resposta de erro

{
"status": "error",
"message": "Validação falhou em 1 registro.",
"processed": 2,
"errors": 1,
"details": [
{
"index": 2,
"field": "date",
"code": "INVALID_FORMAT",
"message": "Data deve estar no formato YYYY-MM-DD."
}
]
}

Códigos de status HTTP

CódigoSignificado
200OK — requisição processada com sucesso
201Created — registros criados com sucesso
400Bad Request — payload inválido ou campos obrigatórios ausentes
401Unauthorized — API Key inválida ou ausente
403Forbidden — sem permissão para o recurso solicitado
404Not Found — endpoint ou recurso não encontrado
422Unprocessable Entity — dados válidos, mas com erro semântico
429Too Many Requests — rate limit excedido (aguarde 60 s)
500Internal Server Error — erro interno, contate o suporte

O limite de referência é de 100 requisições por minuto por parceiro. Para cargas grandes, prefira envio em lote ou Cloud Storage.

Conector dedicado

Nem todo parceiro tem equipe disponível para montar uma exportação. No conector dedicado, o time da Sipru constrói, opera e mantém um extrator ligado direto ao seu sistema — você não escreve código.

Quando faz sentido

  • Você não tem equipe técnica livre para desenvolver e manter a integração.
  • Seu sistema não oferece exportação padrão nem API.
  • Trata-se de ERP proprietário, base SQL legada, ou dados que hoje vivem em planilha.

O que a Sipru assume

O extrator é escrito para a sua fonte específica — banco SQL, API interna, plataforma de e-commerce — e roda na infraestrutura da Sipru, em agendamento combinado com você. A saída alimenta o mesmo pipeline do envio por CSV, com o mesmo dicionário de dados.

Já existem conectores em produção lendo bancos de parceiros por rede privada, quando o acesso direto não é possível pela internet.

O que fica do seu lado

Três coisas, e só elas:

  1. Acesso de leitura à fonte — usuário de banco, credencial de API, ou o caminho combinado.
  2. Uma pessoa de referência que saiba explicar o modelo de dados do seu sistema: onde está a venda, o que é loja, qual campo é o SKU.
  3. Aval para a conectividade — se o acesso exige rede privada ou liberação de IP, o time propõe o desenho e você aprova.

O levantamento do seu modelo de dados costuma ser a parte mais longa, e depende mais da disponibilidade dessa pessoa de referência do que do desenvolvimento em si.

Como é o onboarding

1. Levantamento técnico. O time analisa o seu sistema e identifica onde estão os dados, em que formato e com que frequência mudam. É a etapa mais longa, e a que mais depende de você — ver a pessoa de referência acima.

2. Desenvolvimento do conector. O time constrói o extrator e a transformação para o formato do dicionário de dados.

3. Validação conjunta. Testes com dados reais, com você junto, para conferir integridade e consistência antes de valer.

4. Ativação e monitoramento. O conector entra em produção monitorado pelo time, que é avisado quando uma extração falha.

O desenvolvimento, a manutenção e a operação do conector são custeados pela Sipru. Do seu lado ficam apenas os três itens acima.

Para começar, escreva para sipru@sipru.ai contando qual é o seu sistema e quem é o contato técnico.

Webhook

O webhook ainda não existe

Nenhum endpoint desta seção responde hoje — o serviço de ingestão não é alcançável de fora da infraestrutura da Sipru, e a exposição pública ainda não foi decidida. Para integrar agora, use Cloud Storage ou conector dedicado.

Receba grandes volumes de dados em tempo real via HTTP, com persistência automática no Google Cloud Storage, particionada por data, origem e tipo de evento.

Como funciona

A plataforma disponibiliza endpoints de webhook dedicados para cada parceiro. Ao receber uma requisição HTTP, o webhook captura o payload, valida a estrutura e persiste os dados no GCS de forma organizada e particionada, permitindo consumo posterior para análise e integração.

O desenho prevê baixa latência com resposta imediata, tolerância a picos de tráfego sem perda de dados, e retries automáticos com deduplicação.

Arquitetura do webhook

Fluxo detalhado

1. Recepção da requisição. O parceiro envia um POST para o endpoint exclusivo do webhook. O sistema responde 202 Accepted imediatamente, confirmando o recebimento.

2. Validação e autenticação. O payload é validado contra o schema esperado, e a autenticação é verificada por token, header customizado ou assinatura HMAC. Requisições inválidas recebem 400 ou 401 com detalhe do erro.

3. Enfileiramento com deduplicação. Os dados validados são enfileirados com controle de duplicidade por idempotency_key. Se a mesma requisição chegar mais de uma vez, só a primeira é processada.

4. Persistência no GCS. Os dados são gravados particionados por data, origem e tipo de evento.

5. Processamento pelo pipeline. Depois de persistidos, os dados entram no pipeline de validação e enriquecimento, alimentando a plataforma.

Estrutura de particionamento no GCS

{seu_parceiro}/
└── webhooks/
├── event_type=orders/
│ └── date=2026-04-14/
│ ├── batch_001.json
│ └── batch_002.json
├── event_type=inventory/
│ └── date=2026-04-14/
│ └── batch_001.json
└── event_type=prices/
└── date=2026-04-14/
└── batch_001.json

Mecanismos de resiliência

MecanismoDescrição
Retries automáticosEm caso de falha na persistência, até 5 tentativas com backoff exponencial (1 s, 2 s, 4 s, 8 s, 16 s).
Controle de duplicidadeCada requisição pode incluir idempotency_key. Eventos duplicados são descartados dentro de uma janela de 24 h.
Dead Letter QueueMensagens que falharam após todas as tentativas vão para uma fila de erros, para investigação e reprocessamento manual.
Resposta assíncronaO endpoint retorna 202 Accepted de imediato, desacoplando recepção de processamento e evitando timeout.
Circuit breakerEm falha sistêmica, entra em modo de proteção e enfileira os dados até a recuperação do serviço.

Formato do payload

{
"event_type": "orders",
"idempotency_key": "evt_2026041410300001",
"timestamp": "2026-04-14T10:30:00Z",
"data": [
{
"location_code": "L01",
"product_code": "P123",
"date": "2026-04-14",
"quantity": 60.0,
"unit_sale_price": 40.00,
"unit_cost_price": 25.00,
"order_status": "confirmed"
}
]
}

Resposta do webhook

{
"status": "accepted",
"request_id": "req_8f2a4b6c9d...",
"idempotency_key": "evt_2026041410300001",
"message": "Payload recebido e enfileirado para processamento."
}

Portal self-service

O desenho prevê que o parceiro crie, configure e monitore os próprios webhooks por uma interface, sem depender de suporte técnico.

FuncionalidadeDescrição
Criar e gerenciar endpointsCada endpoint gera um link único para envio de dados.
Configurar autenticaçãoBearer Token, headers customizados ou assinatura HMAC-SHA256, com rotação de token sem downtime.
Visualizar logs de requisiçõesHistórico completo com status, payload recebido, tempo de resposta e detalhe de validação.
Métricas em tempo realVolume de eventos, taxa de sucesso e erro, latência média e alertas por threshold.

Exemplo: endpoint criado pelo portal

Cada endpoint criado geraria um link único:

https://webhooks.sipru.ai/v1/ingest/wh_abc123def456

Exemplo: enviando dados

curl -X POST https://webhooks.sipru.ai/v1/ingest/wh_abc123def456 \
-H "Authorization: Bearer whsec_live_..." \
-H "Content-Type: application/json" \
-d '{
"event_type": "orders",
"idempotency_key": "evt_2026041410300001",
"timestamp": "2026-04-14T10:30:00Z",
"data": [
{
"location_code": "L01",
"product_code": "P123",
"date": "2026-04-14",
"quantity": 60.0,
"unit_sale_price": 40.00,
"unit_cost_price": 25.00,
"order_status": "confirmed"
}
]
}'
O portal é protótipo de interface

A tela existe em /integracoes/webhooks, mas sem backend: os endpoints exibidos não são emitidos de verdade e não recebem tráfego.

Segurança do webhook

CamadaMecanismoDescrição
AutenticaçãoBearer Token / HMAC-SHA256Cada endpoint tem um token secreto. Opcionalmente, assinatura HMAC valida a integridade do payload.
TransporteTLS obrigatórioTodas as requisições usam HTTPS; conexões HTTP são rejeitadas.
Rate limitingControle por endpointLimite configurável por endpoint (padrão 1.000 req/min). Excedentes recebem 429.
IP allowlistingFiltro por IP de origemOpcionalmente, restringe o acesso a uma lista de IPs autorizados.
Acesso ao GCSIAM com menor privilégioOs dados persistidos são acessíveis apenas pelo pipeline, por service accounts com permissão mínima.
Proteção contra abusoLimite de tamanhoPayloads limitados a 5 MB. Requisições maiores recebem 413.

Validação via HMAC-SHA256

O parceiro calcula a assinatura sobre o corpo cru da requisição e a envia no header. A plataforma recalcula e compara.

import hashlib
import hmac

webhook_secret = "whsec_live_..." # fornecido no onboarding
payload_body = b'{"event_type":"orders"}' # corpo cru da requisição

signature = hmac.new(webhook_secret.encode(), payload_body, hashlib.sha256).hexdigest()

headers = {
"X-Webhook-Signature": f"sha256={signature}",
"Content-Type": "application/json",
}

Observabilidade

Descrição
LogsLog estruturado de cada requisição: timestamp, status, tempo de processamento, tamanho do payload e detalhe de validação. Retenção de 90 dias.
MétricasVolume de eventos por minuto, hora e dia; taxa de sucesso e erro; latência P50, P95 e P99; tamanho médio do payload; uso do rate limit.
AlertasConfiguráveis por threshold — taxa de erro acima de X%, latência acima de Y ms, volume abaixo do esperado. Notificação por e-mail ou webhook reverso.

Códigos de resposta do webhook

CódigoSignificado
202Accepted — payload recebido e enfileirado
400Bad Request — payload inválido ou schema incorreto
401Unauthorized — token inválido ou assinatura HMAC incorreta
403Forbidden — IP não autorizado, quando o allowlisting está ativo
409Conflict — idempotency_key já processada, duplicata descartada
413Payload Too Large — payload acima de 5 MB
429Too Many Requests — rate limit excedido para o endpoint
500Internal Server Error — erro interno, dados enfileirados para retry

Para acompanhar a disponibilização desta integração, escreva para sipru@sipru.ai.

Checklist antes do envio

  • O nome do arquivo começa pela entidade, no padrão entidade_YYYYMMDD.csv?
  • A data no nome corresponde ao período dos dados, não ao dia do envio?
  • O cabeçalho tem todas as colunas obrigatórias daquela entidade?
  • Os campos data estão em YYYY-MM-DD? (nem toda entidade usa o mesmo campo de data — ver o dicionário)
  • Os valores monetários são unitários, não o total da linha?
  • Os location_code e product_code referenciados já foram enviados em lojas e produtos, e são os mesmos códigos em todas as entidades?
  • Os códigos estão sem espaço sobrando no começo ou no fim?
  • O arquivo está em UTF-8? Acento quebrado no cabeçalho impede o reconhecimento da coluna.

Separador, BOM, vírgula decimal e colunas extras não precisam de conferência — ver o que o validador aceita.

Suporte

Em caso de dúvida sobre a integração, escreva para sipru@sipru.ai.

O time acompanha todo o processo de integração sem custo para o parceiro. Vale agendar uma call de kickoff para receber as credenciais e tirar as dúvidas técnicas de uma vez.