Documentação

“Entrar com a Spaccia”, API de perfis e jogos, webhooks e o widget do Space.

Começo rápido

Crie um app em Desenvolvedores, cadastre o endereço de retorno (redirect_uri) e guarde o client_id e o client_secret. Dados públicos (perfis e jogos) não precisam de token.

curl https://www.spaccia.com/api/v1/users/levi

Entrar com a Spaccia (OAuth 2.0)

Fluxo de código de autorização. Apps só de navegador ou celular (sem servidor) usam PKCE e nunca o client_secret. Apps com servidor podem usar o segredo, PKCE ou os dois.

1. Mande a pessoa para a tela de autorização:

https://www.spaccia.com/oauth/authorize
  ?response_type=code
  &client_id=SEU_CLIENT_ID
  &redirect_uri=https://seuapp.com/callback
  &scope=profile games
  &state=VALOR_ALEATORIO
  &code_challenge=BASE64URL(SHA256(code_verifier))
  &code_challenge_method=S256

2. Ela volta para o seu redirect_uri com ?code=…&state=… (ou ?error=access_denied). Confira se o state é o mesmo que você mandou. O código vale 10 minutos e uma vez só.

3. Troque o código por tokens (no servidor):

curl -X POST https://www.spaccia.com/api/oauth/token \
  -d grant_type=authorization_code \
  -d code=CODIGO \
  -d redirect_uri=https://seuapp.com/callback \
  -d client_id=SEU_CLIENT_ID \
  -d client_secret=SEU_CLIENT_SECRET      # ou: -d code_verifier=...

{ "access_token": "spc_at_…", "token_type": "Bearer", "expires_in": 3600,
  "refresh_token": "spc_rt_…", "scope": "profile games" }

4. Use o token:

curl https://www.spaccia.com/api/v1/me -H "Authorization: Bearer spc_at_…"

O access_token vale 1 hora. Renove com grant_type=refresh_token e refresh_token=… — cada renovação devolve um refresh_token novo e o antigo para de valer. Para sair, mande o token para POST /api/oauth/revoke (token, client_id). A pessoa também pode tirar o acesso do seu app em Configurações → Apps conectados.

Escopos

  • profile — @, nome, foto, bio e selos.
  • email — O e-mail da sua conta Spaccia.
  • games — Jogos, ranks e horas (inclusive os que vieram da Steam e da Riot).
  • connections — Steam, Discord, Twitch e Riot que você conectou e provou que são suas.

profile vem sempre. Escopos separados por espaço em scope.

API

JSON, CORS aberto. Sem token, só o que qualquer visitante vê no Space (a pessoa decide em Configurações → Privacidade). Erros: { "error": "…", "error_description": "…" }.

  • GET /api/v1/users/:username — perfil público, contas verificadas (com “ao vivo” da Twitch e rank do LoL)
  • GET /api/v1/users/:username/games — jogos, ranks e horas públicos
  • GET /api/v1/me — quem autorizou (token; e-mail com email, jogos com games, contas com connections)
  • GET /api/oauth/userinfo — o mesmo que /me, com sub
{
  "id": "cm…", "username": "levi", "name": "Levi", "avatarUrl": "https://…",
  "bio": "Duelista main.", "location": "São Paulo, BR", "plan": "verified",
  "profileType": "personal", "url": "https://www.spaccia.com/levi",
  "stats": { "followers": 3, "following": 3, "posts": 3 },
  "connections": [
    { "platform": "twitch", "handle": "levigg", "verified": true, "live": true,
      "stream": { "title": "Ranked até o Imortal", "game": "VALORANT", "viewers": 1284 } },
    { "platform": "riot", "handle": "Levi#BR1", "verified": true,
      "lol": { "region": "br1", "level": 312, "soloRank": "Esmeralda II" } }
  ]
}

Webhooks

Cadastre uma URL https na página do app e escolha os eventos. A Spaccia manda um POST com JSON quando algo muda para quem autorizou o seu app. Responda 2xx em até 5 segundos. Se falhar, tentamos de novo até 5 vezes, com intervalos crescentes (a partir de 1 minuto; pode levar mais quando há pouco movimento) — e você pode reenviar pelo portal. O mesmo evento pode chegar mais de uma vez: use o Spaccia-Delivery para ignorar repetidos.

  • profile.updated — A pessoa mudou nome, foto, bio ou outros dados do perfil
  • connections.updated — Conectou, verificou ou desconectou uma conta (Steam, Discord, Twitch, Riot)
  • games.updated — Jogos, horas ou ranks importados mudaram
  • grant.revoked — A pessoa tirou o acesso do seu app
  • user.deleted — A pessoa excluiu a conta na Spaccia (apague os dados dela)
POST /seu/webhook
Spaccia-Event: profile.updated
Spaccia-Delivery: cm…
Spaccia-Signature: t=1760000000,v1=5f1c…

{ "id": "evt_…", "type": "profile.updated", "createdAt": "2026-10-06T12:00:00.000Z",
  "data": { "user": { "id": "cm…", "username": "levi" }, "fields": ["bio"] } }

Confira a assinatura antes de confiar no conteúdo: HMAC-SHA256 do segredo do webhook sobre `${t}.${corpo}` (o corpo cru, antes de interpretar o JSON). Recuse eventos com t muito antigo.

import { createHmac, timingSafeEqual } from "node:crypto";

function verificar(corpo, cabecalho, segredo) {
  const { t, v1 } = Object.fromEntries(cabecalho.split(",").map((p) => p.split("=")));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; // 5 min
  const esperado = createHmac("sha256", segredo).update(`${t}.${corpo}`).digest("hex");
  return v1.length === esperado.length && timingSafeEqual(Buffer.from(v1), Buffer.from(esperado));
}

Widget

O cartão de qualquer Space para colar no seu site (mostra só o que é público):

<iframe src="https://www.spaccia.com/embed/levi" width="420" height="230"
  style="border:0;border-radius:16px;max-width:100%" loading="lazy"
  title="Space de levi na Spaccia"></iframe>

Links de Space compartilhados no Discord, WhatsApp e X já mostram uma prévia com foto, jogos e contas verificadas (imagem gerada em /:username/opengraph-image).

Bot do Discord

Comandos /spaccia perfil usuario, /spaccia eu (para quem verificou o Discord na Spaccia) e /spaccia squads jogo. Para colocar no seu servidor, use o botão em Servidores. Mostra só o que é público no Space.

Extensão da Twitch

Painel embaixo da live com o Space do dono do canal (jogos, ranks e contas verificadas). Quem faz live verifica a Twitch em Configurações → Contas conectadas e instala a extensão da Spaccia no painel de criador da Twitch. Os dados vêm de GET /api/twitch/extension/:idDoCanal.

Limites

  • Sem token: 120 requisições por minuto por IP. Com token: 600 por minuto por app e pessoa.
  • Token: 30 trocas por minuto por app e IP.
  • Até 5 apps por conta e 5 endereços de retorno por app.
  • Passou do limite: HTTP 429 — espere um minuto.