@cactus-agents/kyc
Service para verificação de identidade (KYC). Suporta múltiplos operadores (pay2free, serasa, legitimuz, caf, sumsub, unico, shieldid). Oferece start/status de verificação e helpers para interpretar o estado do KYC.
Instalação
pnpm add @cactus-agents/kyc
Uso recomendado (via wrapper)
import { createKycFromClient } from "@cactus-agents/kyc";
const kyc = createKycFromClient(client);
const startResponse = await kyc.start("global");
const statusResponse = await kyc.getStatus(startResponse.correlation_id!);
Uso manual (com fetcher)
import { createKycService } from "@cactus-agents/kyc";
const kyc = createKycService({
get: <T>(path: string) => fetcher.get<T>(path),
});
API — KycService
start(source?)
Inicia uma verificação KYC. Retorna URL do iframe do operador e dados da sessão.
start(source?: KycSource): Promise<KycStartResponse>
| Param | Tipo | Default | Descrição |
|---|---|---|---|
source | string | "global" | Contexto que disparou o KYC |
Endpoint: GET /bff/users/kyc?source={source}
startRecovery(source, token)
Inicia KYC com token de recuperação (link enviado por e-mail/SMS).
startRecovery(source: KycSource, token: string): Promise<KycStartResponse>
Endpoint: GET /bff/users/kyc/recovery?source={source}&token={token}
getStatus(kycId)
Consulta o status de uma verificação em andamento.
getStatus(kycId: number | string): Promise<KycStatusResponse>
Endpoint: GET /bff/users/kyc/status?kyc_id={kycId}
getStatusRecovery(kycId, token)
Consulta status com token de recuperação.
getStatusRecovery(kycId: number | string, token: string): Promise<KycStatusResponse>
Endpoint: GET /bff/users/kyc/status/recovery?kyc_id={kycId}&token={token}
Helpers de status
Funções para interpretar o status retornado pela API. Aceitam number, string ou enum.
import {
isKycApprovedStatus,
isKycReprovedStatus,
isKycProcessingStatus,
isKycLivenessPendingStatus,
isKycManualApprovePendingStatus,
normalizeKycStatus,
} from "@cactus-agents/kyc";
| Helper | Retorna true quando |
|---|---|
isKycApprovedStatus(status) | APPROVED ou MANUAL_APPROVED |
isKycReprovedStatus(status) | REPROVED ou MANUAL_REPROVED |
isKycProcessingStatus(status) | PROCESSING ou LIVENESS_PENDING |
isKycLivenessPendingStatus(status) | LIVENESS_PENDING |
isKycManualApprovePendingStatus(status) | MANUAL_APPROVE_PENDING |
normalizeKycStatus(status)
Converte qualquer representação (number, string, enum) para KycStatus enum.
normalizeKycStatus(status: KycStatusLike): KycStatus | null
Tipos
KycStatus (enum)
enum KycStatus {
PROCESSING = 0,
APPROVED = 1,
REPROVED = 2,
MANUAL_APPROVED = 3,
MANUAL_APPROVE_PENDING = 4,
MANUAL_REPROVED = 5,
LIVENESS_PENDING = 6,
}
KycStartResponse
interface KycStartResponse {
correlation_id?: number;
operator?: KycOperatorName;
status?: KycStatusLike;
operation_type?: KycOperationType;
url?: string;
exception?: string;
}
KycStatusResponse
interface KycStatusResponse {
status: KycStatusLike;
token?: string;
}
KycOperatorName
type KycOperatorName =
| "caf" | "legitimuz" | "pay2free" | "serasa"
| "sumsub" | "unico" | "shielid" | "shieldid"
| string;
Parsing de mensagens do operador
parseKycOperatorMessage interpreta payloads postMessage dos iframes dos operadores KYC, retornando eventos tipados:
import { parseKycOperatorMessage } from "@cactus-agents/kyc";
const event = parseKycOperatorMessage(operator, messageEvent.data);
// event.type: "completed" | "failed" | "manual_approve_pending" | "mobile_started" | "unknown"
Operadores suportados: pay2free, serasa, legitimuz, shieldid.
Tipos de evento:
| Tipo | Interface | Descricao |
|---|---|---|
completed | KycEventCompleted | Verificacao concluida com sucesso |
failed | KycEventFailed | Verificacao falhou |
manual_approve_pending | KycEventManualApprovePending | Aguardando aprovacao manual |
mobile_started | KycEventMobileStarted | Fluxo mobile iniciado |
unknown | KycEventUnknown | Evento nao reconhecido |
O tipo union KycMessageEvent engloba todos os eventos possiveis.
Labels de motivo de KYC forcado
import { getKycReasonLabel, KYC_REASON_LABELS } from "@cactus-agents/kyc";
const label = getKycReasonLabel("password_changed");
// → "validation:kyc_reasons.password_change"
Motivos conhecidos:
| Reason | i18n Key |
|---|---|
password_changed | validation:kyc_reasons.password_change |
reset_password | validation:kyc_reasons.password_recovery |
admin_change_password | validation:kyc_reasons.admin_password_change |
location_changed_login | validation:kyc_reasons.login_location_change |
device_changed_login | validation:kyc_reasons.login_device_change |
ip_changed | validation:kyc_reasons.ip_change |
login_7_days_ago | validation:kyc_reasons.access_after_7_days |
Motivos com cookie_liveness retornam validation:kyc_reasons.selfie_validation. Demais retornam validation:kyc_reasons.unknown.
Tipo KycForceReason: union dos motivos acima + string (extensivel).
Tipo de integração — iframe ou SDK
O KycStartResponse não diz explicitamente como renderizar. inferKycIntegrationType() classifica para você:
import { inferKycIntegrationType } from "@cactus-agents/kyc";
inferKycIntegrationType(startResponse);
// "iframe" → a resposta trouxe `url`
// "sdk" → a resposta trouxe `token` (com ou sem `process_id`)
// "unknown" → nenhum dos dois; o caller DEVE surfacear erro
Precedência: url ganha de token. KycIntegrationType é a union "iframe" | "sdk" | "unknown".
Subpath exports (operadores)
Dois operadores exigem SDK de browser e por isso ficam isolados em subpaths — o barrel principal não os importa, então quem não usa Unico não carrega o SDK dele:
| Import | Exports |
|---|---|
@cactus-agents/kyc/unico | createUnicoLauncher, UnicoLauncher, UnicoLaunchOptions, UnicoSDKEnv, UnicoSDKType, UnicoSdkFinishEvent |
@cactus-agents/kyc/sumsub | createSumsubLauncher, SumsubLauncher, SumsubLaunchOptions, SumsubSDKError |
:::caution O subpath /unico traz uma dependência de runtime
@cactus-agents/kyc declara idpay-b2b-sdk@^2.2.2 em dependencies, e é o caminho do Unico que a usa. O isolamento em subpath é o que evita esse peso em brands que não integram Unico — não importe de /unico "só por conveniência".
:::
// Unico — carrega o SDK oficial e abre o modal
import { createUnicoLauncher } from "@cactus-agents/kyc/unico";
const launcher = createUnicoLauncher();
await launcher.launch({ token, type: "IFRAME", env: "prod" });
env default é "prod" ("uat" só é repassado ao SDK quando explicitamente pedido) e type default é "IFRAME". Há um delay curto e deliberado entre init e open — sem ele o SDK oficial corre no primeiro launch.
// SumSub — injeta o script e monta o painel num container
import { createSumsubLauncher } from "@cactus-agents/kyc/sumsub";
const launcher = createSumsubLauncher();
await launcher.launch({ token, lang, country /* ... */ });
Os dois launchers são browser-only: createSumsubLauncher().launch() joga erro fora do browser.
Arquivos relevantes
| Arquivo | Conteúdo |
|---|---|
src/service.ts | createKycService, createKycFromClient |
src/status.ts | Helpers de status (isKycApprovedStatus, etc.) |
src/types.ts | Tipos, enum KycStatus e inferKycIntegrationType |
src/index.ts | Re-exports públicos do barrel |
src/messages.ts | parseKycOperatorMessage, tipos de evento |
src/reasons.ts | getKycReasonLabel, KYC_REASON_LABELS, KycForceReason |
src/unico.ts / src/operators/unico.ts | Subpath ./unico + launcher |
src/sumsub.ts / src/operators/sumsub.ts | Subpath ./sumsub + launcher |
Tipos do barrel que costumam faltar em integração nova: KycFetcher, KycIntegrationType, KycOperationType, KycOperatorName, KycSource, KycStatusLike, KycStatusString, KycStartResponse, KycStatusResponse.