Complete Know Your Customer (KYC) Verification

Overview

The Know Your Customer (KYC) API enables you to programmatically verify the information of users onboarding to your platform and ensure regulatory compliance. KYC verification of your users is required before they can use BitGo products on your platform.

KYC Webhooks

You can set up webhooks to keep you informed throughout the KYC process. See the Create Enterprise Webhooks guide for more information.

Prerequisites

1. Submit KYC

Submit basic KYC information for your user. If necessary, uploading supporting documents occurs in the next step.

Endpoint: Create Identity

export ACCESS_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 $ACCESS_TOKEN" \
  -d '{
    "enterpriseId": "59cd72485007a239fb00282ed480da1f", # newly created child enterprise for end user
    "userId": "67d28e3dea178ede86f2962e959865a0", # primary contact for the end user of the child enterprise
    "organizationId": "'"$ORGANIZATION_ID"'",
    "nameFirst": "John",
    "nameLast": "Doe",
    "nameMiddle": "F",
    "debugStatus": "passed",
    "debugFailureReason": "expired",
    "phoneNumber": "+442083661173",
    "birthdate": "2025-03-13T00:00:00Z",
    "occupation": "Other - Default",
    "countryOfCitizenship": "USA",
    "countryOfResidence": "USA",
    "govIdCountryOfIssuance": "USA",
    "politicallyExposedPerson": false,
    "addressStreet1": "Street 1",
    "addressStreet2": "Unit 100",
    "addressCity": "City",
    "addressSubdivision": "state",
    "country": "USA",
    "transactionType": "institutionalIndividual",
    "addressPostalCode": "33604"
}'
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',
 addressStreet1: 'Street 1',
 addressCity: 'City',
 addressSubdivision: 'state',
 addressPostalCode: '33604',
 dateOfIncorporation: '2025-03-13T00:00:00Z',
 debugFailureReason: 'expired',
 debugStatus: 'passed',
 enterpriseId: '59cd72485007a239fb00282ed480da1f', // newly created child enterprise for end user
 userId: '67d28e3dea178ede86f2962e959865a0', // primary contact for the end user of the child enterprise
 nameFirst: 'John',
 nameMiddle: 'F',
 nameLast: 'Doe',
 phoneNumber: '+442083661173',
 occupation: 'Other - Default',
 politicallyExposedPerson: false,
 organizationId,
 transactionType: 'institutionalIndividual',
};

response = await superagent
 .post(apiUrl)
 .set('Authorization', `Bearer ${ACCESS_TOKEN}`)
 .set('Accept', 'application/json')
 .send(params);

Note: You can simulate KYC verification failures in the test environment by using the debugStatus and debugFailureReason parameters.

Step Result

You create an identity for KYC purposes and BitGo returns the id and status of the created identity. The status is initiating which confirms that BitGo has received the end user's KYC information and is reviewing it.

{
  "id": "993ec85b-ad23-4259-bde5-703a071a0783",
  "status": "initiating"
}

2. Check KYC status

Check the KYC status of your end user to determine next steps.

Endpoint: Get Identity

export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ORGANIZATION_ID="<YOUR_ORGANIZATION_ID>"
export ENTERPRISE_ID="<CHILD_ENTERPRISE_ID>"
export IDENTITY_ID="<END_USER_IDENTITY_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 $ACCESS_TOKEN"
import superagent from 'superagent';
const ACCESS_TOKEN = '<SERVICE_USER_ACCESS_TOKEN>';
const organizationId = '<YOUR_ORGANIZATION_ID>';
const enterpriseId = '<CHILD_ENTERPRISE_ID>';
const identityId = '<END_USER_IDENTITY_ID>';

const apiUrl = `https://app.bitgo-test.com/api/evs/v1/identity?organizationId=${organizationId}&enterpriseId=${enterpriseId}&identityId=${identityId}`;

const response = await superagent
  .get(apiUrl)
  .set('Authorization', `Bearer ${ACCESS_TOKEN}`);

Note: Use both the organization and enterprise IDs to successfully fetch your end user KYC identity.

Step Result

One of the following KYC statuses is returned:

  • initiating - BitGo confirms receipt of the end user's KYC information.
  • evaluating submission - The KYC information is in initial review by automated checks.
  • awaiting document upload - BitGo requires supporting identity verification documents to continue with the review process.
  • in review - BitGo manually reviews the KYC information.
  • awaiting signature - BitGo completes review of the KYC information and now requires you to confirm verification with a signature.
  • incomplete verifications - BitGo can't complete verification using the provided documents. You must re-upload identity verification documents for the end user. BitGo recommends uploading a different kind of identity verification document.
  • approved - BitGo approves your end user's KYC verification and marks it as complete.
{
    "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

If a user is a United States citizen, you don't need to submit documentation unless BitGo requests it. If an end user needs to submit identity verification documents, their KYC status is awaiting document upload.

If a user isn't a United States citizen, you must submit additional identity verification documents.

BitGo recommends submitting all the necessary documents for an end user in a single API call. Documents must not exceed 15MB in size and must be minimum 200x200px.

Endpoint: Create Identity Document

export IDENTITY_ID="<END_USER_IDENTITY_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"
export ID_CLASS="<DOCUMENT_ID_CLASS>"

curl -X POST \
  "https://app.bitgo-test.com/api/evs/v1/identity/$INTENTY_ID/document" \
  -H "Content-Type: multipart/form-data" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "selectedIdClass": "'"$ID_CLASS"'",
    "frontPhoto": null,
    "backPhoto": null,
    "proofOfResidency": null
}'

Step Result

BitGo receives the supporting documents and validates them to complete KYC verification. The users's KYC status updates to evalutating submission. BitGo asynchronously progresses the status to in review and manually reviews the information. Once approved, the status updates to awaiting signature.

{
  "id": "string",
  "status": "evalutating submission",
  "selectedIdClass": "cct",
  "fileUploads": [
    {
      "fileName": "string",
      "fileSize": 0,
      "uploadStatus": "string",
      "documentType": "frontPhoto"
    }
  ]
}

4. Sign Completed KYC

Once BitGo approves the user's KYC verification, the user must sign to confirm their verification. You can check the status of KYC verifications using the Get Identity endpoint. To complete this step, the status must be awaiting signature.

Endpoint: Submit KYC Signatures

export IDENTITY_ID="<END_USER_IDENTITY_ID>"
export ACCESS_TOKEN="<SERVICE_USER_ACCESS_TOKEN>"

curl -X POST \
  "https://app.bitgo-test.com/api/evs/v1/identity/$IDENTITY_ID/signatures" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_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
    }
  ]'
import superagent from 'superagent';
const ACCESS_TOKEN = '<SERVICE_USER_ACCESS_TOKEN>';
const IDENTITY_ID = '<END_USER_IDENTITY_ID>';

const apiUrl = `https://app.bitgo-test.com/api/evs/v1/identity/${IDENTITY_ID}/signatures`;

const params = [
 {
   "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(apiUrl)
 .set('Authorization', `Bearer ${ACCESS_TOKEN}`)
 .set('Accept', 'application/json')
 .send(params);

Step Result

{
  "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": []
}

Next Steps

Create Go Accounts for your users.

See Also