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.