Pular para conteúdo

Autenticação

A API de integração da Gubee (/integration/*) usa JWT (JSON Web Token) para autenticação. Este documento explica como obter, usar e renovar seus tokens.

Como funciona

  1. Você pega um API Token no painel da Gubee (Minha Conta > Acesso à API).
  2. Troca esse API Token por um JWT válido por 1 hora via endpoint de renovação.
  3. Envia o JWT no header Authorization: Bearer <jwt> em toda chamada.
  4. Quando o JWT expira (1h), repete o passo 2.
[Painel Gubee] → API Token (permanente)
[POST /tokens/revalidate/apitoken] → JWT (válido 1h)
[GET /integration/*] ← Authorization: Bearer <jwt>

Regra crítica: sellerId vem do token, nunca do body

O sellerId identifica qual seller está fazendo a chamada. Ele é sempre extraído automaticamente do JWT — você não precisa (e não deve) enviá-lo no body, query string ou path.

Nunca envie sellerId no body

Campos sellerId em payloads são ignorados silenciosamente. O seller é sempre determinado pelo token.

A única exceção é a cotação de frete, que é um endpoint público (sem JWT):

  • POST /integration/quotes/{sellerId}/{postalCode} — recebe sellerId no path porque é usado em checkouts públicos onde não há login.

Obter o JWT

1. Pegar o API Token no painel

No painel da Gubee: Minha Conta > Acesso à API. Gere um API Token e guarde-o com segurança. Ele é permanente (não expira) e funciona como sua credencial raiz.

2. Trocar pelo JWT (válido 1h)

curl -X POST https://api.gubee.com.br/integration/tokens/revalidate/apitoken \
  -H "Content-Type: application/json" \
  --data-raw '"SEU_API_TOKEN_AQUI"'

Formato do body

O body é o API Token entre aspas duplas (JSON string), não um objeto. Use --data-raw '"token"' (com aspas duplas envolvendo o token).

Resposta (200 OK)

{
  "token": "eyJhbGciOiJIUzUxMiJ9...",
  "expiresIn": 3600,
  "sellerId": "SELLER123"
}
Campo Descrição
token O JWT (use no header Authorization)
expiresIn Validade em segundos (3600 = 1h)
sellerId Seu identificador de seller (informativo)

Erros na renovação

HTTP Causa O que fazer
400 Token ainda válido Aguarde expirar ou use o JWT atual
403 Janela de renovação expirou Gere um novo API Token no painel
404 Token não reconhecido Verifique se copiou o token completo

Usar o JWT

Todo request autenticado deve enviar:

Authorization: Bearer eyJhbGciOiJIUzUxMiJ9...
Content-Type: application/json

Exemplo:

curl -X GET "https://api.gubee.com.br/integration/skus/by-sku?sku=SKU-123" \
  -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9..." \
  -H "Accept: application/json"

Erros 401/403

Sintoma Causa Solução
401 sem header Authorization ausente Adicione Authorization: Bearer <jwt>
401 token expired JWT venceu (1h) Renove via /tokens/revalidate/apitoken
403 Sem permissão Confirme com o administrador da conta

Boas práticas

  • Renove 5 min antes de expirar: cache o JWT com TTL de 55min, renove automaticamente antes do vencimento para evitar janelas de 401.
  • Não paralelize a renovação: use uma única função/thread responsável por renovar; as demais leem do cache.
  • Nunca logue o JWT completo: máscare tudo menos os primeiros 10 caracteres.
  • HTTPS obrigatório: nunca envie o token em HTTP.
  • Não compartilhe o API Token entre ambientes: cada ambiente (dev, prod) deve ter seu próprio.
  • Revogação: JWTs não podem ser revogados individualmente antes da expiração. Em caso de vazamento, gere um novo API Token no painel (o antigo é invalidado).

Exemplo: renovação automática em Python

import requests
import time
import threading

class GubeeTokenManager:
    def __init__(self, api_token):
        self.api_token = api_token
        self.jwt = None
        self.expires_at = 0
        self._lock = threading.Lock()

    def get_jwt(self):
        with self._lock:
            if not self.jwt or time.time() > self.expires_at - 300:
                self._renew()
            return self.jwt

    def _renew(self):
        resp = requests.post(
            "https://api.gubee.com.br/integration/tokens/revalidate/apitoken",
            headers={"Content-Type": "application/json"},
            data=f'"{self.api_token}"'
        )
        resp.raise_for_status()
        data = resp.json()
        self.jwt = data["token"]
        self.expires_at = time.time() + data["expiresIn"]

# Uso
token_mgr = GubeeTokenManager("SEU_API_TOKEN")
jwt = token_mgr.get_jwt()
requests.get(
    "https://api.gubee.com.br/integration/skus/by-sku?sku=X",
    headers={"Authorization": f"Bearer {jwt}"}
)

Exemplo: renovação automática em Node.js

const axios = require('axios');

let jwt = null;
let expiresAt = 0;

async function getJwt() {
  if (!jwt || Date.now() > expiresAt - 5 * 60 * 1000) {
    await renew();
  }
  return jwt;
}

async function renew() {
  const { data } = await axios.post(
    'https://api.gubee.com.br/integration/tokens/revalidate/apitoken',
    JSON.stringify(process.env.GUBEE_API_TOKEN),
    { headers: { 'Content-Type': 'application/json' } }
  );
  jwt = data.token;
  expiresAt = Date.now() + data.expiresIn * 1000;
}

module.exports = { getJwt };

Exemplo: renovação automática em Java

public class GubeeTokenManager {

    private final OkHttpClient http = new OkHttpClient();
    private final String apiToken;
    private volatile String jwt;
    private volatile long expiresAtMs;

    public synchronized String getJwt() {
        if (jwt == null || System.currentTimeMillis() > expiresAtMs - 300_000) {
            renew();
        }
        return jwt;
    }

    private void renew() {
        RequestBody body = RequestBody.create(
            "\"" + apiToken + "\"",
            MediaType.get("application/json")
        );
        Request req = new Request.Builder()
            .url("https://api.gubee.com.br/integration/tokens/revalidate/apitoken")
            .post(body).build();
        try (Response res = http.newCall(req).execute()) {
            if (!res.isSuccessful()) {
                throw new RuntimeException("Renovação falhou: " + res.code());
            }
            JsonObject dto = JsonParser.parseReader(res.body().charStream())
                .getAsJsonObject();
            this.jwt = dto.get("token").getAsString();
            this.expiresAtMs = System.currentTimeMillis()
                + dto.get("expiresIn").getAsLong() * 1000L;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Próximos passos