Pular para conteúdo

API: Subscription

Visão Geral

Consulta de informações da assinatura do tenant autenticado. Créditos de IA são consumidos a cada resposta de IA e atualizados em tempo real via SignalR.

Endpoints

GET /api/subscription/credits

Retorna o saldo de créditos e status da assinatura do tenant.

Autorização: Qualquer usuário autenticado

Response (200 OK) — com assinatura:

{
  "balance": 450,
  "status": "Active"
}

Response (200 OK) — sem assinatura:

{
  "balance": -1,
  "status": null
}

Campos:

Campo Tipo Descrição
balance int Saldo de créditos (-1 se tenant não possui assinatura)
status string? Status da assinatura (null se sem assinatura)

Status possíveis:

Status Descrição
Active Assinatura ativa, todos os recursos disponíveis
AiQuotaExhausted Créditos esgotados, sistema funciona sem IA
PastDue Pagamento vencido, grace period de 24h
Suspended Suspenso após grace period
Cancelled Cancelado após 30 dias de suspensão

GET /api/subscription/details

Retorna detalhes completos da assinatura: status, período, créditos, preço, configuração contratada e uso atual de recursos.

Autorização: Admin

Response (200 OK):

{
  "status": "Active",
  "currentPeriodStart": "2024-01-01T00:00:00Z",
  "currentPeriodEnd": "2024-02-01T00:00:00Z",
  "creditBalance": 450,
  "monthlyCreditPackage": 500,
  "monthlyPriceBrl": 199.90,
  "contractedInstances": 2,
  "totalAgents": 6,
  "extraAgents": 2,
  "extraUsers": 0,
  "extraKbBlocks": 1,
  "extraStepBlocks": 0,
  "extraAttachmentBlocks": 0,
  "extraFaqBlocks": 0,
  "agents": { "current": 3, "max": 6 },
  "users": { "current": 2, "max": 4 },
  "instances": { "current": 2, "max": 2 },
  "knowledgeDocs": { "current": 7, "max": 15 },
  "steps": { "current": 4, "max": 10 },
  "faqs": { "current": 12, "max": 100 },
  "attachmentStorage": { "currentBytes": 52428800, "maxBytes": 1073741824 }
}

Response (404 Not Found): Tenant sem assinatura.

Campos:

Campo Tipo Descrição
status string Status da assinatura
currentPeriodStart DateTime Início do período atual
currentPeriodEnd DateTime Fim do período atual
creditBalance int Saldo de créditos
monthlyCreditPackage int Franquia mensal de créditos
monthlyPriceBrl decimal Valor mensal total em BRL
contractedInstances int Instâncias contratadas
totalAgents int Total de agentes permitidos (free + extras)
extraAgents int Blocos extras de agentes
extraUsers int Blocos extras de usuários
extraKbBlocks int Blocos extras de documentos de conhecimento
extraStepBlocks int Blocos extras de steps
extraAttachmentBlocks int Blocos extras de armazenamento de anexos
extraFaqBlocks int Blocos extras de FAQs
agents ResourceUsage Agentes criados vs limite
users ResourceUsage Usuários criados vs limite
instances ResourceUsage Instâncias criadas vs limite contratado
knowledgeDocs ResourceUsage Documentos de conhecimento vs limite
steps ResourceUsage Steps criados (total do tenant) vs limite
faqs ResourceUsage FAQs criadas (total do tenant) vs limite
attachmentStorage StorageUsage Bytes usados vs limite em bytes

ResourceUsage: { current: int, max: int }

StorageUsage: { currentBytes: long, maxBytes: long }


GET /api/subscription/pricing

Retorna o catálogo de produtos e pacotes de créditos disponíveis para composição da assinatura.

Autorização: Qualquer usuário autenticado (rate limited)

Response (200 OK):

{
  "products": [
    {
      "code": "instance",
      "name": "Instância WhatsApp",
      "description": "Conexão com número WhatsApp",
      "priceBrl": 79.90,
      "priceUsd": 14.99
    }
  ],
  "monthlyPackages": [
    {
      "credits": 500,
      "priceBrl": 49.90,
      "priceUsd": 9.99,
      "discountPercent": 0,
      "isAddon": false
    }
  ],
  "addonPackages": [
    {
      "credits": 100,
      "priceBrl": 12.90,
      "priceUsd": 2.49,
      "discountPercent": 0,
      "isAddon": true
    }
  ]
}

