Crypto-as-a-Service: Complete KYC Verification
Programmatically verify user information for regulatory compliance. See the Guide.
-
You submit basic KYC information for your user to create an identity for KYC purposes. BitGo returns the identity with status
initiating, confirming receipt of the end user's information. You must provide valid tax identification numbers for US individuals.Prerequisites: Set up child enterprise first.
-
You check the KYC status to determine next steps. Status may be
initiating,evaluating submission,awaiting document upload,in review,awaiting signature,approved, ordeclined. Use both organization and enterprise IDs to fetch the identity. -
You submit identity verification documents when status is
awaiting document upload. Non-US citizens require documentation, while US citizens may not. Document files must not exceed 15MB and must be at least 200x200px. BitGo processes documents through automated validation and manual review. -
You submit signatures to confirm KYC verification after BitGo approval when status is
awaiting signature. End users must sign contracts including CSA (Client Service Agreement), MPA (Master Platform Agreement), and MIC (Market Information and Conditions).
// 1. Submit KYC
export SERVICE_USER_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ORGANIZATION_ID="<YOUR_ORGANIZATION_ID>"
curl -X POST \
https://app.bitgo-test.com/api/evs/v1/identity \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SERVICE_USER_TOKEN" \
-d '{
"enterpriseId": "59cd72485007a239fb00282ed480da1f",
"userId": "67d28e3dea178ede86f2962e959865a0",
"organizationId": "'"$ORGANIZATION_ID"'",
"nameFirst": "John",
"nameLast": "Doe",
"nameMiddle": "F",
"debugStatus": "passed",
"debugFailureReason": "",
"phoneNumber": "+442083661173",
"birthdate": "2025-03-13T00:00:00Z",
"occupation": "Other - Default",
"countryOfCitizenship": "USA",
"countryOfResidence": "USA",
"govIdCountryOfIssuance": "USA",
"identificationNumber": "494-14-2205",
"politicallyExposedPerson": false,
"addressStreet1": "Street 1",
"addressStreet2": "Unit 100",
"addressCity": "San Jose",
"addressSubdivision": "CA",
"country": "USA",
"transactionType": "institutionalIndividual",
"addressPostalCode": "33604"
}'
// 2. Check KYC Status
export IDENTITY_ID="<END_USER_IDENTITY_ID>"
export ENTERPRISE_ID="<CHILD_ENTERPRISE_ID>"
curl -X GET \
"https://app.bitgo-test.com/api/evs/v1/identity?organizationId=$ORGANIZATION_ID&enterpriseId=$ENTERPRISE_ID&identityId=$IDENTITY_ID" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SERVICE_USER_TOKEN"
// 3. Submit Documents
export ID_CLASS="<DOCUMENT_ID_CLASS>"
curl -X POST \
"https://app.bitgo-test.com/api/evs/v1/identity/$IDENTITY_ID/document" \
-H "Authorization: Bearer $SERVICE_USER_TOKEN" \
-F "selectedIdClass=$ID_CLASS" \
-F "frontPhoto=@<PATH_TO_FRONT_PHOTO>" \
-F "backPhoto=@<PATH_TO_BACK_PHOTO>" \
-F "proofOfResidency=@<PATH_TO_PROOF_OF_RESIDENCY>"
// 4. Sign Completed KYC
curl -X POST \
"https://app.bitgo-test.com/api/evs/v1/identity/$IDENTITY_ID/signatures" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $SERVICE_USER_TOKEN" \
-d '[
{
"contractSignerNameFull": "John Smith",
"contractSignedDate": "2025-03-13 13:14:09.767480+00:00",
"contractSignedIPAddress": "123.123.123.123",
"contractVersion": "1.0",
"contractType": "csa",
"userAgreesToTerms": true
},
{
"contractSignerNameFull": "John Smith",
"contractSignedDate": "2025-03-13 13:14:09.767480+00:00",
"contractSignedIPAddress": "123.123.123.123",
"contractVersion": "1.0",
"contractType": "mpa",
"userAgreesToTerms": true
},
{
"contractSignerNameFull": "Jerry Smith",
"contractSignedDate": "2025-03-13 13:14:09.767480+00:00",
"contractSignedIPAddress": "123.123.123.123",
"contractVersion": "1.0",
"contractType": "mic",
"userAgreesToTerms": true
}
]'
// 1. Submit KYC
import superagent from 'superagent';
const ACCESS_TOKEN = '<SERVICE_USER_ACCESS_TOKEN>';
const organizationId = '<YOUR_ORGANIZATION_ID>';
const apiUrl = 'https://app.bitgo-test.com/api/evs/v1/identity/';
const params = {
birthdate: new Date().toISOString(),
country: 'USA',
countryOfIncorporation: 'USA',
countryOfCitizenship: 'USA',
countryOfResidence: 'USA',
govIdCountryOfIssuance: 'USA',
identificationNumber: '494-14-2205',
addressStreet1: 'Street 1',
addressCity: 'San Jose',
addressSubdivision: 'CA',
addressPostalCode: '33604',
dateOfIncorporation: '2025-03-13T00:00:00Z',
debugFailureReason: '',
debugStatus: 'passed',
enterpriseId: '59cd72485007a239fb00282ed480da1f',
userId: '67d28e3dea178ede86f2962e959865a0',
nameFirst: 'John',
nameMiddle: 'F',
nameLast: 'Doe',
phoneNumber: '+442083661173',
occupation: 'Other - Default',
politicallyExposedPerson: false,
organizationId,
transactionType: 'institutionalIndividual',
};
let response = await superagent
.post(apiUrl)
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.set('Accept', 'application/json')
.send(params);
// 2. Check KYC Status
const identityId = '<END_USER_IDENTITY_ID>';
const enterpriseId = '<CHILD_ENTERPRISE_ID>';
const statusUrl = `https://app.bitgo-test.com/api/evs/v1/identity?organizationId=${organizationId}&enterpriseId=${enterpriseId}&identityId=${identityId}`;
response = await superagent
.get(statusUrl)
.set('Authorization', `Bearer ${ACCESS_TOKEN}`);
// 3. Submit Documents
import FormData from 'form-data';
import fs from 'fs';
const idClass = '<DOCUMENT_ID_CLASS>';
const docUrl = `https://app.bitgo-test.com/api/evs/v1/identity/${identityId}/document`;
const formData = new FormData();
formData.append('selectedIdClass', idClass);
formData.append('frontPhoto', fs.createReadStream('<PATH_TO_FRONT_PHOTO>'));
formData.append('backPhoto', fs.createReadStream('<PATH_TO_BACK_PHOTO>'));
formData.append('proofOfResidency', fs.createReadStream('<PATH_TO_PROOF_OF_RESIDENCY>'));
response = await superagent
.post(docUrl)
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.send(formData);
// 4. Sign Completed KYC
const signUrl = `https://app.bitgo-test.com/api/evs/v1/identity/${identityId}/signatures`;
const signParams = [
{
"contractSignerNameFull": "John Smith",
"contractSignedDate": "2025-03-13 13:14:09.767480+00:00",
"contractSignedIPAddress": "123.123.123.123",
"contractVersion": "1.0",
"contractType": "csa",
"userAgreesToTerms": true
},
{
"contractSignerNameFull": "Jay Smith",
"contractSignedDate": "2025-03-13 13:14:09.767480+00:00",
"contractSignedIPAddress": "123.123.123.123",
"contractVersion": "1.0",
"contractType": "mpa",
"userAgreesToTerms": true
},
{
"contractSignerNameFull": "Jerry Smith",
"contractSignedDate": "2025-03-13 13:14:09.767480+00:00",
"contractSignedIPAddress": "123.123.123.123",
"contractVersion": "1.0",
"contractType": "mic",
"userAgreesToTerms": true
}
];
response = await superagent
.post(signUrl)
.set('Authorization', `Bearer ${ACCESS_TOKEN}`)
.set('Accept', 'application/json')
.send(signParams);
// 1. Submit KYC Response
{
"id": "993ec85b-ad23-4259-bde5-703a071a0783",
"status": "initiating"
}
// 2. Check KYC Status Response
{
"identities": [
{
"id": "5436ff2e-1129-49f1-8334-1510955ffe00",
"status": "awaiting document upload",
"organizationId": "68928b9066417fe09212fe9965c88552",
"enterpriseId": "690a234346b3252214cdaf72070c549e",
"userId": "690a234046b3252214cdadfe8600df80",
"createdAt": "2025-11-04T16:05:15.359Z",
"updatedAt": "2025-11-04T16:05:17.975Z",
"signaturesSubmitted": [],
"signaturesRequired": []
}
]
}
// 3. Submit Documents Response
{
"id": "02f3186c-8589-4lfa-a800-1e5cc169c726",
"status": "pending",
"selectedIdClass": "pp",
"fileUploads": [
{
"fileName": "passport-front.jpeg",
"fileSize": 11275,
"uploadStatus": "pending",
"documentType": "frontPhoto"
}
]
}
// 4. Sign Completed KYC Response
{
"id": "cf5d766d-bef1-4874-8b02-54ded0e8333e",
"status": "signature submitted",
"organizationId": "6573806ef79cafdd1aff42fbffc2ab20",
"enterpriseId": "67d28e40ea178ede86f296ac90032286",
"userId": "67d28e3dea178ede86f2962e959865a0",
"updatedAt": "2025-03-13T07:59:52.564Z",
"createdAt": "2025-03-13T07:54:18.842Z",
"errorDescription": "",
"signaturesSubmitted": ["csa", "mpa", "mic"],
"signaturesRequired": []
}