Certificates
SecureCodingHub auto-issues a certificate when a user finishes every learn scenario and every practice challenge in an entire category (Web, API, Mobile, Client). These endpoints expose the issued certificates and a public-style verification lookup. Requires the certificates:read scope.
Endpoints
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /certificates/users/{userId} | certificates:read | Certificate status for every category, for one user. |
GET | /certificates/verify/{certNumber} | certificates:read | Verify a certificate by its public number. |
All paths are relative to https://api.limeplate.com/api/public/v1.
How certificates are issued
Issuance is fully automatic — there is no manual "grant" endpoint. The rules:
- One certificate per category per user. The categories are
web,api,mobile, andclient. - A category certificate is issued the moment a user has completed all learn scenarios and all practice challenges in that category.
- Each certificate is assigned a permanent, public-shareable
certificateNumber. - Issuance fires a
certificate.issuedwebhook event. See Webhooks for the payload.
Re-completing content after issuance does not generate a new certificate; the original number is permanent.
List certificate status for a user
Returns one entry per category. Entries where certificateId is null represent categories the user has started but not yet finished — handy for rendering a "you're 18 of 22 challenges away from your Web certificate" UI.
GET /api/public/v1/certificates/users/{userId}
Authorization: Bearer scs_live_…Response
[
{
"categoryId": "web",
"categoryTitle": "Web Application Security",
"certificateId": "7e4c9d09-86ca-4125-bbd8-7fae54c8f654",
"certificateNumber": "SCH-2026-WEB-000123",
"issuedAt": "2026-05-12T08:41:22Z",
"practiceTotal": 75,
"practiceCompleted": 75,
"learnTotal": 22,
"learnCompleted": 22,
"isComplete": true
},
{
"categoryId": "api",
"categoryTitle": "API Security",
"certificateId": null,
"certificateNumber": null,
"issuedAt": null,
"practiceTotal": 60,
"practiceCompleted": 42,
"learnTotal": 18,
"learnCompleted": 14,
"isComplete": false
},
{
"categoryId": "mobile",
"categoryTitle": "Mobile Application Security",
"certificateId": null,
"certificateNumber": null,
"issuedAt": null,
"practiceTotal": 50,
"practiceCompleted": 0,
"learnTotal": 15,
"learnCompleted": 0,
"isComplete": false
},
{
"categoryId": "client",
"categoryTitle": "Client-Side Security",
"certificateId": null,
"certificateNumber": null,
"issuedAt": null,
"practiceTotal": 40,
"practiceCompleted": 6,
"learnTotal": 12,
"learnCompleted": 2,
"isComplete": false
}
]isCompletemirrors "practiceCompleted == practiceTotal && learnCompleted == learnTotal".practiceTotalandlearnTotalare live counts — adding new content to a category does not invalidate already-issued certificates, but it will move an in-progress user's denominators upward.
Example
curl -sS \
-H "Authorization: Bearer $SCH_API_KEY" \
https://api.limeplate.com/api/public/v1/certificates/users/1a2b3c4d-5e6f-7081-9203-4d5e6f708192Verify a certificate
Looks up a certificate by its public number and returns the holder, organization, and category. Use this to back a "Verify your certificate" page on your career site, or to validate a candidate's claim during hiring.
GET /api/public/v1/certificates/verify/{certNumber}
Authorization: Bearer scs_live_…Although the endpoint behaves like a public verification lookup, the API key and certificates:read scope are still required when calling it. If you want truly public verification with no auth, link to the SecureCodingHub-hosted verification URL instead: https://www.securecodinghub.com/verify/{certNumber}.
Response
{
"certificateNumber": "SCH-2026-WEB-000123",
"userName": "Jane Smith",
"organizationName": "Acme Corp",
"categoryId": "web",
"categoryTitle": "Web Application Security",
"issuedAt": "2026-05-12T08:41:22Z"
}Returns 404 certificate_not_found if no certificate with that number exists. Revoked or test-fixture certificate numbers also return 404.
Example
curl -sS \
-H "Authorization: Bearer $SCH_API_KEY" \
https://api.limeplate.com/api/public/v1/certificates/verify/SCH-2026-WEB-000123Receiving certificate events
If you want to push certificates into an HR/talent system the moment they are issued — rather than polling the user endpoint — subscribe to the certificate.issued webhook. The webhook payload includes userId, certificateNumber, categoryId, and issuedAt, mirroring the verification response. See Webhooks.