Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.hifi.com/llms.txt

Use this file to discover all available pages before exploring further.

How Documents Work

1

Upload file

First, upload the document file using the Upload File endpoint to get a file ID.
2

Add document

Then, associate the file with the user by calling Add Documents with the file ID, type, subtype, and issued country.
3

KYC approval

Once all required documents are uploaded and verified, submit KYC to trigger review.

Document Attributes

Each document requires three key attributes:
AttributeDescriptionExample
typeCategory of document being uploadedPASSPORT
subTypeSide of document (for multi-sided documents)FRONT_SIDE
issuedCountryISO country code where document was issuedUS, GB

Document Types

Supported document types vary by user type (individual vs business).

Individual Documents

For individual user accounts:
TypeDescriptionDocument Group
DRIVERSGovernment-issued driver’s licenseIdentity
ID_CARDNational ID cardIdentity
PASSPORTPassportIdentity
RESIDENCE_PERMITResidence permit or visaIdentity
PROOF_OF_ADDRESSUtility bill, bank statement, leaseAddress
SELFIESelfie photo for identity verificationIdentity
AUTH_LETTERAuthorization letterIdentity
UTILITY_BILLUtility billAddress
BANK_STATEMENTBank statementAddress
RENTAL_AGREEMENTRental agreementAddress
TAX_DOCUMENTTax documentIdentity
VOTER_REGISTRATION_CARDVoter ID cardIdentity
BANK_REFERENCE_LETTERBank reference letterIdentity
LEASE_TENANCY_AGREEMENTLease agreementAddress

Business Documents

For business user accounts, requirements are organized by document groups. Check your specific rail’s requirements (e.g., USD Rail).
TypeDescriptionDocument Group
INCORPORATION_ARTICLESIncorporation articles documentlegalPresence
INCORPORATION_CERTIncorporation certificate documentlegalPresence
STATE_REGISTRYState registry documentlegalPresence, ownershipStructure, controlStructure
SHAREHOLDER_REGISTRYShareholder registry documentownershipStructure
TRUST_AGREEMENTTrust agreement documentownershipStructure, controlStructure
INFORMATION_STATEMENTInformation statement documentownershipStructure, controlStructure
DIRECTORS_REGISTRYDirectors registry documentcontrolStructure
PROOF_OF_ADDRESSProof of address documentcompanyDetails

Document SubTypes

SubTypes specify which side of a document you’re uploading:
SubTypeUse For
FRONT_SIDEFront of ID card or driver’s license
BACK_SIDEBack of ID card or driver’s license
SINGLE_SIDEAll other documents (passport, bills, certificates)
Multi-sided documents: Only ID_CARD and DRIVERS require both FRONT_SIDE and BACK_SIDE. All other document types use SINGLE_SIDE only.

Document Groups

Compliance requirements are organized into document groups. Users must satisfy all required groups for KYC approval.

Individual Requirements

For individual users, typically required: Identity Group (satisfy with one of):
  • Driver’s License (front + back)
  • ID Card (front + back)
  • Passport
  • Residence Permit
Address Group (satisfy with one of):
  • Utility bill
  • Bank statement
  • Lease agreement

Business Requirements

Business document requirements are organized by groups. Requirements vary by rail and jurisdiction. For USD Rail, typically required groups include:
  • legalPresence (min 1): INCORPORATION_ARTICLES, INCORPORATION_CERT, or STATE_REGISTRY
  • ownershipStructure (min 1): SHAREHOLDER_REGISTRY, TRUST_AGREEMENT, INFORMATION_STATEMENT, or STATE_REGISTRY
  • companyDetails (min 1): PROOF_OF_ADDRESS
  • controlStructure (min 1): DIRECTORS_REGISTRY, TRUST_AGREEMENT, INFORMATION_STATEMENT, or STATE_REGISTRY
Beneficial Owner Identity (for each owner >25% share):
  • Same as individual identity requirements: DRIVERS, ID_CARD, PASSPORT, or RESIDENCE_PERMIT
Specific requirements vary by rail and jurisdiction. Check the KYC requirements for your specific use case.

Uploading Documents

Document upload is a two-step process: first upload the file, then associate it with the user.

Step 1: Upload File

Upload the document file using the Upload File endpoint. Request:
curl -X POST "https://sandbox.hifi.com/v2/files" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: multipart/form-data" \
  -F "file=@/path/to/passport.pdf"
