Rialto

KYC & Accreditation

User verification flows for Know Your Customer and accredited investor checks.

Users must complete KYC (Know Your Customer) verification before subscribing to offerings. Both KYC and accredited investor verification are API-driven: your backend submits the user's PII or accreditation claim to Identity, uploads any supporting documents directly to S3 via presigned URLs, and polls or subscribes to webhooks for the result.

KYC endpoints require a Rialto access_token and use the token's org_id claim for organization scoping. Accreditation endpoints also require a Rialto access_token (obtained via token exchange).

KYC Flow

How It Works

  1. Your backend submits the user's KYC PII to Identity
  2. Identity upserts user_pii and creates a KYC verification
  3. Rialto sends the check to its verification provider
  4. If a document scan is required, the response includes a provider URL in required_action.url
  5. You are notified via webhook or poll for the result

Creating a KYC Verification

curl -X POST https://api.rialto.com/identity/kyc-verifications \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <rialto_access_token>" \
  -d '{
    "firstName": "JOHN",
    "lastName": "SMITH",
    "address": "222333 PEACHTREE PLACE",
    "city": "ATLANTA",
    "state": "GA",
    "zip": "30318",
    "country": "USA",
    "ssn": "112223333",
    "dobMonth": "02",
    "dobDay": "28",
    "dobYear": "1975",
    "email": "john.smith@example.com",
    "telephone": "4045551212",
    "idType": "driverLicense",
    "idIssuer": "GA",
    "idNumber": "0123456789"
  }'

Use either a 9-digit ssn or a 4-digit ssnLast4; do not include dashes or spaces.

Response (201):

{
  "success": true,
  "data": {
    "verification_id": "a1b2c3d4-...",
    "user_id": "70000000-...",
    "org_id": "550e8400-...",
    "status": "action_required",
    "checks": {
      "identity": "needs_review",
      "document": "pending"
    },
    "required_action": {
      "type": "document_scan",
      "url": "https://..."
    },
    "submitted_at": "2026-03-15T10:30:00.000Z",
    "completed_at": null,
    "created_at": "2026-03-15T10:30:00.000Z",
    "updated_at": "2026-03-15T10:30:00.000Z"
  }
}

KYC responses are vendor-neutral. They do not expose raw provider payloads, provider status codes, reason flags, ID/selfie artifacts, or provider-specific field names.

KYC Verification Statuses

StatusDescriptionTerminal?
not_startedUser has no KYC verification yetNo
pendingIdentity check is in progressNo
action_requiredUser must complete an action, such as document scanNo
needs_reviewNeeds manual review by Rialto staffNo
approvedIdentity verified successfullyYes
rejectedIdentity verification failed or was rejectedYes
expiredVerification timed outYes
errorUnrecoverable processing errorYes

Check Statuses

Each verification has checks.identity and checks.document fields:

Check StatusMeaning
not_attemptedCheck not yet run
pendingCheck in progress
passedCheck passed
failedCheck failed
needs_reviewCould not verify automatically

Checking KYC Status

# Get a specific verification
curl https://api.rialto.com/identity/kyc-verifications/<verification_id> \
  -H "Authorization: Bearer <rialto_access_token>"

# Get the latest effective KYC status for the authenticated user
curl https://api.rialto.com/identity/kyc \
  -H "Authorization: Bearer <rialto_access_token>"

# org_admin only: list sanitized KYC verifications in your organization
curl https://api.rialto.com/identity/kyc-verifications \
  -H "Authorization: Bearer <rialto_access_token>"

KYC Webhook Events

Subscribe to these events via the webhooks API:

EventWhen it fires
kyc.verification.createdVerification created
kyc.verification.action_requiredUser must complete a required action
kyc.verification.needs_reviewFlagged for manual review
kyc.verification.approvedVerification passed
kyc.verification.rejectedVerification failed

Accreditation Flow

Accreditation is a single record per user/org — there are no sessions. The same record is updated through self-certification and (when required) document review.

How It Works

  1. Your backend fetches or initializes the user's accreditation record
  2. The user self-certifies an accreditationStatus and accreditationBasis
  3. If the basis requires proof, your backend requests a presigned S3 upload URL
  4. Your client PUTs the file directly to S3, then finalizes the upload with Rialto
  5. Rialto queues the accreditation for admin review
  6. You are notified via webhook or poll for the result

Getting the Current Accreditation

GET /identity/accreditations returns the user's current record (creating a baseline pending record on first call).

