KemOS API — Documentação para Integradores
A API do KemOS permite que ISPs e revendedores provisionem automaticamente acesso ao Hub de IA para seus clientes de internet. Integre seu formulário de cadastro, ERP, sistema de billing ou SGP diretamente com o KemOS.
POST /api/v1/provisioning/sub-tenants para ativar o Hub IA de um cliente.Content-Type: application/json em todas as requisições com body.
Primeiros Passos
Siga os três passos abaixo para fazer sua primeira chamada à API em menos de 5 minutos.
X-API-Key de todas as requisições. Teste com um GET /api/v1/provisioning/sub-tenants para listar os clientes existentes.API Keys
O KemOS utiliza autenticação via API Key passada no header de cada requisição. Não há necessidade de tokens OAuth ou sessões.
Headers obrigatórios
Todas as requisições devem incluir os seguintes headers:
Como gerar uma API Key
Acesse Configurações → Integrações → Chaves de API → Gerar Nova Chave no painel do KemOS. Defina um nome descritivo para identificar a origem da integração (ex: "SGP Produção", "n8n Billing").
Rotação de chaves
Recomendamos rotacionar as API Keys a cada 90 dias ou sempre que um colaborador com acesso à chave deixar o time. Chaves revogadas param de funcionar imediatamente.
X-API-Key: sua-api-key-aqui
Content-Type: application/json
curl -X GET \
https://app.kemsolucoes.com.br/api/v1/provisioning/sub-tenants \
-H "X-API-Key: sua-api-key-aqui" \
-H "Content-Type: application/json"
Visão Geral
A Provisioning API permite criar e gerenciar sub-tenants — os clientes finais do seu provedor que terão acesso ao Hub de IA. Sub-tenants herdam automaticamente suas configurações de integração (EvoGo, n8n, SMTP) sem precisar configurar nada.
Base URL
https://app.kemsolucoes.com.br/api/v1
Recursos disponíveis
| Método | Endpoint | Descrição |
|---|---|---|
| POST | /provisioning/sub-tenants |
Cria e ativa um sub-tenant |
| GET | /provisioning/sub-tenants |
Lista sub-tenants paginados |
| GET | /provisioning/sub-tenants/{id} |
Busca um sub-tenant por UUID |
| PATCH | /provisioning/sub-tenants/{id} |
Atualiza dados do sub-tenant |
| DELETE | /provisioning/sub-tenants/{id} |
Desativa o acesso ao Hub IA |
Exemplo mínimo
BASE="https://app.kemsolucoes.com.br/api/v1"
KEY="sua-api-key-aqui"
# Listar sub-tenants
curl "$BASE/provisioning/sub-tenants" \
-H "X-API-Key: $KEY"
POST Criar Sub-tenant
Cria um novo cliente e ativa automaticamente os módulos do plano contratado. Se o e-mail já existir no sistema, retorna erro EMAIL_ALREADY_EXISTS.
Parâmetros do body
| Campo | Tipo | Required | Descrição |
|---|---|---|---|
| name | string | ✅ Sim | Nome completo do cliente |
| string | ✅ Sim | E-mail de acesso ao Hub IA | |
| cpf | string | ✅ Sim | CPF somente números (11 dígitos) |
| phone | string | ✅ Sim | Telefone com DDD, somente números |
| plan | string | Não |
UUID de um plano do revendedor (criado em /planos) ou ID de plano global ("hub-ia-solo", "hub-ia-revendedor"). Quando é um UUID de plano do revendedor, os módulos configurados naquele plano são ativados automaticamente. Padrão: "hub-ia-solo".
Plano do revendedor (recomendado): "plan": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
Plano global (legado): "plan": "hub-ia-solo"
|
| password | string | Não | Senha inicial. Se omitido, gera automaticamente |
| send_welcome | boolean | Não | Envia boas-vindas por e-mail/WhatsApp (padrão: true) |
| metadata | object | Não | Campos livres para referência interna (SGP ID, contrato etc.) |
Códigos de status
Interface demonstrativa — nenhuma requisição real é enviada por esta página.
Requisição
curl -X POST \
https://app.kemsolucoes.com.br/api/v1/provisioning/sub-tenants \
-H "X-API-Key: sua-api-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "João da Silva",
"email": "joao@email.com",
"cpf": "12345678900",
"phone": "11999999999",
"plan": "hub-ia-solo",
"send_welcome": true,
"metadata": {
"sgp_client_id": "22776",
"contrato": "22846"
}
}'
Respostas
{
"ok": true,
"status": "created",
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "joao@email.com",
"name": "João da Silva",
"plan": "hub-ia-solo",
"portal_url": "https://app.kemsolucoes.com.br",
"parent_tenant_id": "c130602d-7fcf-4623-966c-b91e19444b6f",
"group": "Clientes Hub IA",
"modules": ["hub-ia"],
"credentials": {
"email": "joao@email.com",
"temporary_password": "Mudar@2026Hub"
},
"created_at": "2026-07-31T22:00:00Z"
}
}
{
"ok": true,
"status": "already_active",
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "joao@email.com"
}
}
GET Listar Sub-tenants
Retorna uma lista paginada de todos os sub-tenants vinculados ao seu tenant, com suporte a filtros por status e busca textual.
Query parameters
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
| page | integer | 1 |
Número da página |
| limit | integer | 20 |
Itens por página (máx. 100) |
| status | string | — | Filtrar por status: active ou inactive |
| search | string | — | Busca por nome ou e-mail |
Códigos de status
Requisição
curl -X GET \
"https://app.kemsolucoes.com.br/api/v1/provisioning/sub-tenants?page=1&limit=20&status=active" \
-H "X-API-Key: sua-api-key-aqui"
Resposta 200
{
"ok": true,
"data": [
{
"id": "a1b2c3d4-...",
"email": "joao@email.com",
"name": "João da Silva",
"plan": "hub-ia-solo",
"status": "active",
"created_at": "2026-07-31T22:00:00Z"
}
],
"meta": {
"total": 47,
"page": 1,
"limit": 20,
"pages": 3
}
}
GET Buscar Sub-tenant
Retorna os dados completos de um sub-tenant específico, incluindo plano, status, módulos ativos e metadata.
Path parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
| id | uuid | UUID do sub-tenant (retornado no POST) |
Códigos de status
Requisição
curl -X GET \
"https://app.kemsolucoes.com.br/api/v1/provisioning/sub-tenants/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "X-API-Key: sua-api-key-aqui"
Resposta 200
{
"ok": true,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "joao@email.com",
"name": "João da Silva",
"phone": "11999999999",
"plan": "hub-ia-solo",
"status": "active",
"modules": ["hub-ia"],
"group": "Clientes Hub IA",
"parent_tenant_id": "c130602d-7fcf-4623-966c-b91e19444b6f",
"metadata": {
"sgp_client_id": "22776",
"contrato": "22846"
},
"created_at": "2026-07-31T22:00:00Z",
"updated_at": "2026-07-31T22:00:00Z"
}
}
PATCH Atualizar Sub-tenant
Atualiza dados de um sub-tenant existente. Apenas os campos enviados são modificados — campos omitidos permanecem inalterados.
Body (campos opcionais)
| Campo | Tipo | Descrição |
|---|---|---|
| name | string | Nome completo atualizado |
| phone | string | Telefone somente números |
| metadata | object | Substitui o objeto metadata completo |
Códigos de status
Requisição
curl -X PATCH \
"https://app.kemsolucoes.com.br/api/v1/provisioning/sub-tenants/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "X-API-Key: sua-api-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"phone": "11888888888",
"metadata": {
"sgp_client_id": "22776",
"contrato": "22846",
"atualizado_em": "2026-07-31"
}
}'
Resposta 200
{
"ok": true,
"status": "updated",
"data": {
"id": "a1b2c3d4-...",
"phone": "11888888888",
"updated_at": "2026-07-31T22:05:00Z"
}
}
DELETE Desativar Sub-tenant
Desativa o acesso do sub-tenant ao Hub de IA. O usuário e seus dados são preservados — a operação é reversível e não exclui nenhum registro permanentemente.
PATCH /sub-tenants/{id} com "status": "active", ou reative diretamente pelo painel KemOS.Path parameters
| Parâmetro | Tipo | Descrição |
|---|---|---|
| id | uuid | UUID do sub-tenant a desativar |
Códigos de status
Requisição
curl -X DELETE \
"https://app.kemsolucoes.com.br/api/v1/provisioning/sub-tenants/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
-H "X-API-Key: sua-api-key-aqui"
Resposta 200
{
"ok": true,
"status": "deactivated"
}
Visão Geral
Configure um endpoint HTTPS no seu servidor para receber notificações do KemOS quando eventos relevantes ocorrerem — ativações, desativações e pagamentos confirmados.
Configuração
Acesse Configurações → Integrações → Webhooks → URL do Endpoint para registrar seu endpoint. O KemOS fará um POST para essa URL sempre que um evento for disparado.
Verificação de assinatura
Cada requisição de webhook inclui o header X-KemOS-Signature com um HMAC-SHA256 gerado a partir do body usando seu webhook secret. Sempre valide a assinatura antes de processar o evento.
Validar em Node.js
Eventos disponíveis
| Evento | Quando dispara |
|---|---|
| sub_tenant.created | Sub-tenant criado com sucesso via API ou painel |
| sub_tenant.activated | Hub IA ativado para o sub-tenant |
| sub_tenant.deactivated | Acesso desativado via API ou painel |
| payment.received | Pagamento confirmado (Pix, boleto ou cartão) |
Retry policy
O KemOS tenta entregar cada evento até 3 vezes em caso de falha (timeout ou status >= 400). O intervalo entre tentativas é de 30s, 5min e 30min respectivamente. Retorne 2xx para confirmar o recebimento.
Validar assinatura
const crypto = require('crypto');
function validateWebhook(req, secret) {
const signature = req.headers['x-kemos-signature'];
const body = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', secret)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
import hmac, hashlib
def validate_webhook(body: bytes, secret: str, sig: str) -> bool:
expected = hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, sig)
Eventos de Pagamento
Todos os eventos de webhook seguem a mesma estrutura de envelope. O campo event identifica o tipo e o campo data contém os dados específicos do recurso afetado.
Estrutura do envelope
| Campo | Tipo | Descrição |
|---|---|---|
| event | string | Identificador do evento |
| timestamp | string | ISO 8601 UTC do momento do evento |
| data | object | Dados do recurso associado |
timestamp para ordenar eventos e o id do sub-tenant para deduplicação.Payload — sub_tenant.activated
{
"event": "sub_tenant.activated",
"timestamp": "2026-07-31T22:15:29Z",
"data": {
"id": "a1b2c3d4-...",
"email": "joao@email.com",
"name": "João da Silva",
"plan": "hub-ia-solo",
"parent_tenant_id": "c130602d-7fcf-4623-966c-b91e19444b6f"
}
}
Payload — payment.received
{
"event": "payment.received",
"timestamp": "2026-07-31T22:20:00Z",
"data": {
"sub_tenant_id": "a1b2c3d4-...",
"amount": 4990,
"currency": "BRL",
"method": "pix",
"reference": "PAY-2026-07-31-001"
}
}
Códigos de Erro
Todas as respostas de erro seguem o mesmo formato de envelope com "ok": false e um objeto error detalhando a causa.
| Código | Nome | Descrição |
|---|---|---|
| 400 | Bad Request | Parâmetros faltando ou com formato inválido |
| 401 | Unauthorized | API Key ausente, inválida ou revogada |
| 403 | Forbidden | Sem permissão para acessar este recurso |
| 404 | Not Found | Sub-tenant não encontrado para o ID informado |
| 409 | Conflict | E-mail já cadastrado com CPF diferente |
| 422 | Unprocessable Entity | Dados válidos mas regra de negócio violada |
| 429 | Too Many Requests | Rate limit excedido — aguarde e tente novamente |
| 500 | Internal Server Error | Erro no servidor — abra um ticket de suporte |
Formato do erro
{
"ok": false,
"error": {
"code": "INVALID_CPF",
"message": "O CPF informado não é válido.",
"field": "cpf"
}
}
Erro 422 — regra de negócio
{
"ok": false,
"error": {
"code": "PLAN_NOT_ALLOWED",
"message": "O plano 'hub-ia-enterprise' não está disponível para seu tenant.",
"field": "plan"
}
}
Visão Geral
Planos do revendedor permitem que você defina quais módulos do KemOS serão liberados para cada tipo de cliente — sem depender de planos globais da Kem Soluções.
Em vez de fixar "plan": "hub-ia-solo" em todas as integrações, você cria planos personalizados no painel e usa o UUID de cada plano na Provisioning API. Isso permite:
- Segmentar clientes por produto: Internet 500MB + Hub IA, Plano Premium + Financeiro, etc.
- Controlar exatamente quais módulos cada plano ativa — somente módulos que você mesmo tem habilitado
- Alterar módulos de um plano a qualquer momento sem mexer na integração
- Rastrear qual plano originou cada sub-tenant (campo
reseller_plan_idna subscription)
Como funciona
| Etapa | Onde | O que acontece |
|---|---|---|
| 1. Criar plano | KemOS → /planos | Você escolhe os módulos e o sistema gera um UUID único para o plano |
| 2. Copiar UUID | Card do plano | Botão "Copiar" ao lado do Plan ID — use este UUID na sua integração |
| 3. Provisionar | Provisioning API | Passe o UUID no campo plan — os módulos corretos são ativados automaticamente |
| 4. Gerenciar | KemOS → /clientes | Veja todos os sub-tenants provisionados, status e plano utilizado |
Criando um Plano
Acesse KemOS → Configurações → Planos e clique em "+ Novo plano". O modal exibe todos os módulos disponíveis para o seu tenant, agrupados por categoria.
Campos do plano
| Campo | Obrigatório | Descrição |
|---|---|---|
| Nome | ✅ Sim | Nome interno do plano. Ex: "Internet 500MB + Hub IA" |
| Descrição | Não | Texto opcional para identificação interna |
| Módulos | ✅ Sim | Selecione os módulos que serão liberados para clientes deste plano. Apenas módulos ativos no seu tenant aparecem como opção. |
Após criar
O plano aparece como um card com o Plan ID (UUID) exibido e um botão Copiar. Use este UUID no campo plan da Provisioning API. Você pode editar os módulos do plano a qualquer momento — clientes já provisionados não são afetados retroativamente.
API — criar plano programaticamente
curl -X POST \
https://app.kemsolucoes.com.br/api/tenant/plans \
-H "X-API-Key: sua-api-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Internet 500MB + Hub IA",
"description": "Plano combo com acesso ao Hub de IA",
"modules": ["hub-ia", "hub-ia-busca", "hub-ia-agentes"]
}'
Resposta 201
{
"ok": true,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Internet 500MB + Hub IA",
"description": "Plano combo com acesso ao Hub de IA",
"modules": ["hub-ia", "hub-ia-busca", "hub-ia-agentes"],
"status": "active",
"created_at": "2026-08-01T00:00:00Z"
}
}
Provisionando com Plano
Com o UUID do plano em mãos, passe-o no campo plan ao criar um sub-tenant. O sistema detecta automaticamente que é um plano do revendedor (formato UUID) e ativa exatamente os módulos configurados.
Comportamento do campo plan
Valor do campo plan | Comportamento |
|---|---|
a1b2c3d4-e5f6-7890-abcd-ef1234567890 (UUID) |
Plano do revendedor — ativa os módulos configurados no plano. Valida que o plano pertence ao seu tenant e está ativo. |
hub-ia-solo |
Plano global — ativa o módulo hub-ia (legado, compatível) |
| omitido | Usa hub-ia-solo como padrão |
Resposta — campos relacionados ao plano
| Campo | Descrição |
|---|---|
modules |
Array com os IDs dos módulos ativados para o sub-tenant |
plan |
Plan ID de billing utilizado (hub-ia-revendedor quando plano do revendedor) |
group |
Nome do grupo de usuário criado/reutilizado para este conjunto de módulos |
Exemplo com plano do revendedor
curl -X POST \
https://app.kemsolucoes.com.br/api/v1/provisioning/sub-tenants \
-H "X-API-Key: sua-api-key-aqui" \
-H "Content-Type: application/json" \
-d '{
"name": "Maria Souza",
"email": "maria@email.com",
"cpf": "98765432100",
"phone": "11988887777",
"plan": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"send_welcome": true,
"metadata": {
"sgp_client_id": "33001",
"plano_internet": "500MB"
}
}'
Resposta 201
{
"ok": true,
"status": "created",
"data": {
"id": "b9c8d7e6-f5a4-3210-fedc-ba9876543210",
"email": "maria@email.com",
"name": "Maria Souza",
"plan": "hub-ia-revendedor",
"portal_url": "https://app.kemsolucoes.com.br",
"parent_tenant_id": "c130602d-7fcf-4623-966c-b91e19444b6f",
"group": "Internet 500MB + Hub IA",
"modules": ["hub-ia", "hub-ia-busca", "hub-ia-agentes"],
"credentials": {
"email": "maria@email.com",
"temporary_password": "HubIAzx9t42801"
},
"created_at": "2026-08-01T12:00:00Z"
}
}
Erro — plano não encontrado
{
"ok": false,
"error": {
"code": "RESELLER_PLAN_NOT_FOUND",
"message": "Plano não encontrado ou inativo para este tenant.",
"field": "plan"
}
}
Rate Limits
Para garantir estabilidade da plataforma, a API aplica limites de requisições por API Key. Os limites são compartilhados entre todos os endpoints.
Headers de controle
Cada resposta da API inclui os seguintes headers para monitorar seu consumo:
| Header | Descrição |
|---|---|
X-RateLimit-Limit |
Limite máximo de requisições no período |
X-RateLimit-Remaining |
Requisições restantes no período atual |
X-RateLimit-Reset |
Timestamp Unix de quando o limite é resetado |
Retry-After |
Segundos para aguardar (presente apenas em 429) |
Headers — exemplo de resposta
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 84
X-RateLimit-Reset: 1753996800
Resposta 429 — rate limit excedido
{
"ok": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Limite de requisições atingido. Tente novamente em 42 segundos.",
"retry_after": 42
}
}