Pangeia ID — Guia de Integração (v2.1)

Guia oficial para integrar login Pangeia ID em qualquer site ou app. Uma conta única para o usuário; autenticação server-to-server segura para você.

SDK: pangeia-id.js v2.2.0 — suporta modo popup e modo modal (iframe inline). Compatível com v2, sem breaking changes.

🤖
Usa IA para programar? Cursor, Copilot, Claude, ChatGPT — tem um prompt pronto esperando por você. Pular direto para a seção de integração via IA →

Antes de começar: obtenha sua API Key

Toda chamada server-to-server ao Pangeia ID requer uma API Key. Para obtê-la:

  1. Acesse seu dashboard Pangeia ID e vá para a aba API Keys.
  2. Ative o Modo Desenvolvedor no canto superior direito da seção.
  3. Clique em Gerar nova API Key e informe o nome do seu app.
  4. Copie o valor do campo API Key e guarde no backend do seu app. Nunca exponha no frontend.
PANGEIA_API_KEY=pk_live_...

TL;DR (em 30 segundos)

  1. Adicione o script pangeia-id.js na sua página.
  2. Crie um botão com classe .pangeiaid-login e data-exchange-url.
  3. Implemente no seu backend o endpoint POST /auth/exchange-hash.
  4. Seu backend chama POST /api/auth/exchange-hash no Pangeia com sua API Key.
  5. Com pid + user na resposta, crie a sessão local e pronto.

Passo a Passo (modo newbie)

Passo 1 — Frontend: botão pronto

<button class="pangeiaid-login" data-exchange-url="/auth/exchange-hash">
  Entrar com Pangeia ID
</button>

<script defer src="https://id.pangeialabs.com/static/pangeia-id.js"></script>
<script defer src="/static/js/pangeia-auth.js"></script>

O SDK vincula automaticamente o clique ao botão. Exemplo de /static/js/pangeia-auth.js:

document.addEventListener("pangeia:authenticated", function (ev) {
  // ev.detail.result contém { ok, pid, user }
  console.log("Usuário autenticado:", ev.detail.result.user.name);
  window.location.reload();
});

document.addEventListener("pangeia:cancel", function (ev) {
  // ev.detail.info.reason: "user_closed" | "escape" | "backdrop_click" | "popup_closed" | "popup_blocked" | "timeout"
  console.log("Login cancelado:", ev.detail.info.reason);
});

document.addEventListener("pangeia:error", function (ev) {
  console.error("Erro Pangeia:", ev.detail.error);
});

CSP recomendada (sem unsafe-inline)

Não use onclick/onload no HTML nem <script>...</script> inline — use arquivos externos com defer.

Content-Security-Policy:
  default-src 'self';
  script-src  'self' https://id.pangeialabs.com;
  connect-src 'self' https://id.pangeialabs.com;
  frame-ancestors 'self';
  base-uri 'self';

Passo 2 — Backend: endpoint local de exchange

Esse endpoint recebe o login_hash do SDK e o troca no Pangeia pelo objeto de usuário.

Exemplo Python (Flask)

import os
import requests
from flask import Flask, request, jsonify, session

app = Flask(__name__)
app.secret_key = "troque-isto"

PANGEIA_BASE  = "https://id.pangeialabs.com"
PANGEIA_API_KEY = os.environ["PANGEIA_API_KEY"]

@app.post("/auth/exchange-hash")
def auth_exchange_hash():
    data       = request.get_json() or {}
    login_hash = (data.get("login_hash") or "").strip()
    if not login_hash:
        return jsonify({"ok": False, "error": "login_hash obrigatória"}), 400

    resp = requests.post(
        f"{PANGEIA_BASE}/api/auth/exchange-hash",
        headers={"Authorization": f"Bearer {PANGEIA_API_KEY}", "Content-Type": "application/json"},
        json={"login_hash": login_hash},
        timeout=15,
    )
    out = resp.json()
    if not resp.ok or not out.get("ok"):
        return jsonify(out), resp.status_code

    session["pid"]        = out["pid"]
    session["user_email"] = out["user"]["email"]
    return jsonify(out), 200