curl https://api.rialto.com/identity/accreditations \
  -H "Authorization: Bearer <rialto_access_token>"

Submitting Self-Certification

PUT /identity/accreditations upserts the user's self-certified accreditation.

curl -X PUT https://api.rialto.com/identity/accreditations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <rialto_access_token>" \
  -d '{
    "accreditationStatus": "accredited",
    "accreditationBasis": "income"
  }'
FieldValues
accreditationStatusaccredited, non_accredited
accreditationBasisincome, net_worth, license_7_65_82, entity, not_accredited

Non-accredited self-certification finalizes immediately. Accredited self-certification with a basis that requires proof transitions the review status to pending_review and waits for a document upload.

Review Statuses

The accreditation record's review_status drives the lifecycle:

Review StatusDescriptionTerminal?
not_requiredNo admin review needed (e.g., self-certified non-accredited)No
pending_reviewAwaiting document upload or admin pickupNo
under_reviewAdmin is reviewingNo
more_info_neededAdmin requested additional informationNo
approvedAccreditation verified by adminYes
deniedAccreditation denied by adminYes
expiredAccreditation lapsedYes

Accreditation Statuses

The user's effective accreditation classification:

StatusDescription
pendingNot yet self-certified
accreditedAccredited investor
non_accreditedNot accredited
qualified_purchaserQualified purchaser (QP)
qualified_clientQualified client (QC)
expiredAccreditation expired

Accreditation Bases

The basis for accreditation:

BasisDescription
incomeIncome-based accreditation
net_worthNet worth-based
license_7_65_82Series 7, 65, or 82 license holder
entityEntity-based accreditation
not_accreditedNot accredited

Uploading Supporting Documents

Document upload is a two-step process. First, request a presigned S3 PUT URL:

curl -X POST https://api.rialto.com/identity/accreditations/documents \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <rialto_access_token>" \
  -d '{
    "documentType": "income_proof",
    "fileName": "tax-return-2025.pdf",
    "contentType": "application/pdf",
    "fileSizeBytes": 524288
  }'
FieldRequiredDescription
documentTypeYesincome_proof, net_worth_proof, license_proof, or entity_proof (must match the submitted basis)
fileNameYesOriginal file name
contentTypeYesapplication/pdf, image/jpeg, or image/png
fileSizeBytesYesFile size in bytes (max 10 MB)

Response (201):

{
  "success": true,
  "data": {
    "id": "d4e5f6a7-...",
    "accreditation_id": "b2c3d4e5-...",
    "document_type": "income_proof",
    "status": "upload_pending",
    "upload": {
      "method": "PUT",
      "url": "https://...presigned...",
      "headers": { "Content-Type": "application/pdf" },
      "expires_at": "2026-03-15T10:45:00.000Z"
    }
  }
}

Use the returned upload.url to PUT the file directly to S3 from the browser or your backend. Once the file is uploaded, finalize:

curl -X POST https://api.rialto.com/identity/accreditations/documents/<document_id>/upload \
  -H "Authorization: Bearer <rialto_access_token>"

Finalize HEAD-checks the object in S3 and transitions the document to uploaded. Once a required document is uploaded, the accreditation's review_status becomes pending_review and is queued for admin review.

Document Statuses

StatusDescription
upload_pendingPresigned URL issued, file not yet confirmed
uploadedFile present in S3 and verified
upload_failedObject missing or exceeds 10 MB on finalize

Accreditation Webhook Events

EventWhen it fires
accreditation.submittedUser submitted (self-certified)
accreditation.document.uploadedA supporting document was uploaded
accreditation.more_info_neededAdmin requested more info
accreditation.approvedAccreditation approved
accreditation.deniedAccreditation denied

Token Claims After Verification

After KYC and accreditation are completed, subsequent Rialto tokens include updated claims:

EventClaim updated
KYC approvedkyc_completed = true
Accreditation approvedaccredited = true, accreditation_verified = true

Use these claims for UI hints. Primary Issuance still performs live org-scoped eligibility checks with Identity before subscription create/sign/approval.

Typical User Journey

1. Token Exchange     → User gets Rialto access token
2. Create KYC Verification → User verifies identity
3. KYC Approved       → live eligibility returns kyc_status = approved
4. Submit Accreditation → User self-certifies (and uploads docs if required)
5. Accreditation Approved → accredited = true in token
6. User can now subscribe to offerings

On this page