Skip to content
Developers

TrueCerta REST API

Issue, verify, and manage digital certificates programmatically. Integrate with your LMS, CRM, or custom application.

v1 — StableBase URL: https://truecerta.com/api/v1

Authentication

All API requests (except public verification) require a Bearer token. Generate API keys in your Dashboard > Settings > API.

curl https://truecerta.com/api/v1/certificates \
  -H "Authorization: Bearer trc_live_your_api_key_here"

Security: API keys grant full access to your organization. Never expose them in client-side code. Store them as environment variables.

Error Handling

Errors return standard HTTP status codes with a JSON body:

{
  "error": {
    "message": "Course not found or does not belong to your organization",
    "code": "not_found"
  }
}

Scroll

ParameterTypeRequiredDescription
401unauthorizedOptionalMissing or invalid API key
403plan_limit_exceededOptionalCertificate or course limit reached for your plan
404not_foundOptionalResource not found
422unprocessable_entityOptionalMissing or invalid parameters
429rate_limitedOptionalToo many requests
500internal_errorOptionalServer error

Certificates

GET
/api/v1/certificates

List all certificates

POST
/api/v1/certificates

Issue a new certificate

GET
/api/v1/certificates/:code

Get a single certificate by code

POST
/api/v1/certificates/:code/revoke

Revoke a certificate

List Certificates

Returns a paginated list of your certificates.

Query Parameters

Scroll

ParameterTypeRequiredDescription
course_iduuidOptionalFilter by course
statusstringOptional"valid", "expired", or "all" (default)
cursorstringOptionalPagination cursor (created_at of last item)
limitnumberOptionalResults per page (max 50, default 50)
curl "https://truecerta.com/api/v1/certificates?status=valid&limit=10" \
  -H "Authorization: Bearer trc_live_your_key"
{
  "data": [
    {
      "id": "uuid",
      "code": "TRC-ACA-26-F5N8K3",
      "holder_name": "Jane Doe",
      "holder_email": "jane@example.com",
      "course_id": "uuid",
      "course_name": "Web Development",
      "issued_at": "2026-03-15T10:00:00Z",
      "expires_at": "2027-03-15T10:00:00Z",
      "claimed_at": "2026-03-16T14:00:00Z",
      "is_claimed": true,
      "created_at": "2026-03-15T10:00:00Z"
    }
  ],
  "pagination": {
    "cursor": "2026-03-15T10:00:00Z",
    "has_more": true
  }
}

Issue a Certificate

Request Body

Scroll

ParameterTypeRequiredDescription
course_iduuidRequiredID of the course
holder_namestringRequiredFull name of the certificate holder
holder_emailstringRequiredEmail of the certificate holder
issued_atISO 8601OptionalCustom issue date (defaults to now)
curl -X POST https://truecerta.com/api/v1/certificates \
  -H "Authorization: Bearer trc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "course_id": "your-course-uuid",
    "holder_name": "Jane Doe",
    "holder_email": "jane@example.com"
  }'

Revoke a Certificate

Scroll

ParameterTypeRequiredDescription
reasonstringOptionalReason for revocation
curl -X POST https://truecerta.com/api/v1/certificates/TRC-ACA-26-F5N8K3/revoke \
  -H "Authorization: Bearer trc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Issued in error"}'

Courses

GET
/api/v1/courses

List all courses

POST
/api/v1/courses

Create a new course

Create a Course

Scroll

ParameterTypeRequiredDescription
namestringRequiredCourse name
descriptionstringOptionalCourse description
validity_period_monthsnumberOptionalCertificate validity in months (null = never expires)
curl -X POST https://truecerta.com/api/v1/courses \
  -H "Authorization: Bearer trc_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Web Development", "validity_period_months": 12}'

Verification (Public)

The verification endpoint is public and does not require authentication. Use it to check the validity of any TrueCerta certificate. CORS headers are included — you can call this endpoint directly from browser JavaScript.

GET
/api/v1/verify/:code

Verify a certificate by code

