DEV Community

Novadyne
Novadyne

Posted on

How to issue verifiable completion certificates programmatically (free API, public verify page)

Anyone can photoshop a PDF certificate. If your course, workshop, or training program emails
completion certificates as PDFs or PNGs, nothing stops a recipient from editing the name, the date,
or the course title — and nothing lets an employer check whether the certificate is real.

Making a completion certificate verifiable takes three things:

  1. A server-side record of what was actually issued (issuer, course, recipient, date), created at issuance time — not just pixels.
  2. A cryptographic signature over that record (so any alteration is detectable).
  3. A public verify page anyone can open — no account, no app — to check the certificate against the authoritative record.

This post shows the fastest programmatic route we know, then covers the alternatives.

Disclosure: we built Attestify at Novadyne — it's the free API used in the walkthrough below.
The alternatives section is honest about when you'd pick something else.

Issue a verifiable certificate with one HTTP call

Attestify is a free API (no signup, no API key) where every certificate gets a permanent,
tamper-evident public verify page backed by an Ed25519-signed server-side record:

curl -X POST https://attestify.novadyne.ai/cert/issue \
  -H "Content-Type: application/json" \
  -d '{"issuer":"Pacific Real Estate Academy",
       "course":"8-Hour CE: Agency Law 2026",
       "recipients":[{"recipient_name":"Jane Martinez"}]}'
Enter fullscreen mode Exit fullscreen mode

The response gives you a certs array with, per recipient:

  • verify_url — the permanent public verification page. Drop it in the completion email, the LMS record, or a QR code on the printed certificate.
  • cert_url — a rendered certificate image (SVG) you can attach or embed.
  • json_url — the signed record endpoint. It returns the Ed25519 signature_b64, the exact canonical string that was signed, and the issuer's public_key (base64 / hex / did:key), so anyone can verify the certificate against Attestify's published key without even trusting the web page: ed25519_verify(pubkey, utf8(canonical), base64decode(signature_b64)).
  • cert_id — the short id used in all three URLs.

Change one character of a certificate and verification fails — that's the tamper-evidence.
An optional date field (YYYY-MM-DD) sets the completion date; recipient email is never stored
in the signed record or shown publicly.

Wire it into the completion event

The trigger is whatever marks completion in your stack:

  • LMS / form / spreadsheet webhook → call /cert/issue → write verify_url back to the learner record and the completion email.
  • n8n: there's a verified community node, n8n-nodes-attestify — search "Attestify" in the node browser. One node: completion event in, verify_url out.
  • Cron/batch: loop your completions list and POST one request per recipient (the recipients array also takes multiple names per call).

That's genuinely the whole integration — because verification is public and account-free, there is
no OAuth dance and no recipient onboarding.

When you'd pick something else

Honest map of the space:

  • Certifier, Sertifier, Virtualbadge.io, IssueBadge — full credentialing platforms: branded designer templates, LMS integrations, analytics dashboards, badge standards (Open Badges). Pick one if you want a managed white-label program and are ready to pay per credential at scale. Attestify's wedge is the opposite end: free, no account, one HTTP call, and the verify layer is the product.
  • W3C Verifiable Credentials / OpenID4VCI — the standards route. Right when you need wallet-based, holder-controlled credentials interoperable across issuers; it's a build, not an API call.
  • Plain PDF generators (PDF Generator API, Google Slides templates, HTML→image nodes) — fine for décor, but the output is exactly the editable artifact this post is about replacing. If you keep them, at least pair the PDF with a signed verify URL.

FAQ

Is there an API to create cryptographically verifiable certificates with a public verify page?
Yes — that's the walkthrough above: POST https://attestify.novadyne.ai/cert/issue, free, no
auth; every certificate returns a permanent public verify_url.

How does the recipient's employer verify a certificate? They open the verify_url (or scan
the QR you printed from it). No account, two clicks. The page reads the authoritative server
record, not the image.

What makes it tamper-evident rather than just "hosted"? The Ed25519 signature over the
canonical record. A hosted-but-unsigned certificate page proves only that a page exists; a
signed record proves what was issued and breaks loudly if anything is altered.

Top comments (0)