Pular para conteúdo

Cobranças da Gubee

Todo mês a Gubee cobra o seller pelo uso da plataforma: o plano contratado aplicado aos pedidos do mês, canais adicionais, SKUs e anúncios acima do limite, notas fiscais emitidas pelo emissor, mensalidade fixa e créditos de IA. Os endpoints de /integration/billing/invoices dão ao seu sistema acesso a essas cobranças: a lista dos meses fechados, o detalhe de como cada mês foi calculado e os arquivos (CSV e XLSX) com os pedidos e as notas fiscais que entraram na conta.

Cobrança, não nota fiscal

"Fatura" aqui é a cobrança da Gubee ao seller. Não confunda com as notas fiscais de venda do seller, que ficam em Notas Fiscais e DANFE.

Quando usar

Recurso Quando
GET /integration/billing/invoices Conciliar no ERP ou no financeiro o valor cobrado pela Gubee em cada mês
GET /integration/billing/invoices/{id} Mostrar ao seller como o mês foi calculado: plano, consumo e composição do valor
GET /integration/billing/invoices/{id}/export Baixar a lista de pedidos e de notas fiscais que entraram na cobrança, para conferência
Notas Fiscais e DANFE Notas fiscais de venda emitidas pelo seller (não é cobrança da Gubee)

Permissão exigida

Os três endpoints exigem a permissão billing:view — "Ver cobranças da Gubee e baixar os arquivos". O seller é sempre o dono do token: não existe parâmetro sellerId, e um seller nunca vê a cobrança de outro.

Também aceitam o token de integração legado do seller.

Pedir a permissão no app OAuth2

As permissões de um app OAuth2 são declaradas no cadastro, não na URL de autorização:

  1. No painel da Gubee, em Integrações → Meus apps, marque billing:view ao criar o app (Criar e gerenciar apps).
  2. O seller vê a permissão na tela de aprovação e autoriza. O access_token emitido passa a carregar billing:view.

Acrescentar a permissão a um app já publicado

Alterar as permissões de um app revoga na hora a autorização de todos os sellers conectados. Cada um precisa autorizar o app de novo. Renovar com refresh_token não traz a permissão nova: só uma nova autorização traz. Detalhes em Permissões dos apps.

Sem a permissão, a chamada recebe 403 com required_scope:

{
  "status": 403,
  "required_scope": "billing:view"
}

Endpoints

Todos sob /integration/billing/invoices (JSON plano, sem _links):

Método Path Descrição
GET ?page=&size= Lista paginada das cobranças dos meses fechados, uma por mês, da mais recente para a mais antiga
GET /{id} Detalhe de uma cobrança: plano aplicado, consumo do mês e composição do valor
GET /{id}/export Links de download dos arquivos de pedidos e de notas fiscais da cobrança

Os exemplos usam:

export GUBEE_API="https://api.gubee.com.br"
export JWT="<access_token do app OAuth2>"

Listar as cobranças

curl -s "$GUBEE_API/integration/billing/invoices?page=0&size=20" \
  -H "Authorization: Bearer $JWT"
Parâmetro Padrão Descrição
page 0 Página, começando em 0
size 20 Itens por página, de 1 a 100

Resposta 200:

{
  "items": [
    {
      "id": "6701f0c2a1b2c3d4e5f60718",
      "period": "2026-09",
      "totalAmount": 2122.76,
      "files": {
        "orders": { "csv": true, "xlsx": true, "applicable": true },
        "fiscalNotes": { "csv": true, "xlsx": false, "applicable": true }
      }
    }
  ],
  "total": 1,
  "page": 0,
  "pageSize": 20,
  "filesSince": "2026-10"
}

A lista traz só meses fechados, uma cobrança por mês: a vigente daquele mês. O mês corrente e as prévias calculadas antes do fechamento nunca aparecem. Se a Gubee recalcular um mês, a lista passa a mostrar o novo cálculo com outro id.

Campo Tipo Descrição
items[].id String Identificador da cobrança. Use nos outros dois endpoints
items[].period String AAAA-MM Mês cobrado
items[].totalAmount Número Valor total cobrado no mês, em reais
items[].files Objeto Quais arquivos existem para o mês (abaixo)
total Inteiro Total de cobranças, somando todas as páginas
page Inteiro Página devolvida
pageSize Inteiro Tamanho da página
filesSince String AAAA-MM Primeiro mês com arquivos. Meses anteriores não têm arquivos para baixar

O objeto files

files.orders (pedidos) e files.fiscalNotes (notas fiscais) têm a mesma forma:

