Skip to main content
POST
/
kyc
/
validate
Validate KYC status
curl --request POST \
  --url https://kyc.provider.example/opencharge/kyc/validate \
  --header 'Content-Type: application/json' \
  --header 'X-OC-ID: <x-oc-id>' \
  --header 'X-OC-Nonce: <x-oc-nonce>' \
  --header 'X-OC-Signature: <x-oc-signature>' \
  --header 'X-OC-Timestamp: <x-oc-timestamp>' \
  --data '
{
  "user_ocid": 12345,
  "grants": [
    "name",
    "email",
    "phone",
    "id_card",
    "liveness"
  ]
}
'
{
  "user_ocid": 12345,
  "kyc_complete": true,
  "grants": {
    "name": "verified",
    "email": "verified",
    "phone": "verified",
    "id_card": "verified",
    "liveness": "verified",
    "passport": "missing",
    "address": "restricted"
  },
  "verified_at": 1706500000,
  "expires_at": 1738036000
}
Use this endpoint to check if a user has completed KYC and what permissions they’ve granted to your OCID.

Use Cases

  • Check if a user has verified their identity before processing a transaction
  • Determine which KYC data you can request via /kyc/data
  • Verify the user has granted your OCID access to specific data

Verification Statuses

Each KYC item returns one of these statuses:
StatusMeaning
verifiedUser provided this and KYC provider verified it
pendingUser provided this but verification is in progress
missingUser has not provided this information
restrictedUser explicitly denied permission for this item

Implementation

app.post('/kyc/validate', verifyAuth, async (req, res) => {
  const requestingOcid = req.headers['x-oc-id'];
  const { user_ocid, grants } = req.body;

  // Get user's KYC record
  const userKyc = await db.getUserKyc(user_ocid);
  if (!userKyc) {
    return res.status(404).json({
      error: { code: 'USER_NOT_FOUND', message: 'User not found' }
    });
  }

  // Get grants for this requesting OCID
  const userGrants = await db.getKycGrants(user_ocid, requestingOcid);

  // Build status for each requested grant
  const grantStatus = {};
  const checkGrants = grants || Object.keys(userKyc.items);

  for (const grant of checkGrants) {
    if (userGrants.denied?.includes(grant)) {
      grantStatus[grant] = 'restricted';
    } else if (!userKyc.items[grant]) {
      grantStatus[grant] = 'missing';
    } else if (userKyc.items[grant].status === 'pending') {
      grantStatus[grant] = 'pending';
    } else if (userGrants.granted?.includes(grant)) {
      grantStatus[grant] = 'verified';
    } else {
      grantStatus[grant] = 'missing'; // Not granted to this OCID
    }
  }

  res.json({
    user_ocid,
    kyc_complete: userKyc.basic_verified,
    grants: grantStatus,
    verified_at: userKyc.verified_at,
    expires_at: userKyc.expires_at
  });
});

Example: Check Before Transaction

async function checkUserKyc(kycProviderOcid, userOcid, requiredGrants) {
  const response = await fetch(`${kycProviderEndpoint}/kyc/validate`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-OC-ID': MY_OCID,
      'X-OC-Timestamp': timestamp,
      'X-OC-Nonce': nonce,
      'X-OC-Signature': signature
    },
    body: JSON.stringify({
      user_ocid: userOcid,
      grants: requiredGrants
    })
  });

  const result = await response.json();

  // Check if all required grants are verified
  const allVerified = requiredGrants.every(
    grant => result.grants[grant] === 'verified'
  );

  if (!allVerified) {
    // Redirect user to grant page for missing/restricted items
    const missingGrants = requiredGrants.filter(
      grant => result.grants[grant] !== 'verified'
    );
    return { verified: false, missing: missingGrants };
  }

  return { verified: true };
}

Headers

X-OC-ID
string
required

Caller's OCID

X-OC-Timestamp
string
required

Unix timestamp in seconds

X-OC-Nonce
string
required

Unique request identifier

X-OC-Signature
string
required

secp256k1 ECDSA signature

Body

application/json
user_ocid
integer
required

The end user's OCID

grants
string[]

Specific grants to check (optional, returns all if omitted)

Response

KYC validation result

user_ocid
integer
required
kyc_complete
boolean
required

Whether user has completed basic KYC verification

grants
object
required

Status of each KYC item

verified_at
integer

Unix timestamp of last verification

expires_at
integer

Unix timestamp when verification expires