Autenticação
A API Groups usa dois tipos de autenticação dependendo do recurso:
- Platform Admin JWT — para gerenciar Groups via
/platform/v1/groups/*. Obtenha em admin.superdb.com.br. - Group API Key — para provisionar e gerenciar tenants via
/groups/v1/*. Gerada ao criar um Group no Admin UI — aparece apenas uma vez.
Group API Key é secreta. Nunca exponha no frontend. Guarde no .env do seu backend e jamais comite no git.
Todos os endpoints retornam JSON e aceitam Content-Type: application/json.
Endpoints de Platform Admin
Requerem Authorization: Bearer <platform_admin_jwt>. Use para configurar Groups no Admin UI ou via scripts de automação.
POST /platform/v1/groups
Cria um novo Group associado a um projeto template.
POST https://auth.superdb.com.br/platform/v1/groups
Authorization: Bearer <platform_admin_jwt>
Content-Type: application/json
{
"name": "ERP Clínicas",
"description": "Template para sistemas de gestão de clínicas médicas",
"template_project_id": "proj_erp_clinica_template"
}
{
"id": "grp_a1b2c3d4e5f6",
"name": "ERP Clínicas",
"description": "Template para sistemas de gestão de clínicas médicas",
"template_project_id": "proj_erp_clinica_template",
"tenant_count": 0,
"created_at": "2026-05-14T10:30:00Z"
}
const resp = await fetch('https://auth.superdb.com.br/platform/v1/groups', {
method: 'POST',
headers: {
'Authorization': `Bearer ${platformAdminJwt}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'ERP Clínicas',
template_project_id: 'proj_erp_clinica_template',
}),
})
const group = await resp.json()
GET /platform/v1/groups
Lista todos os Groups da plataforma.
curl https://auth.superdb.com.br/platform/v1/groups \
-H "Authorization: Bearer $PLATFORM_ADMIN_JWT"
[
{
"id": "grp_a1b2c3d4e5f6",
"name": "ERP Clínicas",
"tenant_count": 12,
"created_at": "2026-05-14T10:30:00Z"
},
{
"id": "grp_x9y8z7w6v5u4",
"name": "Gestão Escolar",
"tenant_count": 4,
"created_at": "2026-05-10T08:15:00Z"
}
]
GET /platform/v1/groups/:id
Retorna detalhes de um Group específico.
curl https://auth.superdb.com.br/platform/v1/groups/grp_a1b2c3d4e5f6 \
-H "Authorization: Bearer $PLATFORM_ADMIN_JWT"
DELETE /platform/v1/groups/:id
Deleta um Group. Retorna 409 Conflict se o Group ainda tiver tenants ativos.
curl -X DELETE https://auth.superdb.com.br/platform/v1/groups/grp_a1b2c3d4e5f6 \
-H "Authorization: Bearer $PLATFORM_ADMIN_JWT"
# Response: 204 No Content (sucesso)
# Response: 409 Conflict (group tem tenants ativos)
Endpoints de Group API (tenants)
Requerem Authorization: Bearer <group_api_key>. Use no backend do seu SaaS para provisionar clientes.
POST /groups/v1/:group_id/tenants
Provisiona um novo tenant para o Group. Esta é a operação mais importante — chame quando um novo cliente se cadastrar no seu SaaS.
O SuperDB clona o schema template, cria as tabelas de auth, gera o role Postgres dedicado e retorna as keys em ~1-2 segundos.
POST https://auth.superdb.com.br/groups/v1/grp_a1b2c3d4e5f6/tenants
Authorization: Bearer <group_api_key>
Content-Type: application/json
{
"slug": "clinica_sao_lucas",
"external_id": "company_789",
"metadata": {
"cnpj": "12.345.678/0001-99",
"plan": "professional",
"admin_email": "dr.pedro@saolucas.com.br"
}
}
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
slug |
string | Sim | Identificador único. Só letras minúsculas, números e underscore. |
external_id |
string | Não | ID do cliente no seu banco de dados. |
metadata |
object | Não | JSON livre. Armazenado mas não indexado. |
{
"tenant": {
"id": "ten_f7e8d9c0b1a2",
"slug": "clinica_sao_lucas",
"schema_name": "proj_clinica_sao_lucas",
"external_id": "company_789",
"group_id": "grp_a1b2c3d4e5f6",
"metadata": { "cnpj": "12.345.678/0001-99", "plan": "professional" },
"created_at": "2026-05-14T11:45:00Z"
},
"anon_key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiYW5vbiIsInRlbmFudCI6ImNsaW5pY2Ffc2FvX2x1Y2FzIn0.XXXX",
"service_role_key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoic2VydmljZV9yb2xlIn0.YYYY"
}
Salve as keys imediatamente. O service_role_key não é armazenado no SuperDB após a criação — por segurança. Se perder, precisará revogar e gerar novas keys.
interface ProvisionResult {
tenant: {
id: string
slug: string
schema_name: string
external_id?: string
created_at: string
}
anon_key: string
service_role_key: string
}
export async function provisionTenant(params: {
slug: string
externalId?: string
metadata?: Record<string, unknown>
}): Promise<ProvisionResult> {
const url = `${process.env.SUPERDB_BASE_URL}/groups/v1/${process.env.SUPERDB_GROUP_ID}/tenants`
const resp = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERDB_GROUP_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
slug: params.slug,
external_id: params.externalId,
metadata: params.metadata,
}),
})
if (!resp.ok) {
const error = await resp.text()
throw new Error(`Provisioning falhou (${resp.status}): ${error}`)
}
return resp.json() as Promise<ProvisionResult>
}
GET /groups/v1/:group_id/tenants
Lista todos os tenants de um Group.
curl "https://auth.superdb.com.br/groups/v1/grp_a1b2c3d4e5f6/tenants?limit=20&offset=0" \
-H "Authorization: Bearer $SUPERDB_GROUP_API_KEY"
{
"tenants": [
{
"id": "ten_f7e8d9c0b1a2",
"slug": "clinica_sao_lucas",
"external_id": "company_789",
"created_at": "2026-05-14T11:45:00Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}
GET /groups/v1/:group_id/tenants/:id
Retorna detalhes de um tenant específico. Não retorna as keys (por segurança).
curl "https://auth.superdb.com.br/groups/v1/grp_a1b2c3d4e5f6/tenants/ten_f7e8d9c0b1a2" \
-H "Authorization: Bearer $SUPERDB_GROUP_API_KEY"
DELETE /groups/v1/:group_id/tenants/:id
Deleta um tenant e apaga o schema Postgres — operação irreversível. Todos os dados do tenant são removidos.
IRREVERSÍVEL. Esta operação executa DROP SCHEMA tenant_xyz CASCADE. Faça backup antes. Confirme o slug do tenant antes de chamar.
curl -X DELETE \
"https://auth.superdb.com.br/groups/v1/grp_a1b2c3d4e5f6/tenants/ten_f7e8d9c0b1a2" \
-H "Authorization: Bearer $SUPERDB_GROUP_API_KEY"
# Response: 204 No Content
export async function deleteTenant(tenantId: string): Promise<void> {
const url = `${process.env.SUPERDB_BASE_URL}/groups/v1/${process.env.SUPERDB_GROUP_ID}/tenants/${tenantId}`
const resp = await fetch(url, {
method: 'DELETE',
headers: {
'Authorization': `Bearer ${process.env.SUPERDB_GROUP_API_KEY}`,
},
})
if (!resp.ok && resp.status !== 204) {
throw new Error(`Deleção falhou: ${resp.status}`)
}
}
Códigos de erro
| Status | Código | Descrição |
|---|---|---|
400 |
invalid_slug |
Slug contém caracteres inválidos ou está vazio. |
401 |
unauthorized |
Token ausente, expirado ou inválido. |
403 |
forbidden |
API Key não tem permissão para este Group. |
409 |
slug_conflict |
Slug já existe neste Group. |
422 |
provisioning_failed |
Erro interno ao clonar o schema. Tente novamente. |
429 |
rate_limited |
Muitas requisições. Máximo 10 provisionamentos/minuto. |