Campos:

Campo Tipo Descrição
products SubscriptionProductResponse[] Produtos modulares (instância, agentes extras, etc.)
monthlyPackages CreditPackageResponse[] Pacotes de créditos mensais (não-addon)
addonPackages CreditPackageResponse[] Pacotes avulsos de créditos (addon)

SubscriptionProductResponse:

Campo Tipo Descrição
code string Código único do produto
name string Nome de exibição
description string? Descrição do produto
priceBrl decimal Preço unitário em BRL
priceUsd decimal Preço unitário em USD

CreditPackageResponse:

Campo Tipo Descrição
credits int Quantidade de créditos
priceBrl decimal Preço em BRL
priceUsd decimal Preço em USD
discountPercent int Desconto percentual (0-100)
isAddon bool Se é pacote avulso (addon)

POST /api/subscription/calculate

Calcula o preço mensal estimado com base na configuração desejada, sem alterar a assinatura.

Autorização: Qualquer usuário autenticado (rate limited)

Request:

{
  "instances": 2,
  "extraAgents": 1,
  "extraUsers": 0,
  "extraKbBlocks": 1,
  "extraStepBlocks": 0,
  "extraAttachmentBlocks": 0,
  "extraFaqBlocks": 0,
  "monthlyCreditPackage": 500
}

Validação:

Campo Regra
instances >= 1, <= 100
extraAgents >= 0, <= 100
extraUsers >= 0, <= 100
extraKbBlocks >= 0, <= 100
extraStepBlocks >= 0, <= 100
extraAttachmentBlocks >= 0, <= 100
extraFaqBlocks >= 0, <= 100
monthlyCreditPackage >= 0, <= 100000

Response (200 OK):

{
  "monthlyPriceBrl": 259.70,
  "monthlyPriceUsd": 49.97,
  "limits": {
    "maxAgents": 5,
    "maxUsers": 4,
    "maxKnowledgeDocs": 15,
    "maxSteps": 10,
    "maxAttachmentStorageMb": 1024,
    "maxFaqs": 100
  },
  "lineItems": [
    {
      "code": "instance",
      "name": "Instância WhatsApp",
      "quantity": 2,
      "unitPriceBrl": 79.90,
      "totalBrl": 159.80,
      "unitPriceUsd": 14.99,
      "totalUsd": 29.98
    },
    {
      "code": "extra_agent",
      "name": "Agente Extra",
      "quantity": 1,
      "unitPriceBrl": 49.90,
      "totalBrl": 49.90,
      "unitPriceUsd": 9.99,
      "totalUsd": 9.99
    },
    {
      "code": "credit_package",
      "name": "Créditos Mensais (500)",
      "quantity": 1,
      "unitPriceBrl": 49.90,
      "totalBrl": 49.90,
      "unitPriceUsd": 9.99,
      "totalUsd": 9.99
    }
  ]
}

Campos:

Campo Tipo Descrição
monthlyPriceBrl decimal Total mensal em BRL
monthlyPriceUsd decimal Total mensal em USD
limits CalculatedLimitsResponse Limites resultantes da configuração
lineItems PriceLineItem[] Detalhamento por item (somente items com quantity > 0)

PriceLineItem:

Campo Tipo Descrição
code string Código do produto (constantes em ProductCodes)
name string Nome de exibição
quantity int Quantidade
unitPriceBrl decimal Preço unitário BRL
totalBrl decimal Total do item BRL
unitPriceUsd decimal Preço unitário USD
totalUsd decimal Total do item USD

Response (400 Bad Request): Validação falhou — retorna erros do FluentValidation.


Atualização em Tempo Real

O saldo de créditos é atualizado via SignalR sempre que um crédito é consumido ou adicionado:

Hub: OnCreditBalanceUpdated(int balance, string status)

O frontend usa SubscriptionStateService para cache client-side (TTL 5 min). O SignalR atualiza o cache diretamente — componentes reagem via evento OnChanged sem re-fetch da API.


Erros Comuns

Status Código Descrição
401 UNAUTHORIZED Token JWT ausente ou inválido
400 VALIDATION_ERROR Campos inválidos no request (CalculatePrice)
404 NOT_FOUND Tenant sem assinatura (GetDetails)