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:
- No painel da Gubee, em Integrações → Meus apps, marque
billing:viewao criar o app (Criar e gerenciar apps). - O seller vê a permissão na tela de aprovação e autoriza. O
access_tokenemitido passa a carregarbilling: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:
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:
Listar as cobranças¶
| 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:
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:
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 comCache-Control: no-store. Chame/exporta 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
idda cobrança e gere os links de novo quando precisar. - Pagine. Percorra a lista com
pageesize(até 100) até cobrirtotal. - Tolere valores novos.
plan.type,channels.rule,discounts[].typeecharges[].typepodem ganhar valores novos. Mostre um rótulo genérico para o que não conhecer e continue somandoamount; não falhe a leitura. Ignore campos desconhecidos. - Não guarde
idcomo chave do mês. Um recálculo troca oid. A chave do mês éperiod. - Trate
charges: nulleavailable: falsecomo estados normais, não como erro.
Próximos passos¶
- Permissões dos apps: catálogo de permissões, incluindo
billing:view - Guia do desenvolvedor OAuth2: obter e renovar o token
- Referência OAuth2: erros de autorização e das chamadas