Pular para o conteúdo principal

@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>
ParamTipoDefaultDescrição
sourcestring"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";
HelperRetorna 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:

TipoInterfaceDescricao
completedKycEventCompletedVerificacao concluida com sucesso
failedKycEventFailedVerificacao falhou
manual_approve_pendingKycEventManualApprovePendingAguardando aprovacao manual
mobile_startedKycEventMobileStartedFluxo mobile iniciado
unknownKycEventUnknownEvento 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:

Reasoni18n Key
password_changedvalidation:kyc_reasons.password_change
reset_passwordvalidation:kyc_reasons.password_recovery
admin_change_passwordvalidation:kyc_reasons.admin_password_change
location_changed_loginvalidation:kyc_reasons.login_location_change
device_changed_loginvalidation:kyc_reasons.login_device_change
ip_changedvalidation:kyc_reasons.ip_change
login_7_days_agovalidation: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:

ImportExports
@cactus-agents/kyc/unicocreateUnicoLauncher, UnicoLauncher, UnicoLaunchOptions, UnicoSDKEnv, UnicoSDKType, UnicoSdkFinishEvent
@cactus-agents/kyc/sumsubcreateSumsubLauncher, 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

ArquivoConteúdo
src/service.tscreateKycService, createKycFromClient
src/status.tsHelpers de status (isKycApprovedStatus, etc.)
src/types.tsTipos, enum KycStatus e inferKycIntegrationType
src/index.tsRe-exports públicos do barrel
src/messages.tsparseKycOperatorMessage, tipos de evento
src/reasons.tsgetKycReasonLabel, KYC_REASON_LABELS, KycForceReason
src/unico.ts / src/operators/unico.tsSubpath ./unico + launcher
src/sumsub.ts / src/operators/sumsub.tsSubpath ./sumsub + launcher

Tipos do barrel que costumam faltar em integração nova: KycFetcher, KycIntegrationType, KycOperationType, KycOperatorName, KycSource, KycStatusLike, KycStatusString, KycStartResponse, KycStatusResponse.