Exemplo Node.js (Express)

import express from "express";

const app = express();
app.use(express.json());

const PANGEIA_BASE  = "https://id.pangeialabs.com";
const PANGEIA_API_KEY = process.env.PANGEIA_API_KEY;

app.post("/auth/exchange-hash", async (req, res) => {
  const login_hash = (req.body?.login_hash || "").trim();
  if (!login_hash)
    return res.status(400).json({ ok: false, error: "login_hash obrigatória" });

  const r   = await fetch(`${PANGEIA_BASE}/api/auth/exchange-hash`, {
    method: "POST",
    headers: { "Authorization": `Bearer ${PANGEIA_API_KEY}`, "Content-Type": "application/json" },
    body: JSON.stringify({ login_hash }),
  });
  const out = await r.json();
  return res.status(r.status).json(out);
});

Passo 3 — Consultar dados pelo PID (opcional)

Use quando precisar dos dados do usuário em chamadas posteriores, sem exigir novo login.

curl -X POST https://id.pangeialabs.com/api/user/by-pid \
  -H "Authorization: Bearer SUA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pid":"pid_xxx"}'

Contrato HTTP — endpoints do servidor Pangeia

Todos os endpoints abaixo são chamados pelo seu backend, nunca pelo browser. Autenticação via Authorization: Bearer <api_key>.

Formato de erro padronizado

Toda resposta de erro de validação/negócio segue o shape:

{
  "ok": false,
  "code": "NOME_DO_ERRO",
  "message": "Descrição legível do problema."
}

Exceção: falhas de infraestrutura (ex.: banco de dados temporariamente indisponível durante um failover do cluster) retornam 503 com um shape diferente — {"error": "temporarily_unavailable", "message": "..."}, sem ok nem code. Sempre trate qualquer resposta não-2xx como erro, mesmo quando o shape não bater com o padrão acima.

POST /api/auth/exchange-hash

Body: { "login_hash": "temp_..." }

Resposta de sucesso:

{
  "ok": true,
  "pid": "pid_...",
  "user": {
    "id": "...",
    "name": "...",
    "display_name": "...",
    "username": "nome-de-usuario",
    "aliases": ["nome-de-usuario-alt"],
    "email": "principal@email.com",
    "emails": [{ "email": "outro@email.com", "verified": true }],
    "phone": "...",
    "taxid": "...",
    "birth_date": "...",
    "avatar_url": "https://...",
    "verified_id": false,
    "created_at": "2025-01-10T00:00:00+00:00",
    "updated_at": "2026-06-18T18:07:00+00:00"
  }
}

Campos do objeto user:

Como exibir o selo de conta verificada

Quando verified_id vier true, recomendamos indicar isso visualmente com um selo azul sobreposto ao avatar do usuário, no canto inferior direito — o mesmo padrão usado por redes sociais e apps de mensageria pra indicar contas verificadas. É um símbolo que os usuários já reconhecem; reaproveitar essa posição/cor pra outra coisa (ex: "premium", "online") só gera confusão.

R

