Developer documentation

Build with Reedap

The Reedap REST API lets institutions issue, look up, and verify on-chain credentials, sync students and exam results into their LMS/SIS, and receive signed webhooks when meaningful events happen.

JSON over HTTPSBearer API keysHMAC-SHA256 webhooksCursor paginationTenant-scoped

Quickstart

Issue your first certificate in under two minutes.

  1. Open Admin → API integrations and click Create key with the scopes you need.
  2. Copy the key (shown only once) into your secret manager as REEDAP_API_KEY.
  3. Call the API:
curl -X POST "https://reedap.com/api/public/v1/certificates" \
  -H "Authorization: Bearer $REEDAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient_name": "Ada Lovelace",
    "recipient_email": "ada@example.com",
    "course": "Intro to Programming",
    "grade": "A",
    "issue_date": "2026-06-18"
  }'

The response includes a verify_url you can email to recipients or print on a certificate as a QR code.

Authentication

Tenant-scoped API keys, sent as Bearer tokens.

Every request (except public verify) must include an Authorization header:

Authorization: Bearer rdp_live_<prefix>_<secret>

Keys belong to one institution (tenant) and carry a set of scopes. You can create read-only keys for analytics dashboards and full-write keys for production SIS sync.

ScopeGrants
certificates:readList and fetch certificates issued by your institution
certificates:writeIssue new certificates (on-chain mint runs async)
students:readList students who hold your certificates
students:writeInvite students by email; auto-creates accounts
attempts:readRead exam attempt results and scores
Treat keys like passwords. Never put them in client JS, mobile bundles, or git history. Revoke immediately from the dashboard if leaked.

Certificates

Issue, list, and look up credentials.

POST/certificatescertificates:write

Issues a new certificate. Returns the record plus a public verify_url. On-chain anchoring happens asynchronously — status starts as pending and transitions to minted once confirmed on BSC.

Parameters
NameTypeDescription
recipient_namestringRequired. Full name as it appears on the credential.
recipient_emailstring?Optional but recommended — enables student lookup.
coursestringRequired. Program / course title.
gradestring?Optional grade or classification.
issue_dateYYYY-MM-DDRequired.
expiry_dateYYYY-MM-DD?Optional expiration.
metadataobject?Free-form JSON, included in the on-chain hash.
Response
{
  "id": "5f8c…",
  "certificate_id": "REE-2026-ABCD1234",
  "recipient_name": "Ada Lovelace",
  "course": "Intro to Programming",
  "status": "pending",
  "data_hash": "0x9f…",
  "verify_url": "https://reedap.com/api/public/v1/verify/REE-2026-ABCD1234",
  "created_at": "2026-06-18T12:00:00Z"
}
Try it out

Stored locally in this browser only. Create one in Admin → API integrations.

GET/certificatescertificates:read

Lists certificates issued by your institution, newest first. Cursor-paginated.

Parameters
NameTypeDescription
limit1-200, default 50Max records to return.
cursorISO timestampPass next_cursor from the previous page.
recipient_emailemailFilter by student email.
statuspending | minting | minted | revoked | failedFilter by lifecycle state.
Example
curl -G "https://reedap.com/api/public/v1/certificates" \
  -H "Authorization: Bearer $REEDAP_API_KEY" \
  --data-urlencode "limit=20" \
  --data-urlencode "status=minted"
Response
{
  "data": [ { "id": "…", "certificate_id": "REE-…", "status": "minted", … } ],
  "next_cursor": "2026-06-18T11:59:00Z"
}
Try it out

Stored locally in this browser only. Create one in Admin → API integrations.

limit
status
recipient_email
cursor
GET/certificates/{id}certificates:read

Fetch a single certificate by internal UUID or public certificate_id.

Try it out

Stored locally in this browser only. Create one in Admin → API integrations.

id

Students

Enrol students and read your roster.

POST/studentsstudents:write

Invites a student by email. Creates an auth account if needed and adds them to your institution. Idempotent on email.

Example
curl -X POST "https://reedap.com/api/public/v1/students" \
  -H "Authorization: Bearer $REEDAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"new@student.com","full_name":"New Student"}'