Campo Tipo Descrição
applicable Boolean false quando o arquivo não existe para o mês, por exemplo sem notas fiscais cobradas. Os outros dois campos vêm false
csv Boolean Há arquivo CSV
xlsx Boolean Há cópia XLSX. Pode faltar mesmo com o CSV presente

Ver como o mês foi cobrado

curl -s "$GUBEE_API/integration/billing/invoices/6701f0c2a1b2c3d4e5f60718" \
  -H "Authorization: Bearer $JWT"

Resposta 200:

{
  "id": "6701f0c2a1b2c3d4e5f60718",
  "period": "2026-09",
  "calculatedAt": "2026-10-01T03:10:41.512",
  "totalAmount": 2122.76,
  "usage": {
    "orders": 3120,
    "ordersAmount": 152340.55,
    "activeSkus": 820,
    "inactiveSkus": 40,
    "activeAds": 1500,
    "activeChannels": 4,
    "invoicerAccounts": 1,
    "issuedFiscalNotes": 2987
  },
  "plan": {
    "type": "PERCENT",
    "value": 1.0,
    "fixedFee": 350.0,
    "minimumAmount": 0,
    "startDate": "2025-01-01",
    "channels": {
      "rule": "FOR_EVERY_FURTHER",
      "pricePerChannel": 50.0,
      "freeChannels": 2,
      "groupSize": null
    },
    "limits": {
      "activeSkus": 1000,
      "inactiveSkus": 100,
      "activeAds": 2000,
      "pricePerAdditional": 0.5
    },
    "discounts": [
      { "type": "PERCENTAGE", "value": 10.0, "whenOrdersAmountAbove": 200000.0 }
    ],
    "valueTiers": [],
    "orderTiers": [],
    "pricePerInvoicerAccount": 0,
    "pricePerIssuedFiscalNote": 0.05
  },
  "charges": [
    { "type": "PLAN", "quantity": null, "base": 152340.55, "rate": 1.0, "unitPrice": null, "amount": 1523.41 },
    { "type": "CHANNELS", "quantity": 2, "base": null, "rate": null, "unitPrice": 50.0, "amount": 100.00 },
    { "type": "INVOICER_FISCAL_NOTES", "quantity": 2987, "base": null, "rate": null, "unitPrice": 0.05, "amount": 149.35 },
    { "type": "FIXED_FEE", "quantity": null, "base": null, "rate": null, "unitPrice": null, "amount": 350.00 }
  ],
  "files": {
    "orders": { "csv": true, "xlsx": true, "applicable": true },
    "fiscalNotes": { "csv": true, "xlsx": false, "applicable": true }
  }
}

O detalhe só existe para as cobranças que aparecem na lista. O id de uma prévia, do mês corrente ou de um cálculo já substituído responde 404.

Campo Tipo Descrição
id String Identificador da cobrança
period String AAAA-MM Mês cobrado
calculatedAt Data e hora, sem fuso Quando o mês foi calculado, no horário de Brasília
totalAmount Número Valor total cobrado, em reais
usage Objeto Consumo do mês que entrou no cálculo
plan Objeto Plano aplicado ao mês
charges Lista ou null Composição do valor, linha a linha. Veja quando vem null
files Objeto O mesmo objeto files da lista

usage: o consumo do mês

Campo Descrição
orders Quantidade de pedidos do mês considerados na cobrança
ordersAmount Soma do valor desses pedidos, em reais
activeSkus SKUs ativos
inactiveSkus SKUs inativos
activeAds Anúncios ativos
activeChannels Canais de venda (marketplaces) ativos
invoicerAccounts Contas do emissor de notas fiscais da Gubee
issuedFiscalNotes Notas fiscais emitidas pelo emissor da Gubee no mês

plan: o plano aplicado

plan.type diz como o valor principal do plano é calculado:

plan.type Como cobra
PERCENT Percentual sobre o valor dos pedidos do mês (value, em pontos percentuais: 1.0 = 1%)
PERCENT_BY_RANGE_OF_VALUE Percentual escolhido pela faixa do valor dos pedidos do mês (valueTiers)
BY_ORDER Valor fixo por pedido (value, em reais)
BY_RANGE_OF_VALUE Valor fixo no mês, escolhido pela faixa do valor dos pedidos (valueTiers)
BY_RANGE_OF_QTY_FIXED_INVOICE Valor fixo no mês, escolhido pela faixa da quantidade de pedidos (orderTiers)
BY_RANGE_OF_QTY_VALUE_PER_ORDER Valor por pedido, escolhido pela faixa da quantidade de pedidos (orderTiers)
BY_SKU_AD_LIMIT_AND_ORDER Uma faixa de pedidos grátis e valor por pedido acima dela, com limite de SKUs e anúncios (orderTiers, limits). Não cobra canais adicionais
NONE Sem cobrança de plano. Os demais itens (mensalidade, emissor, créditos de IA) podem ser cobrados

