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

> Source: <https://dev.to/novadynehq/how-to-issue-verifiable-completion-certificates-programmatically-free-api-public-verify-page-4j4l>
> Published: 2026-07-16 08:33:35+00:00

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:

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.*

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"}]}'
```

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.

The trigger is whatever marks completion in your stack:

`/cert/issue`

→ write `verify_url`

back to the
learner record and the completion email.`n8n-nodes-attestify`

— search "Attestify" in the
node browser. One node: completion event in, `verify_url`

out.`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.

Honest map of the space:

**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.
