API de CPF para plataformas SaaS: como implementar multi-tenancy

Aprenda a implementar multi-tenancy para consultas de CPF via API em plataformas SaaS, com controle de consumo e isolamento por tenant.

Redação CPFHub.io
Redação CPFHub.io
··7 min de leitura
API de CPF para plataformas SaaS: como implementar multi-tenancy

Para implementar multi-tenancy com API de CPF em plataformas SaaS, o caminho é criar uma camada intermediária que isola o consumo por tenant, controla limites individuais e centraliza a chave de API no backend. Cada tenant opera com seu próprio namespace no cache, registro de consumo e faturamento proporcional. A OWASP recomenda que chaves de API nunca sejam expostas ao cliente final — a arquitetura de middleware resolve exatamente isso.


Desafios do multi-tenancy com APIs externas

Controle de consumo

Quando múltiplos tenants compartilham uma única chave de API, é necessário rastrear quantas consultas cada um realizou para fins de faturamento e limites.

Isolamento de dados

Os resultados de consulta de um tenant não devem ser acessíveis por outro. Mesmo que o cache seja compartilhado, as chaves devem incluir o identificador do tenant.

Limites diferenciados

Cada tenant pode ter um plano diferente dentro da sua plataforma SaaS, com limites de consultas distintos.

Faturamento proporcional

O custo das consultas à API precisa ser repassado (total ou parcialmente) para cada tenant com base no seu consumo real.


Arquitetura proposta

A solução consiste em uma camada intermediária (middleware) entre os tenants e a API da CPFHub.io.

Componentes

  • Middleware de controle -- Recebe as requisições dos tenants, verifica limites e encaminha para a API.

  • Banco de dados -- Armazena os limites e o consumo de cada tenant.

  • Cache compartilhado -- Redis com chaves prefixadas pelo tenant ID para isolamento.

  • Módulo de faturamento -- Contabiliza o consumo para cobrança.


Implementação em Python com Flask

import requests
import redis
import json
from flask import Flask, request, jsonify
from datetime import datetime

app = Flask(__name__)

redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

CPFHUB_API_KEY = 'SUA_CHAVE_DE_API'

# Configuracao de limites por tenant (em producao, vem do banco de dados)
TENANT_LIMITES = {
    'tenant_001': {'limite_mensal': 500, 'plano': 'basico'},
    'tenant_002': {'limite_mensal': 2000, 'plano': 'premium'},
    'tenant_003': {'limite_mensal': 100, 'plano': 'trial'}
}

def obter_consumo_mensal(tenant_id: str) -> int:
    mes_atual = datetime.now().strftime('%Y-%m')
    chave = f'cpfhub:consumo:{tenant_id}:{mes_atual}'
    consumo = redis_client.get(chave)
    return int(consumo) if consumo else 0

def incrementar_consumo(tenant_id: str):
    mes_atual = datetime.now().strftime('%Y-%m')
    chave = f'cpfhub:consumo:{tenant_id}:{mes_atual}'
    redis_client.incr(chave)
    # Expirar no final do mes seguinte
    redis_client.expire(chave, 60 * 60 * 24 * 35)

def verificar_limite(tenant_id: str) -> bool:
    config = TENANT_LIMITES.get(tenant_id)
    if not config:
    return False
    consumo = obter_consumo_mensal(tenant_id)
    return consumo < config['limite_mensal']

@app.route('/api/cpf/<cpf>')
def consultar_cpf(cpf):
    # 1. Identificar tenant
    tenant_id = request.headers.get('X-Tenant-ID')
    if not tenant_id:
    return jsonify({'error': 'Header X-Tenant-ID obrigatorio'}), 400

    if tenant_id not in TENANT_LIMITES:
    return jsonify({'error': 'Tenant nao encontrado'}), 404

    # 2. Verificar limite
    if not verificar_limite(tenant_id):
    return jsonify({
    'error': 'Limite de consultas excedido',
    'consumo': obter_consumo_mensal(tenant_id),
    'limite': TENANT_LIMITES[tenant_id]['limite_mensal']
    }), 429

    # 3. Verificar cache (isolado por tenant)
    chave_cache = f'cpfhub:cache:{tenant_id}:{cpf}'
    cacheado = redis_client.get(chave_cache)
    if cacheado:
    return jsonify(json.loads(cacheado))

    # 4. Consultar API
    url = f'https://api.cpfhub.io/cpf/{cpf}'
    headers = {
    'x-api-key': CPFHUB_API_KEY,
    'Accept': 'application/json'
    }

    try:
    response = requests.get(url, headers=headers, timeout=10)
    resultado = response.json()

    if resultado.get('success'):
    # Cachear por 1 hora
    redis_client.setex(chave_cache, 3600, json.dumps(resultado))

    # Incrementar consumo
    incrementar_consumo(tenant_id)

    return jsonify(resultado)

    except requests.exceptions.Timeout:
    return jsonify({'error': 'Timeout na consulta'}), 504
    except Exception as e:
    return jsonify({'error': str(e)}), 500

@app.route('/api/consumo')
def obter_consumo():
    tenant_id = request.headers.get('X-Tenant-ID')
    if not tenant_id:
    return jsonify({'error': 'Header X-Tenant-ID obrigatorio'}), 400

    config = TENANT_LIMITES.get(tenant_id, {})
    consumo = obter_consumo_mensal(tenant_id)

    return jsonify({
    'tenant_id': tenant_id,
    'consumo_atual': consumo,
    'limite_mensal': config.get('limite_mensal', 0),
    'restante': max(0, config.get('limite_mensal', 0) - consumo),
    'plano': config.get('plano', 'desconhecido')
    })