← Exemplo de posicionamento correto: selo azul (#1D9BF0) no canto inferior direito do avatar, com um contorno na cor de fundo do seu app pra se destacar.

Código do exemplo acima:

<div style="position: relative; width: 72px; height: 72px;">
  <img src="avatar.jpg" alt="Avatar"
       style="width:100%;height:100%;border-radius:50%;object-fit:cover;" />

  <!-- Selo de conta verificada — só renderize se verified_id === true -->
  <span style="
    position: absolute;
    bottom: -2px;
    right: -2px;
    width: 22px;
    height: 22px;
    background: #1D9BF0;
    border-radius: 50%;
    border: 2.5px solid white;
    display: flex;
    align-items: center;
    justify-content: center;
  ">
    <svg width="13" height="13" viewBox="0 0 24 24" fill="white">
      <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z"/>
    </svg>
  </span>
</div>

Erros possíveis:

POST /api/user/by-pid

Body: { "pid": "pid_..." }

Retorna {"ok": true, "user": {...}} com o mesmo objeto user acima. Atualiza last_access_at do vínculo automaticamente.

Erros possíveis:

GET /api/identity-verification/price

Retorna o valor vigente da anuidade de verificação de conta — use pra informar seus próprios usuários de quanto custa a conta verificada, sem precisar hardcodar o valor no seu app (o preço pode mudar).

curl https://id.pangeialabs.com/api/identity-verification/price \
  -H "Authorization: Bearer SUA_API_KEY"

Resposta:

{
  "ok": true,
  "price": 30.0,
  "currency": "BRL",
  "period": "year"
}

⚠️ price pode vir 0. A anuidade é configurável pelo Pangeia ID e pode ser zerada a qualquer momento. Não assuma um valor sempre maior que zero — trate esse caso na sua própria interface: se o seu app mostra algo como "custa apenas R$ {'{'}price{'}'}", troque a mensagem quando price === 0 em vez de exibir "custa R$ 0,00". Uma boa dica: em vez de mostrar o preço, aproveite pra deixar mais convidativo — algo como "e a boa notícia é que está 100% grátis agora! 🎉", com destaque e uma animação, chama bem mais atenção do que só "grátis".

Erros possíveis:


O que é o PID

O pid (persistent identifier) é o identificador único e permanente de um usuário dentro da sua integração. É gerado automaticamente no primeiro login e reutilizado em todos os logins seguintes do mesmo usuário no mesmo app.

Use o pid como chave primária do usuário na sua base de dados — ele nunca muda, mesmo que o usuário troque e-mail ou username.


Webhook (segurança e consumo)

Configure uma webhook_url na sua integração (aba API Keys do dashboard). O Pangeia enviará eventos assinados a cada mudança relevante no perfil do usuário.

Headers enviados pelo Pangeia

Payload

{
  "version":    "2",
  "event_id":   "evt_...",
  "event_type": "user.updated",
  "timestamp":  "2026-02-14T00:00:00Z",
  "pid":        "pid_...",
  "user": {
    "id": "...",
    "name": "...",
    "display_name": "...",
    "username": "nome-de-usuario",
    "aliases": ["nome-de-usuario-alt"],
    "email": "principal@email.com",
    "emails": [{ "email": "outro@email.com", "verified": true }],
    "phone": "...",
    "taxid": "...",
    "birth_date": "...",
    "avatar_url": "https://...",
    "verified_id": false,
    "created_at": "2025-01-10T00:00:00+00:00",
    "updated_at": "2026-06-18T18:07:00+00:00"
  }
}

Tipos de evento

Campos vazios ("") = o usuário apagou aquela informação

Telefone, CPF e data de nascimento são opcionais no perfil Pangeia ID — o usuário pode apagar qualquer um deles no dashboard dele. Quando isso acontece, o user.updated chega com o campo como string vazia ("") — o campo nunca é omitido do payload, e o Pangeia ID nunca envia null pra esses campos, sempre "". Exceção: enquanto o usuário tiver uma verificação de conta em andamento (documentos enviados, aguardando pagamento ou em revisão) ou aprovada e vigente, CPF e data de nascimento ficam travados e não podem ser apagados nem alterados — só o telefone continua livre nesse período.

Trate "" como "apague esse dado no seu sistema", não como "sem novidade, deixo como está". Se você ignorar um campo vazio, o dado que o usuário explicitamente removeu — o CPF que ele apagou, o telefone que ele tirou do perfil — continua guardado no seu banco, e isso quebra a expectativa dele de que remover ali remove em todo lugar que aceita login Pangeia ID.

A mesma regra vale pra qualquer alteração, em qualquer campo: se name, username, avatar_url etc. mudar, sobrescreva com o valor que veio no evento (ou na resposta mais recente de exchange-hash/by-pid) — nunca faça merge com o que você já tinha, nunca descarte por parecer uma mudança pequena. O Pangeia ID é a fonte de verdade do perfil; seu banco deve refletir exatamente o último payload recebido, campo a campo. Por robustez na sua checagem, trate null e "" como equivalentes mesmo que hoje só "" seja enviado.

Revogação e reconexão: o usuário pode sumir e depois voltar

Revogar (aba "Apps conectados" do dashboard do usuário) desconecta só aquela integração — a conta Pangeia ID dele continua existindo normalmente, com todas as outras integrações intactas. O pid daquele vínculo específico é marcado como revogado pra sempre: a partir do user.revoked, qualquer chamada a POST /api/user/by-pid com esse pid responde 404 PID_NOT_FOUND_OR_REVOKED permanentemente.

Ao receber user.revoked, seu sistema precisa fazer duas coisas ao mesmo tempo:

  1. Ocultar o usuário — ele não deve mais aparecer como logado nem conseguir acessar a conta vinculada àquele pid no seu site/app.
  2. Não impedir ele de voltar. Revogar não é um banimento. Se o mesmo usuário clicar em "Entrar com Pangeia ID" no seu site de novo no futuro, o login tem que funcionar normalmente.

O detalhe importante: esse novo login não reaproveita o pid revogado — o Pangeia ID detecta que o vínculo anterior está revogado e gera um pid novo pra esse mesmo par usuário+integração. Do ponto de vista do seu sistema, um pid novo é um usuário novo, sem ligação nenhuma com o pid antigo.

É por isso que a regra abaixo existe: se o usuário revogou o acesso, ele não pode logar de novo e cair direto na conta antiga como se nada tivesse acontecido — vendo pedidos, mensagens, preferências ou qualquer outro dado que ele já tinha "desconectado" antes. Pra garantir isso:

Validação da assinatura

O HMAC é calculado sobre o body JSON compacto (sem espaços), usando o webhook_secret da integração.

import hmac, hashlib
from flask import request

def verify_signature(raw_body: bytes, signature_header: str, secret: str) -> bool:
    if not signature_header or not signature_header.startswith("sha256="):
        return False
    sent     = signature_header.split("=", 1)[1]
    expected = hmac.new(secret.encode("utf-8"), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(sent, expected)

@app.post("/webhook/pangeia-id")
def webhook():
    raw = request.get_data()
    sig = request.headers.get("X-Pangeia-Signature", "")
    if not verify_signature(raw, sig, secret="SEU_WEBHOOK_SECRET"):
        return {"ok": False, "error": "invalid signature"}, 401

    event = request.get_json() or {}
    event_id   = event["event_id"]   # use para idempotência
    event_type = event["event_type"] # "user.updated" | "user.revoked"
    pid        = event["pid"]
    user       = event["user"]
    # processar e retornar 200 rapidamente (o worker faz retry em falha)
    return {"ok": True}, 200

Retry: o worker faz retentativas com backoff exponencial em caso de falha HTTP. Responda 2xx o mais rápido possível; processe de forma assíncrona se necessário.


Modos de abertura: popup vs modal

ModoComo abreQuando usar
popup (padrão) Nova janela do browser (window.open) Compatibilidade ampla, mas pode ser bloqueado em mobile ou por ad-blockers
modal Overlay full-screen com iframe na mesma aba Recomendado — não sofre bloqueio de popup, melhor UX em mobile

Ativando o modo modal

Via atributo no botão:

<button class="pangeiaid-login" data-mode="modal" data-exchange-url="/auth/exchange-hash">
  Entrar com Pangeia ID
</button>

Via JavaScript:

PangeiaID.openLogin({
  mode: "modal",
  exchange: {
    enabled: true,
    url: "/auth/exchange-hash",
  },
  onAuthenticated: function (result) {
    // result = { ok, pid, user }
    window.location.reload();
  },
  onCancel: function (info) {
    // info.reason: ver tabela abaixo
    console.log("Cancelado:", info.reason);
  },
  onError: function (err) {
    // err.code + err.message + err.retriable
    console.error("Erro:", err.code, err.message);
  },
});

O modal fecha automaticamente após autenticação. O usuário também pode fechar clicando no ×, fora do modal ou pressionando Escape.

Abrindo direto na aba de cadastro

Por padrão o modal/popup abre na aba Entrar. Para abrir já na aba Criar conta — útil quando seu site tem botões separados de "Entrar" e "Criar conta grátis" — passe screen: "register". Sem essa opção, nada muda para quem já integra hoje.

<button class="pangeiaid-login" data-mode="modal" data-exchange-url="/auth/exchange-hash">
  Entrar
</button>
<button class="pangeiaid-login" data-mode="modal" data-exchange-url="/auth/exchange-hash" data-screen="register">
  Criar conta grátis
</button>

Via JavaScript, basta informar screen na chamada correspondente a cada botão:

document.getElementById("btn-entrar").addEventListener("click", function () {
  PangeiaID.openLogin({ mode: "modal", screen: "login", exchange: { enabled: true, url: "/auth/exchange-hash" }, /* ... */ });
});
document.getElementById("btn-criar-conta").addEventListener("click", function () {
  PangeiaID.openLogin({ mode: "modal", screen: "register", exchange: { enabled: true, url: "/auth/exchange-hash" }, /* ... */ });
});

CSP adicional para modo modal

Content-Security-Policy:
  default-src 'self';
  script-src  'self' https://id.pangeialabs.com;
  connect-src 'self' https://id.pangeialabs.com;
  frame-src   https://id.pangeialabs.com;
  base-uri    'self';

Referência do SDK

PangeiaID.openLogin(options)

Abre o fluxo de login programaticamente. Útil quando o auto-bind do botão não é suficiente.

💡
Sempre inclua exchange.enabled: true junto com exchange.url. Desde a versão 2.1.2 do SDK, informar exchange.url já liga o exchange automaticamente mesmo sem enabled: true — mas escreva os dois campos explicitamente mesmo assim, é mais claro pra quem ler o código depois. Se por algum motivo exchange.url não chegar a ser configurado, o modo modal falha alto e visível (erro INVALID_CONFIG); o modo popup falha silenciosamente — o login completa no Pangeia ID e seu backend nunca é chamado, sem erro em lugar nenhum. Veja o exemplo completo logo abaixo.
OpçãoTipoPadrãoDescrição
modestring"popup""popup" ou "modal"
screenstring"login"Aba inicial: "login" ou "register"
exchange.enabledbooleaninferido de exchange.urlLiga o exchange server-to-server. Recomendado declarar true explicitamente por clareza, mas informar exchange.url já basta (desde a v2.1.2 do SDK).
exchange.urlstringEndpoint local de exchange (obrigatório para usar exchange)
exchange.methodstring"POST"Método HTTP do exchange
exchange.credentialsstring"include"Política de cookies do fetch
exchange.timeoutMsnumber15000Timeout do exchange em ms
exchange.headersobject{"Content-Type":"application/json"}Headers customizados para o exchange
onAuthenticated(result)functionChamado com o objeto de resposta do exchange
onCancel(info)functionChamado quando o usuário fecha sem autenticar
onError(err)functionChamado em erros de configuração ou de rede

Callback: onAuthenticated(result)

result é a resposta do seu endpoint de exchange — normalmente o objeto retornado pelo Pangeia:

{ ok: true, pid: "pid_...", user: { name, email, username, ... } }

Callback: onCancel(info)

info.reasonQuando ocorre
user_closedUsuário clicou no botão × do modal/popup
escapeUsuário pressionou Escape
backdrop_clickUsuário clicou fora do modal (modo modal)
popup_closedUsuário fechou a janela popup manualmente
popup_blockedBrowser bloqueou a abertura do popup
timeoutTempo limite excedido sem autenticação
already_openTentativa de abrir modal já aberto

Callback: onError(err)

O objeto err tem os campos code, message, retriable e opcionalmente cause.

err.codeCausa
INVALID_CONFIGexchange.url ausente ou configuração inválida
EXCHANGE_HTTP_ERRORSeu endpoint de exchange retornou HTTP 4xx/5xx
EXCHANGE_INVALID_RESPONSEResposta do exchange não contém "ok": true
EXCHANGE_TIMEOUTTimeout atingido na chamada ao exchange
EXCHANGE_NETWORK_ERRORFalha de rede na chamada ao exchange
PANGEIA_MESSAGE_INVALIDMensagem postMessage do Pangeia veio incompleta

Eventos DOM

Além dos callbacks, o SDK dispara eventos no document — útil para ouvir em múltiplos pontos da página.

Eventoev.detail
pangeia:authenticated{ element, result }result é a resposta do exchange
pangeia:cancel{ element, info }info.reason conforme tabela acima
pangeia:error{ element, error }error.code conforme tabela acima

element é o botão .pangeiaid-login que originou o fluxo (disponível apenas no auto-bind).

PangeiaID.init(options)

Chamado automaticamente no DOMContentLoaded. Pode ser chamado manualmente para configurar callbacks globais ou um seletor customizado.

PangeiaID.init({
  selector:        ".meu-botao-login", // padrão: ".pangeiaid-login"
  mode:            "modal",            // padrão para todos os botões sem data-mode
  exchange: {
    url:         "/auth/exchange-hash",
    credentials: "include",
  },
  onAuthenticated: function (result, element) { /* ... */ },
  onCancel:        function (info,   element) { /* ... */ },
  onError:         function (err,    element) { /* ... */ },
});

Configuração por data-* (auto-bind)

Atributos disponíveis no elemento .pangeiaid-login:

AtributoPadrãoDescrição
data-modepopuppopup ou modal
data-screenloginAba inicial: login ou register
data-exchange-urlEndpoint local de exchange (obrigatório)
data-exchange-methodPOSTMétodo HTTP do exchange
data-exchange-credentialsincludePolítica de cookies do fetch
data-exchange-timeout-ms15000Timeout em ms
data-exchange-payload-keylogin_hashNome do campo enviado ao exchange
data-exchange-headers{"Content-Type":"application/json"}JSON com headers customizados para o exchange

FAQ

Popup ou modal — qual escolher?
Modal. Não sofre bloqueio de popup, funciona melhor em mobile e tem UX mais fluida. Popup fica disponível para casos que exijam janela separada.

Preciso expor a API Key no frontend?
Não. A API Key fica exclusivamente no backend. O frontend não carrega credenciais.

Como identificar o usuário no meu banco?
Use o pid. É persistente e único por usuário por integração — nunca muda mesmo que o usuário troque e-mail ou username.

Meu endpoint de exchange deve retornar exatamente o que o Pangeia retorna?
Sim — o SDK valida se a resposta contém "ok": true. Retornar o objeto inteiro do Pangeia é o caminho mais simples.

O webhook pode chegar mais de uma vez com o mesmo event_id?
Sim, em caso de retry. Sempre persista o event_id e ignore eventos já processados.

Como obter o webhook_secret?
Ele é gerado automaticamente ao criar a integração e exibido no dashboard em "API Keys". Você pode rotacioná-lo a qualquer momento.

Como sei se um usuário tem conta verificada?
Campo verified_id no objeto user (exchange-hash, by-pid e webhooks). Fica true só enquanto a verificação estiver aprovada e dentro da validade de 1 ano. O webhook user.updated dispara toda vez que esse campo muda — não só quando vira true (aprovação/renovação), mas também quando volta a false (expiração sem renovação, ou verificação removida por um admin).

O verified_id de um usuário voltou pra false sem ele ter deixado a verificação expirar — o que houve?
Um admin do Pangeia ID pode remover uma verificação manualmente (ex.: documento enviado por engano, suspeita de fraude, pedido do próprio usuário). Isso dispara user.updated igual a uma expiração normal — trate do mesmo jeito, sem tratamento especial: esconda o selo de verificado assim que verified_id vier false, independente do motivo.

Um campo do usuário chegou como "" — foi bug, ou o usuário apagou de propósito?
Ele apagou de propósito. Telefone, CPF e data de nascimento são opcionais e o usuário pode removê-los a qualquer momento — o campo vem como string vazia, nunca omitido, nunca null. Apague o dado correspondente no seu sistema também. Veja "Campos vazios" na seção de webhook.

Um usuário que revogou o acesso pode voltar a logar no meu site depois?
Sim, e o login funciona normalmente — revogar desconecta a integração, não bane a pessoa. Mas ele volta com um pid novo, nunca o revogado. Trate isso como um usuário novo, sem ligação com a conta antiga: qualquer dado que você tenha retido daquele pid revogado por obrigação legal precisa ficar num histórico isolado, nunca visível a partir do pid novo. Veja "Revogação e reconexão" na seção de webhook.


Checklist de go-live

  1. API Key salva em variável de ambiente no backend (nunca no frontend).
  2. Botão com .pangeiaid-login e data-exchange-url funcionando.
  3. Endpoint local /auth/exchange-hash criado e testado.
  4. Sessão local criada após exchange com sucesso (pid salvo).
  5. Webhook configurado, assinatura validada e idempotência por event_id implementada.
  6. Campo vazio ("") em user.updated é tratado como remoção do dado no seu sistema, não ignorado.
  7. user.revoked oculta o usuário sem apagar dados de guarda legal obrigatória — e, se ele voltar com um pid novo, esses dados retidos não resurgem na conta dele.
  8. CSP configurada (adicionar frame-src se usar modo modal).

Integrando com ajuda de IA

Se você usa IA para programar (Cursor, GitHub Copilot, Claude, ChatGPT etc.), o fluxo é simples: você faz a parte do dashboard manualmente (leva 2 minutos) e passa um prompt pronto para a IA implementar todo o resto.

Passo 1 — Prepare o dashboard (você faz, não a IA)

  1. Acesse seu dashboard e vá para a aba API Keys.
  2. Ative o Modo Desenvolvedor no canto superior direito da seção.
  3. Clique em Gerar nova API Key, informe o nome do seu app e salve.
  4. Copie o valor da API Key (começa com pk_live_) — vai para uma variável de ambiente no seu backend.
  5. Copie o Webhook Secret (começa com whsec_) — também vai para variável de ambiente.
  6. No campo URL do Webhook, informe o endpoint do seu backend que vai receber os eventos do Pangeia (ex: https://seusite.com.br/webhooks/pangeia). Pode deixar em branco agora e preencher depois.
  7. Salve a integração.

Passo 2 — Passe este prompt para a sua IA

Substitua os valores em caixa alta e cole direto no chat da sua IA:

Preciso integrar o Pangeia ID (SSO brasileiro) no meu projeto.

Leia a documentação em https://id.pangeialabs.com/apidoc e implemente a integração completa.

Minhas credenciais (use SOMENTE no backend, nunca no frontend ou no código versionado):
- API Key: pk_live_COLE_AQUI
- Webhook Secret: whsec_COLE_AQUI
- URL do meu webhook: https://MEU_SITE/MEU_ENDPOINT_WEBHOOK