Response:
{
  "id": "file_zEFpbPhk71NaQfEVMR544",
  "createdAt": "2023-10-01T12:00:00Z",
  "fileName": "passport.pdf",
  "size": 204800,
  "mimeType": "application/pdf"
}
Save the id from the response - you’ll need it in step 2.

Step 2: Add Document

Associate the uploaded file with the user using the Add Documents endpoint. Request:
curl -X POST "https://sandbox.hifi.com/v2/kyc/documents" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "usr_abc123",
    "type": "PASSPORT",
    "subType": "SINGLE_SIDE",
    "issuedCountry": "US",
    "fileId": "file_zEFpbPhk71NaQfEVMR544"
  }'
Request Fields:
  • userId (required): User ID for whom documents are being uploaded
  • type (required): Document type from the supported types list
  • subType (required): FRONT_SIDE, BACK_SIDE, or SINGLE_SIDE
  • issuedCountry (required): ISO 3166-1 alpha-2 country code
  • fileId (required): File ID from step 1
Response:
{
  "id": "doc_abc123",
  "type": "PASSPORT",
  "subType": "SINGLE_SIDE",
  "issuedCountry": "US",
  "fileId": "file_zEFpbPhk71NaQfEVMR544",
  "url": "https://example.com/doc_123"
}
For detailed field documentation, see the Add Documents API reference.

File Requirements

Documents must meet these requirements:
RequirementSpecification
File typesPDF, JPG, JPEG, PNG
Max size10 MB per file
ResolutionMinimum 300 DPI recommended
QualityClear, legible, all corners visible
ColorColor or grayscale (no black & white)
Document quality matters: Blurry, cropped, or illegible documents will be rejected. Ensure all text and photos are clearly visible before uploading.

Key Concepts

KYC approval requires satisfying all document groups:Example for Individual (USD Rail):
  • Identity group: Upload ONE of (passport, driver’s license, ID card, residence permit)
  • Address group: Upload ONE of (utility bill, bank statement, lease)
Example for Business (USD Rail):
  • legalPresence group: Upload ONE of (INCORPORATION_ARTICLES, INCORPORATION_CERT, STATE_REGISTRY)
  • ownershipStructure group: Upload ONE of (SHAREHOLDER_REGISTRY, TRUST_AGREEMENT, INFORMATION_STATEMENT, STATE_REGISTRY)
  • companyDetails group: Upload ONE of (PROOF_OF_ADDRESS)
  • controlStructure group: Upload ONE of (DIRECTORS_REGISTRY, TRUST_AGREEMENT, INFORMATION_STATEMENT, STATE_REGISTRY)
  • Owner identity: Upload identity documents for EACH beneficial owner (>25% share)
You must provide enough documents to satisfy each required group.
For driver’s licenses and ID cards, upload both sides separately using the two-step process:Upload front side:
# Step 1: Upload front file
curl -X POST "https://sandbox.hifi.com/v2/files" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@front.jpg"
# Returns: { "id": "file_front123", ... }

# Step 2: Add front document
curl -X POST "https://sandbox.hifi.com/v2/kyc/documents" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "usr_abc123",
    "type": "DRIVERS",
    "subType": "FRONT_SIDE",
    "issuedCountry": "US",
    "fileId": "file_front123"
  }'
Upload back side:
# Step 1: Upload back file
curl -X POST "https://sandbox.hifi.com/v2/files" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@back.jpg"
# Returns: { "id": "file_back123", ... }

# Step 2: Add back document
curl -X POST "https://sandbox.hifi.com/v2/kyc/documents" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "usr_abc123",
    "type": "DRIVERS",
    "subType": "BACK_SIDE",
    "issuedCountry": "US",
    "fileId": "file_back123"
  }'
Both uploads must complete successfully for the document to be considered complete.
The issuedCountry field is critical for compliance:
  • Must match the country that issued the document
  • Use ISO 3166-1 alpha-2 codes (e.g., US, GB, CA, DE)
  • Affects which documents are accepted
  • Used for sanctions screening and compliance checks
Common codes:
  • US - United States
  • GB - United Kingdom
  • CA - Canada
  • MX - Mexico
  • BR - Brazil
Uploaded documents progress through verification:
  • PENDING_REVIEW: Document uploaded, awaiting verification
  • APPROVED: Document verified and accepted
  • REJECTED: Document rejected (see rejection reason)
  • EXPIRED: Document expired and needs replacement
