@hibrit/connect
v0.4.0
Published
SDK oficial para integração de produtos ao ecossistema Hibrit Hub
Downloads
139
Maintainers
Readme
@hibrit/connect
SDK oficial para integração de produtos ao ecossistema Hibrit Hub.
Instalação
npm install @hibrit/connect
# ou
pnpm add @hibrit/connect
# ou
yarn add @hibrit/connectConfiguração
Você precisa das credenciais fornecidas pelo Hibrit Hub:
apiKey: Chave de API do seu produto (formato:hbt_...)apiSecret: Secret para assinatura de webhooks (formato:whsec_...)productSlug: Slug do seu produto (ex:taktics,leadfloww)
import { HibritConnect } from '@hibrit/connect';
const hub = new HibritConnect({
apiKey: process.env.HUB_API_KEY,
apiSecret: process.env.HUB_WEBHOOK_SECRET,
productSlug: 'taktics',
baseUrl: 'https://connect.hibrit.com.br', // opcional (default)
});Sincronização de Organizações
Sincronize organizações/clientes do seu produto com o Hub:
const result = await hub.syncOrganization({
externalId: 'org-123', // ID único no seu sistema
name: 'Empresa ABC', // Nome da organização
slug: 'empresa-abc', // Slug único (opcional)
email: '[email protected]', // Email de contato (opcional)
status: 'active', // active | inactive | trial | suspended
metadata: { // Dados extras (opcional)
plano: 'premium',
origem: 'indicacao',
},
});
if (result.success) {
console.log('Organização sincronizada:', result.data);
// { mappingId: '...', hubOrgId: '...', action: 'created' | 'updated' }
} else {
console.error('Erro:', result.error);
}Sincronização em Lote
const results = await hub.syncOrganizations([
{ externalId: 'org-1', name: 'Empresa A', status: 'active' },
{ externalId: 'org-2', name: 'Empresa B', status: 'active' },
]);
console.log(`Sucesso: ${results.success}, Falhas: ${results.failed}`);Buscar Organizações Mapeadas
Recupere todas as organizações do seu produto que estão mapeadas no Hub:
const result = await hub.getOrganizations({
limit: 100, // Máx: 500
offset: 0, // Para paginação
includeHubOrg: true, // Inclui dados da org no Hub
status: 'synced', // Filtrar por status de sync (opcional)
});
if (result.success) {
console.log('Organizações:', result.data);
console.log('Total:', result.pagination?.total);
console.log('Mais páginas?', result.pagination?.hasMore);
// Cada org contém:
// - external_id: ID no seu sistema
// - hub_org_id: ID no Hub
// - sync_status: 'synced' | 'pending' | 'error' | 'conflict'
// - hubOrg: { id, name, slug, type, status, email } (se includeHubOrg=true)
}Sincronização de Contratos
Novo na v0.4.0! Sincronize contratos vinculados a organizações:
const result = await hub.syncContract({
externalId: 'contrato-123', // ID único no seu sistema
organizationId: hubOrgId, // ID da organização no Hub (hub_org_id)
name: 'Contrato Premium', // Nome do contrato
number: 'CPS-2408', // Número/código do contrato (opcional)
status: 'active', // draft | active | paused | completed | cancelled
startDate: '2024-01-01', // Data de início (opcional)
endDate: '2025-01-01', // Data de término (opcional)
value: 50000, // Valor do contrato (opcional)
currency: 'BRL', // Moeda (opcional, default: BRL)
billingCycle: 'monthly', // monthly | quarterly | yearly | one-time (opcional)
metadata: { // Dados extras (opcional)
sigla: 'AGR',
tipo: 'consultoria',
},
});
if (result.success) {
console.log('Contrato sincronizado:', result.data);
// { contractId: '...', action: 'created' | 'updated' }
} else {
console.error('Erro:', result.error);
}Sincronização em Lote de Contratos
const results = await hub.syncContracts([
{
externalId: 'contrato-1',
organizationId: hubOrgId,
name: 'Contrato A',
status: 'active',
},
{
externalId: 'contrato-2',
organizationId: hubOrgId,
name: 'Contrato B',
status: 'active',
},
]);
console.log(`Sucesso: ${results.success}, Falhas: ${results.failed}`);Exemplo Completo: Organização + Contratos
// 1. Sincronizar organização primeiro
const orgResult = await hub.syncOrganization({
externalId: 'org-123',
name: 'Empresa XYZ',
status: 'active',
});
if (orgResult.success) {
const hubOrgId = orgResult.data.hubOrgId;
// 2. Sincronizar contratos da organização
await hub.syncContract({
externalId: 'contrato-abc',
organizationId: hubOrgId, // ← usar o hub_org_id retornado
name: 'Contrato Principal',
number: 'CPS-2408',
status: 'active',
value: 100000,
});
}Recebendo Webhooks
Quando eventos acontecem no Hub (ex: organização atualizada), você recebe webhooks:
import { verifyWebhookSignature, isTimestampValid } from '@hibrit/connect';
// Em uma API route (Next.js, Express, etc.)
export async function POST(request: Request) {
const body = await request.text();
const signature = request.headers.get('x-hub-signature');
const timestamp = request.headers.get('x-hub-timestamp');
// Validar timestamp (previne replay attacks)
if (!isTimestampValid(timestamp, 300)) {
return Response.json({ error: 'Timestamp expired' }, { status: 401 });
}
// Verificar assinatura
const isValid = verifyWebhookSignature(
signature,
timestamp,
body,
process.env.HUB_WEBHOOK_SECRET
);
if (!isValid) {
return Response.json({ error: 'Invalid signature' }, { status: 401 });
}
// Processar evento
const event = JSON.parse(body);
console.log('Evento recebido:', event.type, event.data);
return Response.json({ received: true });
}Variáveis de Ambiente
# .env.local
HUB_API_KEY=hbt_sua_api_key_aqui
HUB_WEBHOOK_SECRET=whsec_seu_secret_aqui
HUB_PRODUCT_SLUG=seu-produto
HUB_BASE_URL=https://connect.hibrit.com.br # opcionalAPI Reference
HibritConnect
new HibritConnect(config: HibritConnectConfig)
interface HibritConnectConfig {
apiKey: string; // Sua API key
apiSecret: string; // Seu webhook secret
productSlug: string; // Slug do produto
baseUrl?: string; // URL da API (default: https://connect.hibrit.com.br)
timeout?: number; // Timeout em ms (default: 30000)
retries?: number; // Número de retries (default: 3)
}Métodos
| Método | Descrição |
|--------|-----------|
| syncOrganization(payload) | Sincroniza uma organização (push) |
| syncOrganizations(payloads) | Sincroniza múltiplas organizações em lote |
| getOrganizations(options) | Busca organizações mapeadas no Hub |
| removeOrganization(externalId) | Remove mapeamento de organização |
| syncContract(payload) | [v0.4.0] Sincroniza um contrato (push) |
| syncContracts(payloads) | [v0.4.0] Sincroniza múltiplos contratos em lote |
| verifyWebhook(options) | Verifica assinatura de webhook |
| getLoginUrl(options) | Retorna URL de login SSO |
| getConfig() | Retorna configuração (sem secrets) |
Funções Utilitárias
| Função | Descrição |
|--------|-----------|
| generateSignature(apiKey, timestamp, body, secret) | Gera assinatura HMAC-SHA256 |
| verifyWebhookSignature(signature, timestamp, body, secret) | Verifica assinatura de webhook |
| isTimestampValid(timestamp, toleranceSeconds) | Valida timestamp (anti-replay) |
Tipos
Organizações
interface SyncOrganizationPayload {
externalId: string;
name: string;
slug?: string;
email?: string;
status?: 'active' | 'inactive' | 'trial' | 'suspended';
plan?: string;
metadata?: Record<string, unknown>;
}
interface SyncResult {
success: boolean;
data?: {
mappingId: string;
hubOrgId: string;
action: 'created' | 'updated';
};
error?: {
code: string;
message: string;
};
}
interface BatchSyncResult {
total: number;
success: number;
failed: number;
errors: Array<{ externalId: string; error: string }>;
}
interface GetOrganizationsOptions {
limit?: number; // default: 100, max: 500
offset?: number; // default: 0
status?: 'synced' | 'pending' | 'error' | 'conflict';
includeHubOrg?: boolean; // default: true
}
interface GetOrganizationsResult {
success: boolean;
data?: OrganizationMapping[];
pagination?: {
total: number;
offset: number;
limit: number;
hasMore: boolean;
};
error?: { code: string; message: string };
}
interface OrganizationMapping {
id: string;
hub_org_id: string;
external_id: string;
external_name?: string;
external_email?: string;
sync_status: 'synced' | 'pending' | 'error' | 'conflict';
last_sync_at?: string;
hubOrg?: {
id: string;
name: string;
slug: string;
type: 'holding' | 'agency' | 'client' | 'partner' | 'internal';
status: 'active' | 'inactive' | 'suspended' | 'trial' | 'churned';
email?: string;
};
}Contratos (v0.4.0+)
interface SyncContractPayload {
externalId: string;
organizationId: string; // hub_org_id da organização
name: string;
number?: string;
status?: 'draft' | 'active' | 'paused' | 'completed' | 'cancelled';
startDate?: string;
endDate?: string;
renewalDate?: string;
value?: number;
currency?: string;
billingCycle?: 'monthly' | 'quarterly' | 'yearly' | 'one-time';
metadata?: Record<string, unknown>;
}
interface SyncContractResult {
success: boolean;
data?: {
contractId: string;
action: 'created' | 'updated';
};
error?: {
code: string;
message: string;
};
}
interface BatchSyncContractsResult {
total: number;
success: number;
failed: number;
errors: Array<{
externalId: string;
error: string;
}>;
}Segurança
- Todas as requisições são assinadas com HMAC-SHA256
- Formato da assinatura:
sha256={hmac(timestamp.body, secret)} - Timestamps são validados para prevenir replay attacks (tolerância: 5 minutos)
- Nunca exponha
apiSecretno client-side
Suporte
- Documentação: https://docs.hibrit.com.br
- Issues: https://github.com/hibritoficial/hibrit-connect/issues
Licença
MIT
