Status da conta¶
Parceiros que cobram ou administram sellers na Gubee (ERPs, hubs, revendas) podem congelar, descongelar e cancelar a conta de um seller vinculado ao seu app OAuth2, sempre informando o motivo e quem pediu a mudança do seu lado. Toda mudança fica na trilha de auditoria da Gubee e é avisada por webhook.
| Recurso | Quando |
|---|---|
POST /integration/accounts/{sellerId}/status-changes |
Congelar a conta por inadimplência, descongelar quando o seller regularizar, cancelar no fim do contrato |
GET /integration/accounts/{sellerId}/status |
Conferir o status atual, as travas da conta e o histórico das mudanças feitas pelo seu app |
Webhook ACCOUNT_STATUS_CHANGED |
Saber quando o status da conta mudou, inclusive por ação da Gubee ou de outro parceiro |
Os três status¶
| Status | O que significa |
|---|---|
ACTIVE |
Conta funcionando normalmente |
FROZEN |
Conta congelada: existe ao menos uma trava reversível. Integrações e canais param e o seller não entra no painel |
CANCELED |
Conta cancelada. Só a Gubee reverte, dentro do prazo de retenção |
Travas¶
O status é consequência das travas que a conta tem. Cada trava tem um dono:
Trava (type) |
Quem põe | Quem tira |
|---|---|---|
PARTNER_FREEZE |
Um app parceiro, com FREEZE |
Só o mesmo app, com UNFREEZE |
GUBEE_SUSPENSION |
A Gubee (suspensão) | Só a Gubee |
CANCELED |
Um app parceiro, com CANCEL, ou a Gubee |
Só a Gubee, dentro do prazo de retenção |
- A conta fica
FROZENenquanto houver qualquer trava reversível: a do seu app, a de outro parceiro ou uma suspensão da Gubee. CANCELEDprevalece sobre as demais travas.- Cada parceiro congela de forma independente. Se dois apps congelaram a mesma conta, o
UNFREEZEde um tira só a trava dele: a conta continuaFROZENaté o outro também descongelar. - Uma conta desativada antes desta API pode aparecer como
FROZENsem nenhuma trava.
Quem pode o quê¶
| Ação | Permissão | O que faz |
|---|---|---|
FREEZE |
account:freeze |
Põe uma trava do seu app na conta. A conta fica FROZEN |
UNFREEZE |
account:freeze |
Tira a trava do seu app. A conta só volta a ACTIVE se não houver outra trava |
CANCEL |
account:cancel |
Cancela a conta (CANCELED) |
| Consultar status | account:status:view |
Lê status, travas e o histórico do seu app |
O que um parceiro não pode fazer:
- tirar a trava de outro parceiro;
- tirar uma suspensão da Gubee (
GUBEE_SUSPENSION); - reverter um cancelamento. Depois de
CANCEL, toda ação do parceiro na conta recebe409. Só a Gubee reverte, dentro de 90 dias.
Cancelar é definitivo para o parceiro
Use CANCEL só no fim do contrato. Para interromper a conta temporariamente (inadimplência,
pedido do seller), use FREEZE.
Pré-requisitos¶
- Permissões aprovadas pela Gubee.
account:status:view,account:freezeeaccount:cancelnão ficam disponíveis a todo app: peça a liberação ao seu contato comercial na Gubee. Depois de aprovado, o app passa a ter uma service account e pode obter token comclient_credentials. - Vínculo com o seller. O seller precisa ter autorizado o seu app com as permissões da ação (fluxo do Guia do desenvolvedor). É essa autorização que cria o vínculo entre o app e o seller. Sem ela, nenhuma chamada sobre aquele seller passa.
- O
sellerIddo caminho tem de ser um seller vinculado. Um app nunca age sobre um seller que não o autorizou: a resposta é403.
Acrescentar as permissões 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. Detalhes em Permissões dos apps.
Obter o token (client_credentials)¶
As chamadas de status da conta são de servidor para servidor. Use o fluxo client_credentials
com o client_id e o client_secret do app:
curl -s -X POST "https://auth.gubee.com.br/realms/gubee/protocol/openid-connect/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=$GUBEE_CLIENT_ID" \
-d "client_secret=$GUBEE_CLIENT_SECRET"
- O token não traz
refresh_token: peça um novo quando estiver perto de vencer. Oexpires_invem em segundos e não é fixo; leia sempre o da resposta. - O mesmo token serve para todos os sellers vinculados ao app. O seller da chamada é o
sellerIddo caminho, conferido contra os vínculos do app. - O
client_secretnunca sai do seu back-end.
Os exemplos abaixo usam:
export GUBEE_API="https://api.gubee.com.br"
export JWT="<access_token do client_credentials>"
export SELLER_ID="<sellerId vinculado ao app>"
Mudar o status¶
POST /integration/accounts/{sellerId}/status-changes
Headers¶
| Header | Obrigatório | Descrição |
|---|---|---|
Authorization |
sim | Bearer <access_token> |
Content-Type |
sim | application/json |
Idempotency-Key |
sim | Chave única do pedido, até 255 caracteres (ex.: um UUID). Veja Idempotência |
X-Correlation-Id |
não | Identificador de correlação do seu lado (letras, números e ._:-, até 100 caracteres). Sem ele, a Gubee gera um |
Corpo¶
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
action |
string |
sim | FREEZE, UNFREEZE ou CANCEL |
reasonCode |
string |
sim | Motivo padronizado. Veja reasonCodes |
reason |
string |
só com OTHER |
Motivo em texto livre, até 500 caracteres |
requestedBy.name |
string |
sim | Nome de quem, do seu lado, pediu a mudança (até 200 caracteres) |
requestedBy.email |
string |
sim | E-mail dessa pessoa (até 254 caracteres) |
requestedBy.externalId |
string |
não | Id dessa pessoa no seu sistema (até 100 caracteres) |
requestedBy¶
requestedBy identifica o operador do seu lado: a pessoa que mandou congelar ou cancelar.
Ele fica na trilha de auditoria da Gubee junto com o app que fez a chamada (o clientId vem do
token, nunca do corpo). Se a mudança for automática, informe o responsável pela regra
automática ou uma caixa de e-mail do time.
reasonCodes¶
reasonCode |
Quando usar |
|---|---|
PAYMENT_OVERDUE |
Inadimplência do seller com o parceiro |
MERCHANT_REQUEST |
Pedido do próprio seller |
CONTRACT_ENDED |
Fim do contrato entre o seller e o parceiro |
FRAUD_SUSPECTED |
Suspeita de fraude |
MIGRATION |
Migração de conta ou de plataforma |
OTHER |
Outro motivo. Exige reason |
Congelar (FREEZE)¶
curl -s -X POST "$GUBEE_API/integration/accounts/$SELLER_ID/status-changes" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 3f1c9a52-7d0e-4b8a-9f61-2c4d5e6f7a80" \
-d '{
"action": "FREEZE",
"reasonCode": "PAYMENT_OVERDUE",
"reason": "Fatura de setembro em aberto",
"requestedBy": {
"name": "Ana Operadora",
"email": "ana@parceiro.com",
"externalId": "op-7"
}
}'
Resposta 202 Accepted:
{
"sellerId": "seller-1",
"previousStatus": "ACTIVE",
"status": "FROZEN",
"locks": [
{
"type": "PARTNER_FREEZE",
"mine": true,
"clientId": "partner-erp-x",
"reasonCode": "PAYMENT_OVERDUE",
"reason": "Fatura de setembro em aberto",
"requestedBy": "ana@parceiro.com",
"at": "2026-10-15T10:30:00"
}
],
"change": {
"action": "FREEZE",
"reasonCode": "PAYMENT_OVERDUE",
"reason": "Fatura de setembro em aberto",
"requestedBy": {
"name": "Ana Operadora",
"email": "ana@parceiro.com",
"externalId": "op-7"
},
"at": "2026-10-15T10:30:00"
},
"replayed": false
}
Headers da resposta: Idempotent-Replayed (true ou false) e X-Correlation-Id (informe ao
suporte da Gubee).
Descongelar (UNFREEZE)¶
curl -s -X POST "$GUBEE_API/integration/accounts/$SELLER_ID/status-changes" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8b2e4d61-1a3f-4c5b-a7d9-0e1f2a3b4c5d" \
-d '{
"action": "UNFREEZE",
"reasonCode": "PAYMENT_OVERDUE",
"reason": "Fatura de setembro quitada",
"requestedBy": {
"name": "Ana Operadora",
"email": "ana@parceiro.com"
}
}'
O UNFREEZE tira só a trava do seu app. Confira o status da resposta: se ainda vier FROZEN,
a conta tem outra trava (de outro parceiro ou da Gubee), listada em locks com mine: false.
{
"sellerId": "seller-1",
"previousStatus": "FROZEN",
"status": "FROZEN",
"locks": [
{ "type": "GUBEE_SUSPENSION", "mine": false, "at": "2026-10-10T08:00:00" }
],
"change": {
"action": "UNFREEZE",
"reasonCode": "PAYMENT_OVERDUE",
"reason": "Fatura de setembro quitada",
"requestedBy": { "name": "Ana Operadora", "email": "ana@parceiro.com" },
"at": "2026-10-20T09:12:00"
},
"replayed": false
}
Cancelar (CANCEL)¶
curl -s -X POST "$GUBEE_API/integration/accounts/$SELLER_ID/status-changes" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: c4d5e6f7-0a1b-4c2d-8e3f-4a5b6c7d8e9f" \
-d '{
"action": "CANCEL",
"reasonCode": "CONTRACT_ENDED",
"requestedBy": {
"name": "Carlos Financeiro",
"email": "carlos@parceiro.com"
}
}'
A resposta vem com "status": "CANCELED" e a trava CANCELED em locks. A partir daí, qualquer
FREEZE, UNFREEZE ou CANCEL do parceiro nesta conta recebe 409.
Resposta da mudança¶
| Campo | Descrição |
|---|---|
sellerId |
O seller do caminho |
previousStatus |
Status antes do pedido. Ausente num replay |
status |
Status depois do pedido: ACTIVE, FROZEN ou CANCELED |
locks |
Travas da conta depois do pedido. Veja Privacidade das travas |
change |
A mudança aplicada (num replay, a do pedido original) |
replayed |
true quando a resposta é o replay de um pedido anterior com a mesma Idempotency-Key |
Datas (at) vêm em ISO 8601 sem fuso, no horário de Brasília (America/Sao_Paulo).
Consultar o status¶
GET /integration/accounts/{sellerId}/status — exige account:status:view.
{
"sellerId": "seller-1",
"status": "FROZEN",
"locks": [
{
"type": "PARTNER_FREEZE",
"mine": true,
"clientId": "partner-erp-x",
"reasonCode": "PAYMENT_OVERDUE",
"reason": "Fatura de setembro em aberto",
"requestedBy": "ana@parceiro.com",
"at": "2026-10-15T10:30:00"
},
{ "type": "GUBEE_SUSPENSION", "mine": false, "at": "2026-10-10T08:00:00" }
],
"history": [
{
"action": "FREEZE",
"reasonCode": "PAYMENT_OVERDUE",
"reason": "Fatura de setembro em aberto",
"requestedBy": { "name": "Ana Operadora", "email": "ana@parceiro.com" },
"at": "2026-10-15T10:30:00"
}
]
}
Privacidade das travas e do histórico¶
- Travas do seu app (
mine: true) vêm completas:clientId,reasonCode,reason,requestedBy(e-mail) eat. - Qualquer outra trava (de outro parceiro, a suspensão da Gubee, o cancelamento) vem só com
type,mine: falseeat. Você sabe que ela existe (e por que o seuUNFREEZEnão reativou a conta), mas não quem a pôs nem o motivo. historytraz só as mudanças feitas pelo seu app, entre as 20 mais recentes da conta, da mais recente para a mais antiga.typepode ganhar valores novos: trate um valor desconhecido sem falhar.
Idempotência¶
O header Idempotency-Key é obrigatório no POST. A chave vale por app: duas chamadas do seu
app com a mesma chave são o mesmo pedido.
| Situação | Resposta |
|---|---|
| Chave nova | A mudança é aplicada: 202, replayed: false |
| Mesma chave, mesmo corpo | Replay: 202 com o resultado original, replayed: true e header Idempotent-Replayed: true. Nada é reaplicado e não conta no limite por hora |
| Mesma chave, corpo diferente | 422 (idempotencyConflict) |
Gere uma chave nova (um UUID) para cada mudança que você quer fazer e reuse a mesma chave nas
retentativas dessa mudança (timeout, 503, queda de conexão). Assim uma retentativa nunca
congela ou cancela duas vezes.
Limite de requisições¶
Cada app pode fazer 20 mudanças de status por hora, somando todos os sellers. Acima disso a
resposta é 429 com o header Retry-After (segundos até poder tentar de novo). Replays não
contam no limite. O GET de status segue os limites das demais rotas /integration/*.
Erros¶
Os erros seguem o formato Problem (RFC 7807). O identificador do erro (errorKey) vem no campo
message, prefixado por error.:
{
"title": "Too many account status changes; retry later",
"status": 429,
"message": "error.rateLimitExceeded",
"params": "accountStatus",
"retryAfterSeconds": 1260,
"limit": 20
}
O corpo pode trazer outros campos; ignore os que não conhecer.
| HTTP | errorKey |
Quando | O que fazer |
|---|---|---|---|
400 |
invalidStatusCommand |
Idempotency-Key ausente ou longa demais, action ou reasonCode ausente, OTHER sem reason, reason com mais de 500 caracteres, requestedBy ausente ou incompleto. O title lista todos os problemas |
Corrija o pedido; não repita igual |
401 |
— | Token ausente, malformado ou expirado | Obtenha um novo token |
403 |
— | O token não tem a permissão da ação (account:freeze, account:cancel ou account:status:view). O corpo traz required_scope |
Confira a permissão aprovada no app e a autorização do seller |
403 |
sellerNotAuthorized |
O sellerId do caminho não é um seller vinculado ao app |
Confira o sellerId; peça ao seller que autorize o app |
403 |
accountStatusActionForbidden |
Ação não permitida a parceiros | Não repita: a ação é exclusiva da Gubee |
404 |
accountNotFound |
Conta não encontrada | Confira o sellerId |
409 |
accountStatusConflict |
Transição inválida no estado atual: conta já congelada pelo seu app, UNFREEZE sem trava do seu app, conta cancelada, ou mudança concorrente na mesma conta |
Consulte o status (GET) e decida; numa mudança concorrente, tente de novo |
422 |
idempotencyConflict |
Idempotency-Key já usada pelo seu app com outro corpo |
Use uma chave nova para um pedido diferente |
429 |
rateLimitExceeded |
Mais de 20 mudanças na última hora | Espere os segundos de Retry-After |
503 |
accountStatusUnavailable |
Serviço de contas indisponível | Tente de novo mais tarde, com a mesma Idempotency-Key e espera crescente |
Efeitos na conta do seller¶
FROZEN |
CANCELED |
|
|---|---|---|
| Login do seller no painel | Bloqueado | Bloqueado |
| Integrações e canais | Param | Param |
| Webhooks do seller | Pausados (não apagados); o aviso ACCOUNT_STATUS_CHANGED ainda é entregue |
Pausados |
| Cobrança da Gubee | Continua normalmente | Para na data do cancelamento; o mês do cancelamento é cobrado cheio (sem proporcional) |
| Volta atrás | UNFREEZE do mesmo app (ou a Gubee, no caso da suspensão) |
Só a Gubee, em até 90 dias |
- Ao descongelar, integrações e webhooks voltam com a configuração que tinham antes do congelamento. Nada é perdido.
- Depois do cancelamento, os dados da conta ficam retidos por 90 dias, prazo em que a equipe da Gubee pode reverter o cancelamento a pedido. O parceiro não reverte.
Webhook ACCOUNT_STATUS_CHANGED¶
A cada mudança de status da conta (pelo seu app, por outro parceiro ou pela Gubee) a Gubee envia
um webhook do domínio ACCOUNT com type ACCOUNT_STATUS_CHANGED. Para recebê-lo, habilite o
domínio ACCOUNT na configuração de webhook do seller (veja Eventos).
Diferente dos demais domínios, este evento não tem recurso para consultar: os dados vêm no
próprio payload, no campo data.
{
"resource": "",
"itemId": "seller-1",
"sellerId": "seller-1",
"domain": "ACCOUNT",
"type": "ACCOUNT_STATUS_CHANGED",
"attempts": 1,
"sent": "2026-10-15T13:30:01.120000Z",
"received": "2026-10-15T13:30:00.845000Z",
"data": {
"sellerId": "seller-1",
"status": "FROZEN",
"previousStatus": "ACTIVE",
"action": "FREEZE",
"reasonCode": "PAYMENT_OVERDUE",
"actor": { "type": "PARTNER_APP" },
"effectiveAt": "2026-10-15T10:30:00"
}
}
Campo de data |
Descrição |
|---|---|
sellerId |
Seller da conta |
status |
Status depois da mudança: ACTIVE, FROZEN ou CANCELED |
previousStatus |
Status antes da mudança |
action |
FREEZE, UNFREEZE, CANCEL, ou uma ação da Gubee: SUSPEND, UNSUSPEND, REVERT_CANCEL |
reasonCode |
Motivo padronizado |
actor.type |
Quem mudou: PARTNER_APP (algum parceiro), STAFF (equipe Gubee) ou SYSTEM |
effectiveAt |
Quando a mudança valeu (ISO 8601 sem fuso, horário de Brasília) |
- O payload não traz dados pessoais nem o
clientIddo parceiro: umactor.typePARTNER_APPpode ser outro app. Para saber se a mudança foi sua, compare com o seu histórico (GET .../status). - Um
UNFREEZEque não reativa a conta também gera o evento, comstatusepreviousStatusFROZEN. - O aviso de congelamento é entregue mesmo com os webhooks do seller pausados.
- A entrega é at-least-once: o mesmo evento pode chegar mais de uma vez. Deduplique por
data.status+data.effectiveAt(veja Idempotência de webhooks). action,reasonCodeeactor.typepodem ganhar valores novos: trate um valor desconhecido sem falhar.
Boas práticas¶
- Congele, não cancele, quando houver chance de o seller voltar.
- Uma
Idempotency-Keypor intenção, reusada em toda retentativa da mesma mudança. - Leia o
statusda resposta depois deUNFREEZE: a conta pode continuarFROZENpor outra trava. - Trate
409consultando o status antes de repetir. - Respeite o
Retry-Afterno429, em vez de repetir em laço. - Guarde o
X-Correlation-Idda resposta: é o que o suporte da Gubee pede para rastrear um pedido.