How to Integrate Blockchain Certificate Verification into Your Application
A technical guide for developers on integrating OnChainCert's blockchain certificate verification API into web applications, LMS platforms, and HR systems.
Overview
This guide walks through integrating blockchain certificate verification into your application. Whether you’re building an HR system, learning management platform, or credential verification portal, you’ll learn how to verify certificates programmatically.
Prerequisites
Before starting, ensure you have:
- Basic understanding of REST APIs
- Familiarity with JavaScript/TypeScript (examples provided)
- Access to OnChainCert API credentials
- A Polygon RPC endpoint (optional for direct blockchain queries)
Architecture Overview
OnChainCert provides two verification methods:
| Method | Use Case | Response Time | Cost |
|---|---|---|---|
| API Verification | Most applications | 100-500ms | Free tier available |
| Direct Blockchain | High-security needs | 1-3 seconds | Gas fees apply |
For most integrations, API verification provides the best balance of speed and reliability.
Quick Start: API Verification
Step 1: Obtain API Credentials
Register at OnChainCert Developer Portal to receive:
- API Key (public, safe for frontend)
- API Secret (private, server-side only)
Step 2: Basic Verification Request
const verifyCertificate = async (certificateHash) => {
const response = await fetch(
`https://api.onchaincert.org/v1/verify/${certificateHash}`,
{
headers: {
'X-API-Key': process.env.ONCHAINCERT_API_KEY,
},
}
);
return response.json();
};
Step 3: Handle the Response
A successful verification returns:
{
"valid": true,
"certificate": {
"hash": "0x7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069",
"recipient": "John Doe",
"title": "Advanced Web Development",
"issuer": {
"name": "Tech Academy",
"verified": true,
"walletAddress": "0x..."
},
"issuedAt": "2025-01-15T10:30:00Z",
"blockchain": {
"network": "polygon",
"transactionHash": "0x...",
"blockNumber": 12345678
}
}
}
Integration Patterns
Pattern 1: LMS Integration
For Learning Management Systems, integrate verification at course completion:
class CertificateService {
async issueCertificate(courseId, userId) {
const course = await this.getCourse(courseId);
const user = await this.getUser(userId);
const certificateData = {
recipient: user.fullName,
email: user.email,
title: course.certificateTitle,
description: course.description,
completedAt: new Date().toISOString(),
metadata: {
courseId,
score: user.finalScore,
hoursCompleted: course.duration,
},
};
const response = await fetch('https://api.onchaincert.org/v1/issue', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.ONCHAINCERT_API_KEY,
'X-API-Secret': process.env.ONCHAINCERT_API_SECRET,
},
body: JSON.stringify(certificateData),
});
return response.json();
}
}
Pattern 2: HR System Verification
For applicant credential verification during hiring:
const verifyApplicantCredentials = async (applicant) => {
const verificationResults = await Promise.all(
applicant.certificates.map(async (cert) => {
const result = await verifyCertificate(cert.hash);
return {
claimed: cert.title,
verified: result.valid,
issuer: result.certificate?.issuer?.name,
match: result.certificate?.recipient === applicant.name,
};
})
);
return {
applicantId: applicant.id,
totalCertificates: verificationResults.length,
verified: verificationResults.filter(r => r.verified && r.match).length,
flagged: verificationResults.filter(r => !r.verified || !r.match),
};
};
Pattern 3: Public Verification Portal
For building a public-facing verification page:
// React component example
function VerificationPortal() {
const [hash, setHash] = useState('');
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
const handleVerify = async () => {
setLoading(true);
try {
const response = await fetch(`/api/verify?hash=${hash}`);
const data = await response.json();
setResult(data);
} finally {
setLoading(false);
}
};
return (
<div>
<input
value={hash}
onChange={(e) => setHash(e.target.value)}
placeholder="Enter certificate hash or URL"
/>
<button onClick={handleVerify} disabled={loading}>
{loading ? 'Verifying...' : 'Verify Certificate'}
</button>
{result && <VerificationResult data={result} />}
</div>
);
}
Direct Blockchain Verification
For applications requiring maximum security and trustlessness:
import { ethers } from 'ethers';
const ONCHAINCERT_CONTRACT = '0x...'; // Contract address on Polygon
const ABI = [
'function verifyCertificate(bytes32 hash) view returns (bool valid, address issuer, uint256 timestamp)',
];
const verifyOnChain = async (certificateHash) => {
const provider = new ethers.JsonRpcProvider(
process.env.POLYGON_RPC_URL
);
const contract = new ethers.Contract(
ONCHAINCERT_CONTRACT,
ABI,
provider
);
const [valid, issuer, timestamp] = await contract.verifyCertificate(
certificateHash
);
return {
valid,
issuer,
issuedAt: new Date(timestamp * 1000),
};
};
Error Handling
Common error responses and how to handle them:
| Error Code | Meaning | Action |
|---|---|---|
| 404 | Certificate not found | Check hash format, may be invalid |
| 410 | Certificate revoked | Display revocation notice |
| 429 | Rate limit exceeded | Implement exponential backoff |
| 500 | Server error | Retry with backoff, contact support |
const verifyWithErrorHandling = async (hash) => {
try {
const result = await verifyCertificate(hash);
return { success: true, data: result };
} catch (error) {
if (error.status === 404) {
return { success: false, error: 'Certificate not found' };
}
if (error.status === 410) {
return { success: false, error: 'Certificate has been revoked', revoked: true };
}
if (error.status === 429) {
await sleep(1000);
return verifyWithErrorHandling(hash);
}
throw error;
}
};
Webhooks for Real-Time Updates
Subscribe to certificate events:
// Webhook endpoint configuration
app.post('/webhooks/onchaincert', (req, res) => {
const { event, data } = req.body;
switch (event) {
case 'certificate.issued':
handleNewCertificate(data);
break;
case 'certificate.revoked':
handleRevocation(data);
break;
case 'issuer.verified':
handleIssuerVerification(data);
break;
}
res.status(200).send('OK');
});
Security Best Practices
- Never expose API secrets in frontend code
- Validate certificate hashes before querying
- Implement rate limiting on your verification endpoints
- Cache verification results appropriately (5-15 minutes recommended)
- Log all verification attempts for audit trails
Testing
Use the sandbox environment for development:
const API_BASE = process.env.NODE_ENV === 'production'
? 'https://api.onchaincert.org'
: 'https://sandbox.onchaincert.org';
Sandbox provides test certificates and simulated blockchain responses without real transactions.
Next Steps
- Review the complete API documentation
- Explore SDK libraries for Python, Go, and PHP
- Join the developer community for support
This guide is maintained by the OnChainCert engineering team. For technical support, contact [email protected]
OnChainCert Team
OnChainCert