Migration Guide: KYB Cases
This release of @zyphe-sdk/core and @zyphe-sdk/node moves KYB management from the KYB result to the KYB case, adds Transaction Monitoring helpers, and updates the bundled OpenAPI types.
If you review KYB in the dashboard, see the KYB dashboard migration guide for what changed there.
Nothing stops working when you upgrade: the previous KYB helpers are deprecated, not removed, and their endpoints still answer. You only have to act if you use the KYB helpers or read the types listed under Type changes.
| Package | From | To |
|---|---|---|
@zyphe-sdk/core | 0.5.x | next minor (0.6.0) |
@zyphe-sdk/node | 0.4.x | next minor (0.5.0) |
@zyphe-sdk/browser | 0.4.x | patch, no action |
Who needs to migrate
- You call
addKybUbos,removeKybUbo,addKybDirectors,removeKybDirector,requestKybOnDemandDocument, orsendKybUboReminder: move to the case helpers (step 2). Your editor already flags them as deprecated after the upgrade. - You approve or reject KYB results from your backend: use
decideKybCase(step 4). - You import types from
@zyphe-sdk/core/openapi: check Type changes. - You only create verification sessions, verify webhooks, or use the Export API: upgrade, no code change.
1. Upgrade the packages
pnpm add @zyphe-sdk/node@latest
# or, if you use it directly
pnpm add @zyphe-sdk/core@latest
2. Move to the case helpers
The case helpers take a caseId instead of a kybResultId. It is the same value: the ID of a KYB result is the ID of its case. Rename the parameter and keep passing the ID you already store.
| Deprecated | Replacement |
|---|---|
addKybUbos | addKybCaseUbos |
removeKybUbo | removeKybCaseUbo |
addKybDirectors | addKybCaseDirectors |
removeKybDirector | removeKybCaseDirector |
requestKybOnDemandDocument | requestKybCaseOnDemandDocument |
sendKybUboReminder | sendKybCaseUboReminder |
Before:
import { addKybUbos } from '@zyphe-sdk/node'
const { data } = await addKybUbos({ organizationId, kybResultId, isSandbox: true, persons }, opts)
const ubos = data?.uboDefinitions ?? []
After:
import { addKybCaseUbos } from '@zyphe-sdk/node'
const { data } = await addKybCaseUbos({ organizationId, caseId: kybResultId, isSandbox: true, persons }, opts)
const ubos = data?.ubos ?? []
The persons payload is unchanged.
3. Read the new officer response
The four officer helpers (addKybCaseUbos, removeKybCaseUbo, addKybCaseDirectors, removeKybCaseDirector) no longer answer with the whole KYB result. They answer with the case's officers as they stand after the change:
{ caseId: string, ubos: UboDefinition[], directors: DirectorDefinition[] }
| Before (KYB result) | After (officers) |
|---|---|
data.uboDefinitions | data.ubos |
data.directorDefinitions | data.directors |
| any other KYB result field | getKybCase or getFlowResult |
Each person keeps the same stable id, which removeKybCaseUbo / removeKybCaseDirector take as personId. To read the officers without changing them, call getKybCaseOfficers.
The other two replacements behave as before, with two details worth checking:
sendKybCaseUboReminderstill takes arecipientIndex: the position of the UBO inubos. Only a UBO with an email can be invited; one declared without an email is rejected.requestKybCaseOnDemandDocumentalso accepts optionalrecipientEmail,subject,body, anddescriptionnext todocumentKey. ThedocumentKeymust name a document the flow marks as on demand; a document the flow requires upfront is rejected.
4. Decide cases with decideKybCase
Approving or rejecting a KYB result from your backend now goes through the case decision:
import { decideKybCase } from '@zyphe-sdk/node'
const { data, response } = await decideKybCase(
{
organizationId,
caseId,
isSandbox: true,
outcome: 'REJECTED', // or 'APPROVED'
reason: 'Ownership could not be verified', // mandatory on a rejection
reasonCode: 'CDD_INCOMPLETE', // optional classification
},
opts,
)
- The
POST /sdk/organizations/{organization_id}/kyb/{kyb_result_id}/approveand/rejectendpoints are deprecated in favour of this one. Sendoutcome: 'APPROVED'oroutcome: 'REJECTED';reason,reasonCode, anddueDiligenceLevelcarry over. - The answer is the decision (
outcome,statusBefore,statusAfter,decisionId), not the KYB result. Read the case withgetKybCaseafterwards if you need it. - Handle
202: when the organization's approval matrix requires two signatures, the call records adecisionProposalinstead of closing the case. The second signature must come from a person in the dashboard: an API key can propose a decision but cannot confirm one. See Decide a case. - A decision is final. A decided case cannot be decided again.
5. Handle the new error tags
Refusals of a case decision now carry their own errorTag, so you can tell the user why instead of showing a generic bad request:
errorTag | Meaning |
|---|---|
kyb_case_not_decidable | The case's status does not accept this decision (for example, it is already decided) |
kyb_case_not_ready | The case is not ready for review yet: an approval needs it in READY_FOR_REVIEW |
kyb_case_exception_required | The approval rests on something that needs a recorded exception first; the message lists what |
kyb_case_rejecting_hit | A confirmed screening match stands on the case and the organization's policy rejects it |
kyb_case_reason_required | The decision needs a reason (every rejection, and an approval resting on an exception or a match) |
kyb_case_decision_not_authorized | The organization's approval matrix does not let this caller take this decision |
kyb_case_second_signature_required | The confirmation of a proposal is not valid: it must come from a person other than the proposer |
All of them are 400. The message names the specific blocker, so log it.
Type changes
These only affect code that reads the generated types exported from @zyphe-sdk/core/openapi (components['schemas'][...]):
KybConfigno longer hasarticlesOfAssociation,certificateOfIncorporation,customDocuments,organizationalStructureChart, orproofOfAttorney. KYB documents are configured on theKYB_DOCUMENTSstep (KybDocumentsConfig); see KYB steps and configuration.FlowStepTypegainsKYB_DOCUMENTS,KYB_UBOS, andKYB_DIRECTORS. Update exhaustiveswitchstatements over step types.Flowno longer haswebhookUrl. Webhook destinations are configured as webhook endpoints.ErrorTagsno longer containswebsocket.- Removed schemas that were not used by any SDK helper:
CustomDocumentConfig,DocumentConfig,ModerateKybResultPayload,ModerateKybResultResponse,PagedCommunicationsResponse,PagedDocumentRequestsResponse,Uuid, and the dashboardList*Responsetypes.
Additive changes need no action: new optional fields such as SdkCreateVerificationRequestResponse.sessionId, KybMetadata.dueDiligenceLevel, and DvConfig.capture, plus the new KYB case and Transaction Monitoring schemas.
Checklist
- Upgrade
@zyphe-sdk/node(and@zyphe-sdk/coreif you depend on it directly). - Replace the six deprecated KYB helpers and rename
kybResultIdtocaseId. - Read
ubos/directorsinstead ofuboDefinitions/directorDefinitions. - Move backend approvals and rejections to
decideKybCase, handling202. - Map the new
kyb_case_*error tags to user-facing messages. - Fix compile errors from the type changes, if any.
- Run the flow end to end in the sandbox before switching production keys.