Major change: compliance is now rail-agnostic
In v2, KYC access was tracked per rail —USD, GLOBAL_NETWORK, AFRICA_GENERAL, and others each had their own field requirements and their own status. A user could be ACTIVE on one rail and still need a separate submission — sometimes with different required fields — to unlock another. Adding a new corridor to your integration could mean re-submitting KYC for that rail specifically.
v3 has no rail concept anywhere in Compliance. There’s one identity submission and one aggregate complianceStatus per user. Once a Compliance Profile is submitted and approved, HIFI automatically resolves which corridors that user is eligible for based on their profile (country, business type, etc.) and unlocks access accordingly — you don’t call anything rail- or provider-specific to “activate” a corridor. If you later want to offramp through a new corridor that user’s profile already qualifies them for, there’s no additional KYC step; access is already there.
Endpoints
Request changes
Both versions accept identity fields directly on the same object as the rest of KYC in v2; in v3 the same fields move to the standalone Compliance Profile, split cleanly bytype. In both cases beneficial owners, documents, and Q&A are no longer part of this payload — submit them separately via Associated Party, Documents, and Questionnaire.
Individual (KYC)
v2:Business (KYB)
v2:Status changes
v2 tracked status per rail — a user could simultaneously beCOMPLETED on one rail and PENDING on another (GET /kyc/status could return a status per rail, or the whole map). Status enum: CREATED, ACTIVE, INACTIVE, PENDING, COMPLETED, ON_HOLD, RFI_PENDING, INCOMPLETE, REJECTED, MANUAL_REVIEW, CONTACT_SUPPORT.
v3 returns one aggregate status for the user, derived from the underlying compliance review, plus a structured list of exactly what’s blocking approval:
NOT_SUBMITTED, PENDING, IN_REVIEW, APPROVED, REJECTED, REQUIRES_INFO. rfiActions points at exactly which sub-resource needs attention (a specific document, associated party, or profile field) — v2 had no equivalent structured “what’s wrong” list.
New in v3: rfiActions
v2 had no structured way to tell you why a RFI_PENDING status was set — you’d get the status and had to contact support or guess. In v3, whenever complianceStatus is REQUIRES_INFO, rfiActions on GET /v3/users/:userId/compliance/status returns a typed, machine-readable list of exactly what needs to change before resubmission:
Once you’ve addressed every action in the list, call
POST /v3/users/:userId/compliance/submit again — there’s no per-action resubmission endpoint, the whole package goes back for review.
Poll
GET /v3/users/:userId/compliance/status or listen for the compliance status webhook to catch a transition to REQUIRES_INFO — don’t rely on rfiActions being populated at any other status.ID format
The user’s Compliance Profile isn’t independently addressable by its own ID — it’s fetched/updated via the user’s ID (GET/PATCH /users/:userId/compliance/profile), same as v2.