No authentication required
curl https://truecerta.com/api/v1/verify/TRC-ACA-26-F5N8K3
{
  "valid": true,
  "status": "valid",
  "certificate": {
    "code": "TRC-ACA-26-F5N8K3",
    "holder_name": "Jane Doe",
    "is_claimed": true,
    "issued_at": "2026-03-15T10:00:00Z",
    "expires_at": "2027-03-15T10:00:00Z"
  },
  "course": {
    "name": "Web Development",
    "description": "Full-stack web development course",
    "eqf_level": 5,
    "nlqf_level": "5",
    "qualification_label": "MBO 4"
  },
  "academy": {
    "name": "Academy Name",
    "logo_url": "https://..."
  },
  "links": {
    "verify_page": "https://truecerta.com/v/TRC-ACA-26-F5N8K3",
    "open_badge": "https://truecerta.com/api/obi/assertion/TRC-ACA-26-F5N8K3"
  }
}

Possible status values

Scroll

ParameterTypeRequiredDescription
validstringOptionalCertificate is active and within its validity period
never_expiresstringOptionalCertificate was issued without an expiry date
expiredstringOptionalCertificate has passed its expiry date
renewedstringOptionalCertificate has been superseded by a renewal

Open Badges 2.0

TrueCerta supports the Open Badges 2.0 specification. Each claimed certificate has three JSON-LD endpoints that comply with the IMS Global Open Badges standard.

GET
/api/obi/assertion/:code

OB 2.0 Assertion (the credential)

No authentication required
GET
/api/obi/badge-class/:courseId

OB 2.0 BadgeClass (the credential type)

No authentication required
GET
/api/obi/issuer/:orgId

OB 2.0 Issuer Profile (the academy)

No authentication required

Assertion Example

curl https://truecerta.com/api/obi/assertion/TRC-ACA-26-F5N8K3
{
  "@context": "https://w3id.org/openbadges/v2",
  "type": "Assertion",
  "id": "https://truecerta.com/api/obi/assertion/TRC-ACA-26-F5N8K3",
  "recipient": {
    "type": "email",
    "hashed": true,
    "salt": "TRC-ACA-26-F5N8K3",
    "identity": "sha256$abc123..."
  },
  "badge": "https://truecerta.com/api/obi/badge-class/course-uuid",
  "verification": {
    "type": "HostedBadge"
  },
  "issuedOn": "2026-03-15T10:00:00Z",
  "expires": "2027-03-15T10:00:00Z"
}

Validate badges at openbadgesvalidator.imsglobal.org

Webhooks

Configure webhooks in Dashboard > Settings > Webhooks to receive real-time notifications when certificate events occur.

Events

EventDescription
certificate.issuedA new certificate was issued
certificate.claimedA certificate was claimed by a professional
certificate.revokedA certificate was revoked
certificate.expiringA certificate will expire within 30 days
certificate.expiredA certificate has expired

Payload Format

{
  "event": "certificate.issued",
  "data": {
    "certificate": {
      "id": "uuid",
      "code": "TRC-ACA-26-F5N8K3",
      "holder_name": "Jane Doe",
      "holder_email": "jane@example.com",
      "course_id": "uuid",
      "course_name": "Web Development",
      "issued_at": "2026-03-15T10:00:00Z",
      "expires_at": "2027-03-15T10:00:00Z"
    }
  },
  "timestamp": "2026-03-15T10:00:05Z"
}

Signature Verification

Every webhook delivery includes an X-TrueCerta-Signature header containing an HMAC-SHA256 signature of the request body, using your webhook secret as the key.

// Node.js verification example
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(body)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express example
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-truecerta-signature'];
  const body = JSON.stringify(req.body);

  if (!verifyWebhook(body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }

  const { event, data } = req.body;
  console.log('Received:', event, data);
  res.sendStatus(200);
});

Test Webhook

Send a test event to all your registered webhook endpoints:

curl -X POST https://truecerta.com/api/v1/webhooks/test \
  -H "Authorization: Bearer trc_live_your_key"

Rate Limits

Endpoint typeLimitScope
Authenticated API120 requests / minutePer API key
Public verify / OBI60 requests / minutePer IP
Webhook test5 requests / minutePer organization

Rate-limited responses return 429 Too Many Requests.

Need Help?

Questions about the API? Contact us at support@truecerta.com or visit our contact page.