if __name__ == '__main__':
    app.run(port=5000)

Controle de consumo em Node.js

const express = require('express');
const Redis = require('ioredis');

const app = express();
const redis = new Redis();

const CPFHUB_API_KEY = 'SUA_CHAVE_DE_API';

async function verificarLimite(tenantId, limiteMensal) {
    const mesAtual = new Date().toISOString().slice(0, 7);
    const chave = `cpfhub:consumo:${tenantId}:${mesAtual}`;
    const consumo = parseInt(await redis.get(chave) || '0');
    return consumo < limiteMensal;
}

async function incrementarConsumo(tenantId) {
    const mesAtual = new Date().toISOString().slice(0, 7);
    const chave = `cpfhub:consumo:${tenantId}:${mesAtual}`;
    await redis.incr(chave);
    await redis.expire(chave, 60 * 60 * 24 * 35);
}

app.get('/api/cpf/:cpf', async (req, res) => {
    const tenantId = req.headers['x-tenant-id'];
    if (!tenantId) {
    return res.status(400).json({ error: 'Header X-Tenant-ID obrigatorio' });
    }

    const podeContinuar = await verificarLimite(tenantId, 500);
    if (!podeContinuar) {
    return res.status(429).json({ error: 'Limite de consultas excedido' });
    }

    const { cpf } = req.params;

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 10000);

    try {
    const response = await fetch(
    `https://api.cpfhub.io/cpf/${cpf}`,
    {
    headers: {
    'x-api-key': CPFHUB_API_KEY,
    'Accept': 'application/json'
    },
    signal: controller.signal
    }
    );

    clearTimeout(timeoutId);
    const resultado = await response.json();
    await incrementarConsumo(tenantId);

    return res.json(resultado);
    } catch (error) {
    clearTimeout(timeoutId);
    return res.status(500).json({ error: 'Erro na consulta' });
    }
});

app.listen(3000);

Estratégias de faturamento

ModeloDescriçãoMelhor para
Incluso no planoCada plano SaaS inclui X consultasSimplicidade
Pay-per-useCobrar por consulta realizadaTransparência
CréditosTenant compra pacotes de créditosFlexibilidade
HíbridoBase inclusa + excedente cobrado à partePrevisibilidade com elasticidade

Boas práticas

  • Isole o cache por tenant -- Use o tenant ID como prefixo nas chaves do Redis para evitar vazamento de dados entre clientes.

  • Registre cada consulta -- Mantenha um log detalhado com tenant ID, CPF consultado (ou hash), timestamp e resultado para auditoria e faturamento.

  • Implemente alertas de consumo -- Notifique o tenant quando ele atingir 80% e 100% do limite mensal.

  • Considere o plano Corporativo -- Para plataformas SaaS com alto volume de consultas distribuídas entre múltiplos tenants, o plano Corporativo da CPFHub.io oferece limites personalizados e SLA de 99,9%.

  • Centralize a chave de API -- Use uma única chave de API no backend da sua plataforma. Nunca exponha a chave aos tenants.


Perguntas frequentes

Como funciona o isolamento de dados entre tenants ao usar uma API de CPF compartilhada?

O isolamento é feito prefixando todas as chaves de cache e registro com o tenant ID. No Redis, uma chave como cpfhub:cache:tenant_001:12345678900 garante que o resultado da consulta de um tenant nunca seja servido a outro, mesmo que o CPF seja idêntico. Cada tenant enxerga apenas seu próprio consumo e seus próprios resultados.

O que acontece se um tenant ultrapassar o limite de consultas da minha plataforma SaaS?

O middleware deve retornar HTTP 429 para o tenant antes de sequer acionar a API externa. Isso protege seu orçamento e mantém a equidade entre clientes. No plano gratuito da CPFHub.io, 50 consultas mensais são incluídas sem cartão — consultas adicionais custam R$0,15 cada, sem bloqueio automático da API.

Qual modelo de faturamento é mais indicado para SaaS com múltiplos tenants e volumes variáveis?

O modelo híbrido — base inclusa no plano + excedente cobrado à parte — costuma funcionar melhor. Ele dá previsibilidade ao tenant nos meses normais e elasticidade nos picos, sem que você absorva integralmente o custo extra. A CPFHub.io adota exatamente esse modelo: plano com cota inclusa e R$0,15 por consulta além do limite.

Como garantir conformidade com a LGPD ao repassar consultas de CPF entre tenants e a API?

Cada tenant é um controlador de dados independente. O middleware deve registrar a finalidade da consulta, o tenant solicitante e o timestamp, sem armazenar o CPF bruto além do necessário. A ANPD orienta que dados de identificação devem ser tratados com minimização e finalidade declarada — o log de consumo por tenant serve como evidência de rastreabilidade.


Conclusão

Implementar multi-tenancy para consultas de CPF em plataformas SaaS exige planejamento cuidadoso de controle de consumo, isolamento de dados e faturamento. Com uma camada intermediária bem construída e o Redis para controle de limites e cache, é possível oferecer essa funcionalidade de forma escalável e transparente. A CPFHub.io

Cadastre-se em cpfhub.io

CPFHub.io

Pronto para integrar a API?

50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.

Redação CPFHub.io

Sobre a redação

Redação CPFHub.io

Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.

WhatsAppFale conosco via WhatsApp