Os demais campos:

Campo Descrição
type Tipo do plano (tabela acima)
value Valor principal do plano. O sentido depende de type: percentual em PERCENT, reais por pedido em BY_ORDER. Nos planos por faixa, o valor que vale está na faixa
fixedFee Mensalidade fixa, cobrada todo mês (linha FIXED_FEE)
minimumAmount Valor mínimo do mês. Se a soma das linhas ficar abaixo dele, a diferença é cobrada (linha MINIMUM_ADJUSTMENT). 0 = sem mínimo
startDate Data de início do plano (AAAA-MM-DD)
channels Cobrança por canal de venda. null quando os canais não são cobrados
channels.rule FOR_EVERY_FURTHER: cada canal além dos gratuitos custa pricePerChannel. EACH_GROUP_OF: cada grupo completo de groupSize canais além dos gratuitos custa pricePerChannel. UNLIMITED: canais ilimitados, sem cobrança
channels.pricePerChannel Preço, em reais, de cada canal ou grupo adicional
channels.freeChannels Canais incluídos no plano, sem cobrança
channels.groupSize Tamanho do grupo em EACH_GROUP_OF; null nas outras regras
limits Limites de SKUs e anúncios incluídos no plano. null quando o plano não tem limite
limits.activeSkus, limits.inactiveSkus, limits.activeAds Quantidade incluída no plano. O que passar é cobrado nas linhas EXTRA_SKUS e EXTRA_ADS
limits.pricePerAdditional Preço, em reais, de cada SKU ou anúncio acima do limite
discounts[] Descontos condicionais (linha DISCOUNT)
discounts[].type PERCENTAGE (value em pontos percentuais: 10.0 = 10%) ou FIXED (value em reais)
discounts[].whenOrdersAmountAbove O desconto vale quando o valor dos pedidos do mês passa deste valor
valueTiers[] Faixas por valor dos pedidos do mês: from e to em reais, value é o percentual ou o valor da faixa, conforme type
orderTiers[] Faixas por quantidade de pedidos do mês: from e to em pedidos, value é o valor da faixa, conforme type
pricePerInvoicerAccount Preço por conta do emissor de notas fiscais (linha INVOICER_ACCOUNTS)
pricePerIssuedFiscalNote Preço por nota fiscal emitida pelo emissor (linha INVOICER_FISCAL_NOTES)

Listas vazias vêm como []. Campos que não se aplicam ao tipo do plano podem vir 0, null ou vazios.

Como a cobrança é calculada

O valor do mês é a soma das linhas de charges. Cada linha é uma parcela do cálculo, na ordem em que o cálculo acontece, e só aparecem linhas com valor diferente de zero:

charges[].type O que é
PLAN Valor principal do plano, conforme plan.type
CHANNELS Canais de venda acima dos gratuitos
EXTRA_SKUS SKUs acima do limite do plano
EXTRA_ADS Anúncios acima do limite do plano
DISCOUNT Desconto. amount é negativo
INVOICER_ACCOUNTS Contas do emissor de notas fiscais
INVOICER_FISCAL_NOTES Notas fiscais emitidas pelo emissor
FIXED_FEE Mensalidade fixa
MINIMUM_ADJUSTMENT Complemento até o valor mínimo do plano, quando a soma ficou abaixo dele
AI_CREDITS Créditos de IA consumidos
Campo da linha Descrição
type Tipo da linha (tabela acima)
quantity Quantidade cobrada (canais, SKUs, anúncios, notas, contas), quando faz sentido
base Valor sobre o qual o percentual incidiu, em reais
rate Percentual efetivamente usado, em pontos percentuais (1.0 = 1%)
unitPrice Preço unitário, em reais
amount Valor da linha, em reais. A soma de todos os amount é totalAmount

quantity, base, rate e unitPrice vêm null quando não fazem sentido para a linha.