Response
{ "user_id": "9f…", "email": "new@student.com", "invited": true }
Try it out

Stored locally in this browser only. Create one in Admin → API integrations.

GET/studentsstudents:read

Returns the unique set of students who hold a certificate from your institution.

Parameters
NameTypeDescription
limit1-200, default 50Max records to return.
emailstringFilter by email.
Try it out

Stored locally in this browser only. Create one in Admin → API integrations.

limit
email

Exam attempts

Sync scores back into your LMS.

GET/attemptsattempts:read

Returns exam attempts across all exams owned by your institution.

Parameters
NameTypeDescription
limit1-200, default 50
cursorISO timestampPagination cursor.
exam_iduuidFilter to a single exam.
passedtrue | falseFilter by outcome.
Response
{
  "data": [
    {
      "id": "…",
      "exam_id": "…",
      "user_id": "…",
      "score": 87.5,
      "passed": true,
      "submitted_at": "2026-06-18T10:30:00Z"
    }
  ],
  "next_cursor": null
}
Try it out

Stored locally in this browser only. Create one in Admin → API integrations.

limit
exam_id
passed
cursor

Public verification

No auth required — anyone can verify.

Use this on a public website or in QR codes printed on your certificates. The endpoint looks up the credential, reads the on-chain record, and confirms the hash matches.

GET/verify/{certificate_id}no auth

Returns the certificate, tenant branding, and on-chain match status.

Example
curl "https://reedap.com/api/public/v1/verify/REE-2026-ABCD1234"
Response
{
  "found": true,
  "certificate": { "recipient_name": "Ada Lovelace", "status": "minted", … },
  "tenant": { "name": "University of Lagos", "slug": "unilag" },
  "onChain": { "configured": true, "exists": true, "matches": true,
               "issuedAt": 1750000000, "revokedAt": 0 }
}
Try it out
certificate_id

Webhooks

Get notified the moment something happens.

Register your endpoint in Admin → API integrations. Reedap POSTs JSON with these headers:

X-Reedap-Event:     certificate.issued
X-Reedap-Signature: sha256=<hex hmac of raw body>
X-Reedap-Delivery:  <uuid>
Content-Type:       application/json
EventWhen it fires
certificate.issuedAfter a certificate is minted on-chain successfully.
certificate.revokedAfter a certificate is revoked (and the chain record updated).
attempt.submittedWhen a student submits an exam attempt.

Verifying signatures

Always verify the signature with a timing-safe comparison before trusting the payload.

import express from "express";
import crypto from "crypto";

const app = express();

app.post("/webhooks/reedap",
  express.raw({ type: "application/json" }), // need RAW body
  (req, res) => {
    const sig = req.header("X-Reedap-Signature") ?? "";
    const expected = "sha256=" + crypto
      .createHmac("sha256", process.env.REEDAP_WEBHOOK_SECRET)
      .update(req.body) // raw Buffer
      .digest("hex");

    if (sig.length !== expected.length ||
        !crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
      return res.status(401).send("invalid signature");
    }

    const { event, data } = JSON.parse(req.body.toString("utf8"));
    if (event === "certificate.issued") {
      // sync to your LMS
    }
    res.status(200).send("ok");
  });
Retries: Deliveries currently fire once and are logged in your dashboard. Respond 2xx within 8 seconds. Long-running work should be queued from your handler.

Errors & rate limits

All errors return JSON:

{ "error": "Missing scope: certificates:write" }
StatusMeaning
200 / 201Success.
400Bad input — see error field for details.
401Missing, malformed, or revoked API key.
403Key is valid but missing the required scope.
404Resource not found within your tenant.
429Rate limited — back off and retry.
5xxServer error — safe to retry idempotent requests.

Every authenticated request is logged with method, path, status, and timestamp, visible to tenant admins in the dashboard.

SDKs & samples

Official SDKs are on the roadmap. The API is plain REST + JSON, so any HTTP client works. Reach out at developers@reedap.com for integration support, sandbox credentials, or to request an SDK in your stack.