Subscribe to KYC webhook events to track document verification status.
Proof of address documents must meet specific criteria:Accepted documents:
  • Utility bills (electric, gas, water, internet)
  • Bank statements
  • Lease agreements
  • Government correspondence
Requirements:
  • Dated within last 3 months
  • Shows full name matching KYC information
  • Shows complete address
  • Issued by reputable organization
Screenshots or photos of digital statements are typically rejected.

Sample Code

Here’s a complete document upload workflow for individual KYC:
1

Upload identity document

Upload the identity document (passport):
async function uploadIdentityDocument(userId, passportFile) {
  const formData = new FormData();
  formData.append('userId', userId);
  formData.append('type', 'PASSPORT');
  formData.append('subType', 'SINGLE_SIDE');
  formData.append('issuedCountry', 'US');
  formData.append('file', passportFile);
  
  const response = await fetch('https://sandbox.hifi.com/v2/kyc/documents', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    },
    body: formData
  }).then(r => r.json());
  
  console.log('Passport uploaded:', response.documentId);
  return response;
}
2

Upload proof of address

Upload the proof of address document:
async function uploadProofOfAddress(userId, utilityBillFile) {
  const formData = new FormData();
  formData.append('userId', userId);
  formData.append('type', 'PROOF_OF_ADDRESS');
  formData.append('subType', 'SINGLE_SIDE');
  formData.append('issuedCountry', 'US');
  formData.append('file', utilityBillFile);
  
  const response = await fetch('https://sandbox.hifi.com/v2/kyc/documents', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    },
    body: formData
  }).then(r => r.json());
  
  console.log('Proof of address uploaded:', response.documentId);
  return response;
}
3

Upload driver's license (both sides)

Upload both sides of the driver’s license:
async function uploadDriversLicense(userId, frontFile, backFile) {
  // Upload front
  const frontData = new FormData();
  frontData.append('userId', userId);
  frontData.append('type', 'DRIVERS');
  frontData.append('subType', 'FRONT_SIDE');
  frontData.append('issuedCountry', 'US');
  frontData.append('file', frontFile);
  
  const frontResponse = await fetch('https://sandbox.hifi.com/v2/kyc/documents', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
    body: frontData
  }).then(r => r.json());
  
  console.log('Front side uploaded:', frontResponse.documentId);
  
  // Upload back
  const backData = new FormData();
  backData.append('userId', userId);
  backData.append('type', 'DRIVERS');
  backData.append('subType', 'BACK_SIDE');
  backData.append('issuedCountry', 'US');
  backData.append('file', backFile);
  
  const backResponse = await fetch('https://sandbox.hifi.com/v2/kyc/documents', {
    method: 'POST',
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
    body: backData
  }).then(r => r.json());
  
  console.log('Back side uploaded:', backResponse.documentId);
  
  return { front: frontResponse, back: backResponse };
}
4

Complete KYC workflow

Complete the KYC workflow:
async function completeKYC(userId, documents) {
  // Upload identity document
  await uploadIdentityDocument(userId, documents.passport);
  
  // Upload proof of address
  await uploadProofOfAddress(userId, documents.utilityBill);
  
  // Check KYC status
  const user = await fetch(`https://sandbox.hifi.com/v2/users/${userId}`, {
    headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
  }).then(r => r.json());
  
  console.log('KYC Status:', user.kycStatus);
  
  if (user.kycStatus === 'APPROVED') {
    console.log('KYC approved! User can now offramp.');
  } else if (user.kycStatus === 'PENDING') {
    console.log('KYC under review. Documents are being verified.');
  }
}
5

Handle webhook for document verification

Handle webhook events for document verification:
function handleDocumentWebhook(event) {
  if (event.eventType === 'USER.KYC.UPDATE') {
    const { id, kycStatus, kycRejectionReason } = event.data;
    
    if (kycStatus === 'APPROVED') {
      console.log('KYC approved for user:', id);
      enableOfframping(id);
    } else if (kycStatus === 'REJECTED') {
      console.log('KYC rejected:', kycRejectionReason);
      notifyUserToResubmit(id, kycRejectionReason);
    }
  }
}

Getting Help

  • 📧 Email: support@hifi.com
  • 💬 Slack: Message us in our shared Slack channel
  • Users - Understanding user accounts and KYC status
  • KYC Link - Hosted KYC collection flow
  • Webhooks - Monitor KYC verification status
  • API Reference - Complete endpoint documentation