No exemplo acima: 1% sobre R$ 152.340,55 de pedidos (PLAN, R$ 1.523,41), mais 2 canais além dos 2 gratuitos a R$ 50,00 (CHANNELS, R$ 100,00), mais 2.987 notas fiscais emitidas a R$ 0,05 (INVOICER_FISCAL_NOTES, R$ 149,35), mais a mensalidade (FIXED_FEE, R$ 350,00): total de R$ 2.122,76. SKUs e anúncios ficaram dentro dos limites, e o desconto de 10% não entrou porque o valor dos pedidos não passou de R$ 200.000,00; se tivesse entrado, viria uma linha DISCOUNT com amount negativo.

Confira a soma

Some os amount e compare com totalAmount para validar a sua leitura. Os dois sempre batem quando charges vem preenchido.

Quando charges vem null

Se a composição daquele mês não pode ser reproduzida (por exemplo, a configuração do plano mudou depois do cálculo), charges vem null. totalAmount continua sendo o valor cobrado, e plan e usage vêm sempre. Mostre o total e avise que a composição do mês não está disponível.

Baixar os arquivos

curl -s "$GUBEE_API/integration/billing/invoices/6701f0c2a1b2c3d4e5f60718/export" \
  -H "Authorization: Bearer $JWT"

Resposta 200:

{
  "available": true,
  "generatedAt": "2026-10-01T03:12:00",
  "orders": {
    "csvUrl": "https://<link assinado>",
    "xlsxUrl": "https://<link assinado>",
    "expiresAt": "2026-10-14T10:20:00",
    "rows": 3120
  },
  "fiscalNotes": {
    "csvUrl": "https://<link assinado>",
    "xlsxUrl": null,
    "expiresAt": "2026-10-14T10:20:00",
    "rows": 2987
  }
}
Campo Tipo Descrição
available Boolean true quando os arquivos estão liberados para download
generatedAt Data e hora, sem fuso Quando os arquivos foram gerados
orders Objeto Arquivo de pedidos
fiscalNotes Objeto ou null Arquivo de notas fiscais. null quando não existe para o mês
*.csvUrl String Link de download do CSV
*.xlsxUrl String ou null Link de download do XLSX. null quando o mês tem só o CSV
*.expiresAt Data e hora, sem fuso Quando os links deixam de funcionar, cerca de 10 minutos depois da chamada
*.rows Inteiro Linhas de dados do arquivo

Os links baixam o arquivo direto, sem Authorization:

CSV_URL=$(curl -s "$GUBEE_API/integration/billing/invoices/6701f0c2a1b2c3d4e5f60718/export" \
  -H "Authorization: Bearer $JWT" | jq -r '.orders.csvUrl')

curl -s "$CSV_URL" -o pedidos-2026-09.csv

Arquivos ainda não liberados

Enquanto os arquivos do mês não estão liberados, a resposta é 200 com available: false e nenhum link é gerado:

{
  "available": false,
  "generatedAt": null,
  "orders": null,
  "fiscalNotes": null
}

Tente de novo mais tarde. Meses anteriores a filesSince (da lista) não têm arquivos.

Erros

HTTP Quando O que fazer
401 Token ausente, malformado ou expirado Envie Authorization: Bearer <token>; renove se expirado
403 O token não tem billing:view Leia required_scope no corpo; peça a permissão e uma nova autorização ao seller
404 A cobrança não existe ou não é do seller do token. A resposta é a mesma nos dois casos, sem corpo Atualize a lista: o mês pode ter sido recalculado e ganhado outro id
503 Serviço de cobranças indisponível (application/problem+json, title "Billing unavailable") Tente de novo mais tarde, com espera crescente entre as tentativas

Exemplo de 503:

{
  "title": "Billing unavailable",
  "status": 503
}

Os limites de requisição são os mesmos das demais rotas /integration/*.

Boas práticas

  • Peça os links na hora de baixar. Eles valem cerca de 10 minutos (expiresAt) e a resposta vem com Cache-Control: no-store. Chame /export a cada download, em vez de guardar a resposta.
  • Não armazene nem registre em log as URLs. Quem tem o link baixa o arquivo sem token enquanto ele vale. Guarde o id da cobrança e gere os links de novo quando precisar.
  • Pagine. Percorra a lista com page e size (até 100) até cobrir total.
  • Tolere valores novos. plan.type, channels.rule, discounts[].type e charges[].type podem ganhar valores novos. Mostre um rótulo genérico para o que não conhecer e continue somando amount; não falhe a leitura. Ignore campos desconhecidos.
  • Não guarde id como chave do mês. Um recálculo troca o id. A chave do mês é period.
  • Trate charges: null e available: false como estados normais, não como erro.

Próximos passos