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 o Hub de IA automaticamente. Se o e-mail já existir no sistema, retorna o sub-tenant existente sem criar duplicata.
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 | ✅ Sim | Plano contratado. Ex: "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"
}
}
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
}
}