Verifiable Credentials (VCs) let you issue W3C-standard digital credentials from completed verifications. Users can store these credentials in their wallet and share them with other organizations — enabling one-time KYC with privacy-preserving selective disclosure.
Why Verifiable Credentials?
| Traditional KYC | With Verifiable Credentials |
|---|
| User re-verifies for every service | Verify once, reuse everywhere |
| Full PII shared each time | Selective disclosure — share only what’s needed |
| No user control over shared data | User chooses what to disclose |
| No interoperability between providers | W3C standard — works across platforms |
| High cost per re-verification | Issue once, verify for free |
How It Works
Verification completes
A user completes identity verification through the standard Verilock flow and receives an approved decision.
Credential issuance
You issue a verifiable credential containing selected claims from the verification result. The credential is signed as a JWT with your organization’s DID.
User stores credential
The user receives the credential as a signed JWT. They can store it in a digital wallet (Verilock wallet, or any W3C-compatible wallet).
Selective disclosure
When presenting the credential, the user selectively discloses only the claims required — e.g., “over 18” without revealing their full date of birth.
Third-party verification
Any organization with a Verilock API key can verify the credential’s authenticity, check revocation status, and read only the disclosed claims.
Selective Disclosure
Credentials support selective disclosure, allowing holders to reveal only specific claims:
| Full Credential Claims | Age Check | Identity Check | AML Check |
|---|
| Full name | — | Full name | — |
| Date of birth | — | — | — |
| Nationality | — | Nationality | Nationality |
| Document number | — | — | — |
| Age over 18: true | Age over 18: true | — | — |
| AML clear: true | — | — | AML clear: true |
| Address | — | — | — |
API Endpoints
Issue a Credential
Issue a W3C Verifiable Credential from an approved verification session.
POST /v1/credentials/issue
ID of an approved verification session.
Type of credential: IdentityCredential, AgeCredential, or AddressCredential.
Claims to include. Available: full_name, first_name, last_name, date_of_birth, nationality, document_type, document_number, expiry_date, address, gender, age_over_18, age_over_21, aml_clear, identity_verified.
ISO 8601 expiration date. Default: 1 year from issuance.
curl -X POST \
"https://verilock.io/api/v1/credentials/issue" \
-H "Authorization: Bearer qi_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"session_id": "ses_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"credential_type": "IdentityCredential",
"claims": ["full_name", "nationality", "age_over_18", "aml_clear"],
"expiration": "2027-03-19T00:00:00Z"
}'
{
"id": "vc_e5f6a1b2-c3d4-7890-fedc-ba0987654321",
"status": "issued",
"credential_type": "IdentityCredential",
"issuer_did": "did:verilock:org:your-org-id",
"subject_did": "did:verilock:user:user-uuid",
"claims": ["full_name", "nationality", "age_over_18", "aml_clear"],
"issued_at": "2026-03-19T10:00:00Z",
"expires_at": "2027-03-19T00:00:00Z",
"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6InZjK3NkLWp3dCJ9.eyJpc3MiOiJkaWQ6dmVyaWxvY2s6b3JnOi4uLiIs..."
}
Verify a Credential
Verify a presented credential JWT. Any organization with a valid API key can call this endpoint.
POST /v1/credentials/verify-vc
The credential JWT to verify.
curl -X POST \
"https://verilock.io/api/v1/credentials/verify-vc" \
-H "Authorization: Bearer qi_live_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6InZjK3NkLWp3dCJ9..."}'
{
"valid": true,
"credential_id": "vc_e5f6a1b2-c3d4-7890-fedc-ba0987654321",
"issuer_did": "did:verilock:org:issuing-org-id",
"issuer_verified": true,
"expired": false,
"revoked": false,
"disclosed_claims": {
"full_name": "Jean Dupont",
"nationality": "FR",
"age_over_18": true,
"aml_clear": true
},
"verified_at": "2026-03-19T12:00:00Z"
}
Retrieve the full W3C JSON-LD representation of a credential.
GET /v1/credentials/{id}/vc
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://www.w3.org/ns/credentials/examples/v2"
],
"type": ["VerifiableCredential", "IdentityCredential"],
"issuer": "did:verilock:org:your-org-id",
"validFrom": "2026-03-19T10:00:00Z",
"validUntil": "2027-03-19T00:00:00Z",
"credentialSubject": {
"id": "did:verilock:user:user-uuid",
"full_name": "Jean Dupont",
"nationality": "FR",
"age_over_18": true,
"aml_clear": true
}
}
Revoke a Credential
POST /v1/credentials/{id}/revoke-vc
Revocation reason: user_request, data_correction, fraud_detected, compliance.
Revoked credentials immediately fail verification with revoked: true.
Resolve a DID
Resolve any Verilock DID to its DID Document.
{
"@context": ["https://www.w3.org/ns/did/v1"],
"id": "did:verilock:org:your-org-id",
"verificationMethod": [{
"id": "did:verilock:org:your-org-id#key-1",
"type": "JsonWebKey2020",
"controller": "did:verilock:org:your-org-id"
}],
"authentication": ["did:verilock:org:your-org-id#key-1"],
"assertionMethod": ["did:verilock:org:your-org-id#key-1"],
"service": [{
"id": "#verification",
"type": "VerificationService",
"serviceEndpoint": "https://verilock.io/api/v1"
}]
}
Use Cases
A neobank verifies a user once and issues a VC. The user later signs up for a crypto exchange in the same ecosystem — instead of redoing KYC, they present their credential.
// Neobank: Issue credential after KYC approval
const vc = await neobank.credentials.issue({
session_id: approvedSession.id,
credential_type: 'IdentityCredential',
claims: ['full_name', 'date_of_birth', 'nationality', 'aml_clear'],
});
// Send vc.jwt to user's wallet
// Crypto exchange: Verify the user's credential (no re-KYC needed)
const result = await exchange.credentials.verifyVc({ jwt: userJwt });
if (result.valid && result.disclosed_claims.aml_clear) {
// Onboard user immediately -- no document upload needed
createAccount(result.disclosed_claims);
}
Impact: Onboarding drops from 5 minutes to under 10 seconds. Conversion rate increases by 30%.
2. Age-Gated E-Commerce (Alcohol / Tobacco)
An online retailer needs to verify a buyer is over 18 at checkout, without collecting or storing personal data (GDPR-friendly).
# Issue an AgeCredential with minimal claims
vc = client.credentials.issue(
session_id=session_id,
credential_type="AgeCredential",
claims=["age_over_18"],
expiration="2027-01-01T00:00:00Z",
)
# At checkout, verify the buyer's age credential
result = client.credentials.verify_vc(jwt=buyer_jwt)
if result["valid"] and result["disclosed_claims"]["age_over_18"]:
# Age verified -- no DOB, name, or document stored
proceed_to_payment()
Impact: No PII stored, GDPR Article 5(1)(c) compliant (data minimization). No age verification cost per transaction after initial issuance.
3. Marketplace Trust Layer (Gig Economy)
A freelance marketplace requires verified identities for service providers. Workers verify once and reuse their credential across multiple marketplace platforms.
// Marketplace A verifies the worker
const vc = await marketplaceA.credentials.issue({
session_id: approvedSession.id,
credential_type: 'IdentityCredential',
claims: ['full_name', 'nationality', 'identity_verified', 'aml_clear'],
});
// Marketplace B accepts the same credential
const check = await marketplaceB.credentials.verifyVc({ jwt: workerJwt });
if (check.valid && check.disclosed_claims.identity_verified) {
activateProviderAccount(check.disclosed_claims.full_name);
}
4. Travel & Hospitality (Hotel Check-in)
A hotel chain issues identity credentials to verified guests. Guests use them for instant check-in at any hotel in the chain, without presenting physical ID each time.
# Hotel issues credential after first verification
vc = client.credentials.issue(
session_id=session_id,
credential_type="IdentityCredential",
claims=["full_name", "nationality", "document_type"],
)
# Future check-ins: verify the credential
result = client.credentials.verify_vc(jwt=guest_jwt)
if result["valid"]:
check_in_guest(
name=result["disclosed_claims"]["full_name"],
nationality=result["disclosed_claims"]["nationality"],
)
5. Regulatory Compliance Sharing (Multi-Jurisdiction)
A payment processor operating in the EU and UK issues separate credentials for different regulatory requirements. The user presents the appropriate credential per jurisdiction.
// Issue EU-compliant credential (AMLD6)
const euCred = await verilock.credentials.issue({
session_id: session.id,
credential_type: 'IdentityCredential',
claims: ['full_name', 'date_of_birth', 'nationality', 'aml_clear', 'address'],
});
// Issue UK-compliant credential (FCA)
const ukCred = await verilock.credentials.issue({
session_id: session.id,
credential_type: 'IdentityCredential',
claims: ['full_name', 'date_of_birth', 'nationality', 'aml_clear'],
});
// Each credential is independently verifiable and revocable
Credential Types
| Type | Claims Included | Use Case |
|---|
IdentityCredential | Any combination of identity claims | General KYC, onboarding, compliance |
AgeCredential | age_over_18, age_over_21 only | Age-gated services, minimal data |
AddressCredential | address, country_of_residence | Proof of residence, shipping verification |
Pricing
| Operation | Cost |
|---|
| Issue credential | $0.10 per credential |
| Verify credential | Free |
| Revoke credential | Free |
| DID resolution | Free |
Verifiable Credentials can only be issued from sessions with decision: approved. Attempting to issue from a declined or pending session returns a 422 error.
Combine Verifiable Credentials with Zero-Knowledge Proofs for maximum privacy. Issue a VC with full claims, then let users generate ZK proofs that reveal nothing except “this claim is true.”