QRCertificates
Documentation

Build issuance into your own systems

QRCertificates is API-first. Authenticate with a bearer key and automate templates, issuance, batches, and verification from your LMS, SIS, or HR platform.

Base URL & versioning

All endpoints live under the /v1 prefix on your QRCertificates host. In production:

https://qrcertificates.com/v1

Requests and responses are JSON unless noted (template and CSV uploads use multipart form data).

Authentication

Every business endpoint is authenticated with a bearer API key. Create and manage keys in the dashboard under Developers → API keys. A key is shown in full only once, at creation. Send it in the Authorization header (or x-api-key):

curl https://qrcertificates.com/v1/users/me \
  -H "Authorization: Bearer ck_your_api_key"

Writes to /v1/keys require an admin role. Revoking a key takes effect within ~60 seconds (auth results are briefly cached; revocation also busts that cache for immediate effect).

Quickstart: issue a certificate

Issue a single credential from a template. It is rendered, hashed, Ed25519-signed, stored immutably, and (if an email is given) delivered — all asynchronously. The response returns immediately with a certCode and a public verifyUrl.

curl -X POST https://qrcertificates.com/v1/issue \
  -H "Authorization: Bearer ck_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "templateId": "<template-uuid>",
    "recipientName": "Asha Rao",
    "recipientEmail": "[email protected]",
    "variables": { "course": "Data Science", "score": "92%" }
  }'

Response:

{
  "id": "5f3c…",
  "certCode": "QR-3K9F-2A7D",
  "status": "pending",
  "isDemo": false,
  "verifyUrl": "https://qrcertificates.com/verify?code=QR-3K9F-2A7D"
}

Pass "isDemo": true to mint a free, watermarked test certificate that never verifies as genuine.

Endpoint reference

Templates

MethodPathDescription
GET/v1/templatesList templates (supports limit, offset, category).
POST/v1/templatesCreate a template — multipart: background PNG + layout JSON (canvas + positioned fields).
GET/v1/templates/:idFetch one template incl. its layout.
PATCH/v1/templates/:idUpdate name, category, or layout.
DELETE/v1/templates/:idDelete a template.

Issue & certificates

MethodPathDescription
POST/v1/issueIssue a single certificate (see Quickstart).
GET/v1/certificatesList issued certificates for your org.
GET/v1/certificates/:idFetch one certificate.
POST/v1/certificates/:id/revokeRevoke a credential (optional { "reason": "…" }). It then verifies as revoked.
POST/v1/certificates/:id/send(Re)email the certificate to its recipient.

Batches (bulk issuance)

Issue an entire cohort from a CSV (one row per recipient; columns map to template variables), then poll progress.

MethodPathDescription
POST/v1/batchesMultipart: csv file + templateId (+ optional tag). Returns { batchId, total, status }.
GET/v1/batchesList batches.
GET/v1/batches/:idPoll a batch — total, done count, and status.
POST/v1/batches/:id/sendEmail every certificate in the batch.

Billing & credits

MethodPathDescription
GET/v1/creditsCurrent prepaid credit balance (one credit is consumed per non-demo issue).
GET/v1/invoicesList GST-breakdown invoices.

Verification (public, no auth)

Verification is a public GET by certificate code — recipients and employers never need an account. The service independently re-derives the canonical data hash and checks the Ed25519 signature against the platform key, so valid means cryptographically genuine and unrevoked.

curl https://qrcertificates.com/v1/verify/QR-3K9F-2A7D
{
  "status": "valid",
  "certCode": "QR-3K9F-2A7D",
  "recipientName": "Asha Rao",
  "course": "Data Science",
  "issuedAt": "2026-06-30T10:15:00Z",
  "signatureValid": true,
  "issuer": { "tier": "domain", "trusted": true, "label": "acme.edu" },
  "message": "Certificate is valid."
}

status is one of valid, revoked, invalid, demo, or unknown. The human-facing page is /verify?code=<code>.

Webhooks

Register endpoints under Developers → Webhooks to get a signed POST when events happen: certificate.issued, certificate.revoked, batch.completed. Each delivery body is:

{
  "event": "certificate.issued",
  "deliveryId": "…",
  "createdAt": "2026-06-30T10:15:00Z",
  "data": { "certCode": "QR-3K9F-2A7D", "status": "valid", "verifyUrl": "…", "recipientName": "Asha Rao" }
}

Verify authenticity from the X-QRCert-Signature: sha256=<hex> header — it is HMAC-SHA256(rawBody, secret) using the endpoint's signing secret. Delivery is at-least-once; dedupe on X-QRCert-Delivery.

Errors

Errors use standard HTTP status codes with a JSON { "message": "…" } body. Common cases: 401 missing/invalid key, 403 insufficient role, 404 not found, 402/409 out of credits.

Status

Live service status and incident history are published here. For integration help, contact our team.

Issue your first credential in minutes

Start free — no credit card. Design a certificate, issue a verifiable copy, and watch it verify on a public page. Scale to thousands when you are ready.