Começar
Autenticação
Duas formas de acesso. A chave de API serve para as subcontas que você cria; o OAuth2 serve para agir, com consentimento, na conta Sellume de um vendedor.
| Forma | Para quê | Como vai no pedido |
|---|---|---|
| Chave de API | Agir nas suas subcontas e na sua carteira | Authorization: Bearer sk_test_… ou sk_live_… |
| OAuth2 (PKCE) | Agir na conta Sellume de um vendedor que autorizou o seu app (conta vinculada) | Authorization: Bearer oat_test_… ou oat_live_… |
Chave de API#
- Formato:
sk_test_ousk_live_, seguido de um identificador de 12 caracteres,_e um segredo de 40 caracteres. Exemplo:sk_test_ab12cd34ef56_+ 40 caracteres. - Ambiente pelo prefixo:
sk_test_= teste grátis com mídia de exemplo;sk_live_= produção. - Aparece uma única vez, na criação, no portal (Chaves de API). O Sellume guarda só uma impressão (hash) e confere em tempo constante: ninguém consegue ver a chave de novo.
- Escopos: a chave do integrador tem todos os escopos.
- Só no servidor: nunca no navegador, num app instalado ou num repositório. Se vazar, revogue no portal e crie outra: a revogação vale na hora.
- A
sk_live_só pode ser criada depois do acesso de produção.
curl -s $B/saldo -H "Authorization: Bearer sk_test_ab12cd34ef56_…"Chave ausente, inválida ou revogada: 401 UNAUTHORIZED. Integrador pausado: 403 INTEGRATOR_PAUSED.
OAuth2 para contas vinculadas#
Use o OAuth2 quando o seu cliente já é cliente do Sellume e você quer agir na conta Sellume dele, com o consentimento dele. Essa conta aparece na API com origem: vinculada.
- O que você pede por essa conta é pago pela carteira do integrador, no mesmo preço do seu contrato.
- Para clientes que não têm conta no Sellume, não use OAuth: crie subcontas com a chave de API.
- O vendedor continua usando o app do Sellume normalmente e pode revogar o acesso quando quiser.
- Na tela de consentimento o vendedor fica sabendo que você verá o nome da conta dele (não o e-mail).
Apps OAuth no portal#
Cadastre o app no portal, em Apps OAuth:
| Campo | Regra |
|---|---|
| Nome | O nome que o vendedor vê na tela de consentimento. |
| Ambiente | Teste ou produção. Produção só depois do acesso de produção liberado. |
| Tipo | Confidencial (roda num servidor, tem client_secret) ou público (app instalado ou de desktop, sem segredo). |
| Redirect URIs | Endereços exatos, em HTTPS, até 5. No app de teste também valem http://localhost e http://127.0.0.1 com porta. |
| Escopos permitidos | O máximo que o app pode pedir (veja abaixo). |
Você recebe o client_id (app_ + 26 caracteres) e, no app confidencial, o client_secret (cs_test_… ou cs_live_…), que aparece uma única vez. O Sellume guarda só o hash. Trocar o segredo invalida o anterior na hora. Até 10 apps ativos por integrador.
Escopos#
| Escopo | Permite | Por OAuth |
|---|---|---|
contas:ler | Ler a conta vinculada | sim |
produtos:ler | Ler produtos e conferências | sim |
produtos:escrever | Enviar e remover fichas de produto | sim |
geracoes:ler | Ler gerações e baixar resultados | sim |
geracoes:criar | Criar galerias, vídeos e edições (debita a carteira do integrador) | sim |
contas:escrever | Criar e alterar subcontas | não, só chave de API |
creditos:ler | Saldo, extrato, plano e cota do mês | não, só chave de API |
creditos:comprar | Link de pagamento de pacote avulso | não, só chave de API |
avisos:gerenciar | Endereços de aviso | não, só chave de API |
Peça só o que o app usa. Os avisos de uma conta vinculada chegam nos endereços de aviso que você cadastrou com a chave de API, com o contaId da conta vinculada.
PKCE: code_verifier e code_challenge#
PKCE com S256 é obrigatório para todos os apps, inclusive os confidenciais. Para cada autorização, gere um code_verifier aleatório (43 a 128 caracteres de A-Z a-z 0-9 - . _ ~) e envie o code_challenge = BASE64URL(SHA-256(code_verifier)), sem = no fim. Guarde o code_verifier e o state na sessão do usuário.
import { createHash, randomBytes } from 'node:crypto';
const codeVerifier = randomBytes(32).toString('base64url'); // 43 caracteres
const codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');
const state = randomBytes(16).toString('base64url');<?php
function base64url(string $bytes): string {
return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
}
$codeVerifier = base64url(random_bytes(32)); // 43 caracteres
$codeChallenge = base64url(hash('sha256', $codeVerifier, true));
$state = base64url(random_bytes(16));import base64, hashlib, secrets
code_verifier = secrets.token_urlsafe(32) # 43 caracteres
code_challenge = base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest()).rstrip(b"=").decode()
state = secrets.token_urlsafe(16)Passo 1: levar o vendedor à autorização#
Redirecione o navegador do vendedor para:
https://app.sellume.com.br/oauth/autorizar?response_type=code
&client_id=app_…
&redirect_uri=https%3A%2F%2Ferp.exemplo.com.br%2Foauth%2Fretorno
&scope=contas:ler%20produtos:escrever%20geracoes:criar
&state=<aleatório>
&code_challenge=<BASE64URL(SHA256(code_verifier))>
&code_challenge_method=S256(Tudo numa linha só; as quebras acima são só para leitura.) O vendedor entra com a conta Sellume dele e vê a tela de consentimento: o nome do app, quem é o integrador, o que o app poderá fazer e que o integrador verá o nome da conta (não o e-mail).
- Autorizou: volta para
redirect_uri?code=oac_…&state=…. - Cancelou: volta para
redirect_uri?error=access_denied&state=…. - Outros erros que voltam pelo redirecionamento:
invalid_request,invalid_scope,unsupported_response_typeeserver_error. client_idouredirect_uriinválidos nunca redirecionam: a própria tela mostra o erro.
O código vale 60 segundos e uma vez só. Reusar um código revoga os tokens emitidos com ele. Um code_verifier errado também invalida o código e encerra a autorização: peça ao vendedor para autorizar de novo (gere um code_verifier novo a cada autorização e guarde-o junto do state).
Passo 2: trocar o código por tokens#
POST https://api.sellume.com.br/oauth/token, com Content-Type: application/x-www-form-urlencoded (JSON também é aceito).
App confidencial: autentique por HTTP Basic (client_id:client_secret) ou mande client_id e client_secret no corpo. App público: mande só o client_id.
T=https://api.sellume.com.br/oauth/token
curl -s -X POST $T \
-d grant_type=authorization_code \
-d code="oac_…" \
--data-urlencode redirect_uri="https://erp.exemplo.com.br/oauth/retorno" \
-d code_verifier="$CODE_VERIFIER" \
-d client_id="app_…" \
-d client_secret="$CLIENT_SECRET"{
"access_token": "oat_test_…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "ort_test_…",
"scope": "contas:ler produtos:escrever geracoes:criar",
"conta_id": "cta_…"
}A redirect_uri precisa ser igual à do passo 1. Referência: POST/oauth/token.
Usar o token#
Use Authorization: Bearer oat_test_… nos mesmos endpoints /v1, com o mesmo formato de resposta e de erros.
- O token só enxerga a conta vinculada (
conta_id): GET/contasdevolve só ela; qualquer outro id responde404. - Rotas do integrador respondem
403FORBIDDEN para token OAuth:/saldo,/extrato,/plano,/planos,/cota-do-mes,/recargas,/avisos…,/integracao/status,/integracao/chamadas…,/integracao/pedido-producaoePOST /contas. - GET
/integracao/errosvale para os dois. oat_test_= ambiente de teste (mídia de exemplo, sem custo);oat_live_= produção.
curl -s $B/contas -H "Authorization: Bearer oat_test_…"Renovar com o refresh token#
O access token vale 1 hora. O refresh token vale 30 dias e é rotativo: cada uso devolve um novo par e invalida o refresh anterior. Você pode pedir um escopo menor com scope.
curl -s -X POST $T \
-d grant_type=refresh_token \
-d refresh_token="ort_test_…" \
-d client_id="app_…" \
-d client_secret="$CLIENT_SECRET"Revogar#
curl -s -X POST https://api.sellume.com.br/oauth/revogar \
-d token="ort_test_…" -d client_id="app_…" -d client_secret="$CLIENT_SECRET"Aceita access ou refresh token, responde 200 sempre (RFC 7009) e encerra a autorização inteira.
O vendedor também revoga quando quiser em app.sellume.com.br/oauth/autorizacoes. A partir daí o token responde 401 UNAUTHORIZED ("autorização revogada") e a conta vinculada fica pausada. Se o vendedor autorizar de novo, a mesma conta volta: mesmo cta_ e produtos mantidos.
Limites do OAuth#
- 60 chamadas por minuto ao endpoint de token, por app. Passou:
429temporarily_unavailablecomRetry-After. - 20 falhas de autenticação do app em 10 minutos bloqueiam o app por 10 minutos (também
429temporarily_unavailable, com oRetry-Afteraté o fim do bloqueio). - Até 10 autorizações do mesmo vendedor no mesmo app em 10 minutos.
- Até 10 apps ativos por integrador.
Erros do endpoint de token#
Formato RFC 6749: {"error": "…", "error_description": "… em português"}.
| Erro | HTTP | Quando |
|---|---|---|
invalid_request | 400 | Falta um parâmetro obrigatório ou algum parâmetro veio repetido. |
invalid_client | 401 | client_id ou client_secret errado, ou o app está desativado. |
invalid_grant | 400 | Código inválido, vencido ou já usado; redirect_uri diferente do usado na autorização; code_verifier que não confere com o code_challenge; ou refresh token inválido, vencido ou reusado. |
unauthorized_client | 400 | O app não pode usar este tipo de concessão. |
unsupported_grant_type | 400 | grant_type desconhecido. |
invalid_scope | 400 | Escopo fora dos permitidos do app ou maior que o autorizado pelo vendedor. |
temporarily_unavailable | 429 | Muitas chamadas ao endpoint de token pelo mesmo app. |
Causa e como corrigir de cada um: Catálogo de erros › OAuth.