Documentation

CredAxis Developer Docs

CredAxis is an on-chain academic credential infrastructure built on Base (EVM). Universities deploy their own Registry smart contracts to issue tamper-proof transcripts. External parties — employers, graduate schools, regulators — verify credentials instantly without contacting the institution.

ℹ️
Base URL: All API calls go through https://credaxis.app/api — the Render backend is proxied and never exposed publicly.
🏛️

For Institutions

Universities & schools deploy a Registry contract, whitelist students, and issue on-chain transcripts with one click. The registrar dashboard handles everything.

🎓

For Students

Students connect their wallet, request their transcript, and share a cryptographic proof link with anyone. No PDFs that can be faked.

🔍

For Verifiers

Employers, graduate schools, or HR systems call our Verify API with a record ID or student ID and receive instant, on-chain confirmation.

🛠️

For Developers

Integrate CredAxis into your LMS, HR platform, or verification portal with our REST API and institutional API tokens.

Platform Architecture

University Registrar
Registry Smart Contract
Base L2 (EVM)
On-Chain Event Indexer
Hono + PostgreSQL
Student Wallet
IPFS (Pinata)
Metadata + PDF Hash
CredAxis REST API
credaxis.app/api
External Verifier
Verify Endpoint
GET /api/public/verify
Instant Result ✓

Authentication

Most read endpoints are public and require no authentication. Write operations and private data endpoints require a Privy JWT (for registered users) or a CredAxis institutional API token (prefixed ct_) passed as a Bearer token.

Public

No token required. Read-only access to public registry data.

Privy JWT

Issued on login via Privy. Required for student & registrar write actions.

ct_ token

Institutional API key. Issued by admin. Used for server-to-server verification.

Getting Started

Quickstart Guide

Integrate CredAxis transcript verification into your system in under 5 minutes. No blockchain knowledge required.

01

Get an API Token (for private lookups)

Public transcript verification by record ID requires no token. For private student ID lookups, request an institutional API token from your CredAxis admin or via support@credaxis.app.

ℹ️
Tokens are prefixed ct_ and passed as a Bearer token in the Authorization header.
02

Verify a Transcript by Record ID (Public)

This is the simplest integration — just call the public verify endpoint with the transcript's record ID (a 66-character 0x hash from the blockchain).

cURL — Verify by Record ID
bash
curl -X GET \
  "https://credaxis.app/api/public/verify?recordId=0xaa877681f268a7a927036de034fd930a854f2aec555795b6b612edb479ae2987"
Response
json
{
  "transcript": {
    "recordId": "0xaa877681...",
    "registryAddr": "0x0487722E...",
    "issuedAt": "2025-12-01T10:00:00.000Z",
    "status": "Active",
    "fileHash": "0xabc123...",
    "studentHash": "0xdef456..."
  },
  "student": {
    "fullName": "John Doe",
    "studentId": "UG/CS/2021/001",
    "walletAddress": "0xC52A..."
  },
  "university": {
    "name": "Kwame Nkrumah University",
    "contractAddr": "0x0487722E...",
    "logoUrl": "https://..."
  },
  "authorizedBy": "Direct QR Code / Record ID Link"
}
03

Verify by Student ID (Requires Token)

To look up a transcript by student ID (instead of the on-chain record hash), pass your institutional token.

cURL — Verify by Student ID
bash
curl -X GET \
  "https://credaxis.app/api/public/verify?studentId=UG/CS/2021/001&token=ct_your_token_here"
04

JavaScript / TypeScript Integration

TypeScript — Verify Transcript
typescript
const BASE_URL = "https://credaxis.app/api"

async function verifyTranscript(recordId: string) {
  const res = await fetch(
    `${BASE_URL}/public/verify?recordId=${recordId}`
  )

  if (!res.ok) {
    const err = await res.json()
    throw new Error(err.error || "Verification failed")
  }

  const data = await res.json()
  
  // data.transcript.status === "Active" means valid
  return {
    isValid: data.transcript?.status === "Active",
    student: data.student,
    university: data.university,
    issuedAt: data.transcript?.issuedAt,
  }
}

// Usage
const result = await verifyTranscript("0xaa877681...")
console.log(result.isValid)    // true
console.log(result.student)    // { fullName: "John Doe", ... }
05

Register Your Institution

To request transcripts on behalf of your organisation, register as an institution:

cURL — Register Institution
bash
curl -X POST https://credaxis.app/api/institutions/register \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Graduate School",
    "email": "admissions@acme.edu",
    "walletAddress": "0xYourWalletAddress"
  }'
⚠️
After registration, your institution will be reviewed by a CredAxis admin. You will receive an email upon approval.
API Reference

Verify API

The Verify API is the primary public interface for external systems to check the authenticity of academic credentials on-chain.

GET/api/public/verify

Verify a transcript by its on-chain Record ID or by Student ID (with token). Querying by record ID is fully public — no token needed. Querying by student ID requires a valid institutional token for privacy protection.

Query Parameters

ParameterTypeRequiredDescription
recordIdstringNoThe 0x-prefixed on-chain record ID (keccak256 hash). No token required.
studentIdstringNoThe university student ID. Requires a valid token parameter.
tokenstringNoInstitutional API key (ct_...) or student-approved access token (req_...).
⚠️
You must provide either recordId or studentId. Both together defaults to recordId.

Response — Authorized (Full Data)

200 OK — Full authorized response
json
{
  "transcript": {
    "recordId": "0xaa877681f268...",
    "registryAddr": "0x0487722E60f4...",
    "studentHash": "0xdef456abc...",
    "fileHash": "0x1234abcdef...",
    "issuedAt": "2025-12-01T10:00:00.000Z",
    "status": "Active",
    "issuer": "0xregistrar_address",
    "universityId": 1
  },
  "student": {
    "fullName": "John Doe",
    "studentId": "UG/CS/2021/001",
    "email": "john.doe@example.com",
    "walletAddress": "0xC52A761..."
  },
  "university": {
    "name": "Kwame Nkrumah University of Science and Technology",
    "contractAddr": "0x0487722E60f4...",
    "logoUrl": "https://ipfs.io/ipfs/...",
    "stampUrl": "https://ipfs.io/ipfs/..."
  },
  "authorizedBy": "Institutional API Key (Acme Graduate School)"
}

Response — Public Limited (No Token, Student ID Query)

200 OK — Limited public response
json
{
  "transcript": {
    "recordId": "0xaa877681f268...",
    "registryAddr": "0x0487722E60f4...",
    "issuedAt": "2025-12-01T10:00:00.000Z",
    "status": "Active"
  },
  "university": {
    "name": "Kwame Nkrumah University",
    "logoUrl": "https://...",
    "contractAddr": "0x0487722E..."
  },
  "requestAccessRequired": true
}
POST/api/public/request-access

Allows an external verifier (employer, institution) to request permission from a student to view their full transcript details. The student receives an email and can approve or deny with one click.

Request Body

ParameterTypeRequiredDescription
recordIdstringYesThe on-chain transcript record ID.
requesterNamestringYesFull name of the requester.
requesterOrgstringYesOrganisation or company name.
requesterEmailstringYesEmail where the access token will be sent upon approval.
cURL
bash
curl -X POST https://credaxis.app/api/public/request-access \
  -H "Content-Type: application/json" \
  -d '{
    "recordId": "0xaa877681f268...",
    "requesterName": "Dr. Mary Asante",
    "requesterOrg": "Accra Graduate School",
    "requesterEmail": "m.asante@agsgh.edu"
  }'
Response
json
{
  "success": true,
  "message": "Verification request sent to student email."
}
Upon student approval, a time-limited access token is emailed to the requester. Access is valid for 30 days.
POST/api/public/email-transcript

Sends a formatted, verified transcript receipt email directly to any email address. Useful for sharing proof without exposing the dashboard URL.

cURL
bash
curl -X POST https://credaxis.app/api/public/email-transcript \
  -H "Content-Type: application/json" \
  -d '{
    "to": "employer@company.com",
    "recordId": "0xaa877681f268...",
    "registryAddress": "0x0487722E60f4...",
    "studentName": "John Doe",
    "studentId": "UG/CS/2021/001",
    "gpa": "3.85",
    "major": "BSc Computer Science",
    "gradYear": "2025",
    "universityName": "KNUST"
  }'
GET/api/stats/platform

Returns real-time platform statistics.

Response
json
{
  "totalUniversities": 8,
  "activeUniversities": 6,
  "totalTranscripts": 342,
  "totalVerifications": 1024
}
API Reference

Transcript API

Endpoints for reading transcript records indexed from on-chain events. All transcript data is sourced from the Base blockchain indexer.

GET/api/transcripts/:recordId

Fetch a single transcript by its on-chain record ID.

cURL
bash
curl https://credaxis.app/api/transcripts/0xaa877681f268a7a927036de034fd930a854f2aec555795b6b612edb479ae2987
Response
json
{
  "id": 1,
  "recordId": "0xaa877681...",
  "studentHash": "0x...",
  "fileHash": "0x...",
  "registryAddr": "0x0487722E...",
  "issuer": "0x6912bC40...",
  "issuedAt": "2025-12-01T10:00:00.000Z",
  "status": "Active",
  "universityId": 1
}
GET/api/transcripts/by-student/:studentHash

Returns all transcripts for a student identified by their studentHash (keccak256 of the student's wallet address).

ℹ️
Compute studentHash: keccak256(abi.encodePacked(walletAddress))
Compute studentHash in JS
typescript
import { keccak256, encodePacked } from "viem"

const studentHash = keccak256(
  encodePacked(["address"], ["0xC52A761304DE7DFEea1570361bf190803fF55b6c"])
)
// → "0xdef456abc..."
cURL
bash
curl https://credaxis.app/api/transcripts/by-student/0xdef456abc...
GET/api/transcripts/by-registrar/:address

Returns all transcripts issued by a registrar address.

cURL
bash
curl https://credaxis.app/api/transcripts/by-registrar/0x6912bC40f1446Dd8A2201F797f2c09dca3CeB88c
GET/api/transcripts/by-registry/:addr

Returns all transcripts issued through a specific registry contract address.

cURL
bash
curl https://credaxis.app/api/transcripts/by-registry/0x0487722E60f437F5588BC97501177d1384c84E19
POST/api/transcripts/request

A student submits a request for their transcript. If an active transcript already exists on-chain, it is auto-delivered by email. If not, the registrar is notified to issue one.

ParameterTypeRequiredDescription
studentWalletstringYesThe student's EVM wallet address.
emailstringNoStudent email (optional override).
cURL
bash
curl -X POST https://credaxis.app/api/transcripts/request \
  -H "Content-Type: application/json" \
  -d '{
    "studentWallet": "0xC52A761304DE7DFEea1570361bf190803fF55b6c"
  }'
Response — Auto-Delivered
json
{
  "status": "sent",
  "message": "Official transcript found! A verification receipt has been emailed to you."
}
Response — Queued
json
{
  "status": "requested",
  "message": "Transcript request submitted to your university registrar."
}
⚠️
Rate limit: 3 requests per 6 months per student (semester quota).
GET/api/ipfs/metadata/:cid

Returns the full IPFS metadata JSON pinned to Pinata for a given CID.

cURL
bash
curl https://credaxis.app/api/ipfs/metadata/bafybeig...
POST/api/ipfs/upload🔐 Auth Required

Upload transcript metadata to IPFS via Pinata. Only authenticated registrars can call this. Returns the CID and gateway URL.

ℹ️
Requires a Privy JWT in the Authorization header.
ParameterTypeRequiredDescription
studentAddressstringYesStudent wallet address.
studentNamestringYesFull student name.
studentIdstringYesUniversity student ID.
universityNamestringYesName of the university.
registryAddressstringYesRegistry contract address.
gpastringNoCumulative GPA (e.g. '3.85').
majorstringNoDegree program / major.
levelstringNoAcademic level (e.g. 'MPhil', 'System Design Level').
gradYearstringNoYear of graduation.
fileHashstringNoSHA-256 hash of the PDF document.
API Reference

Institution API

External institutions — graduate schools, employers, regulators — can register on CredAxis to gain API access for requesting and verifying student transcripts in bulk.

ℹ️
Institutions must be approved by a CredAxis admin before making transcript requests. Registration is free.

Institution Lifecycle

1Register via POST /api/institutions/register
2Admin reviews & approves
3Request student transcripts
4Student consents → Access granted
POST/api/institutions/register

Register a new institution on the CredAxis platform.

ParameterTypeRequiredDescription
namestringYesOfficial institution name.
emailstringYesPrimary contact email for the institution.
walletAddressstringYesEVM wallet address for the institution.
cURL
bash
curl -X POST https://credaxis.app/api/institutions/register \
  -H "Content-Type: application/json" \
  -d '{
    "name": "MIT Graduate Admissions",
    "email": "admissions@mit.edu",
    "walletAddress": "0xYourEthAddress"
  }'
Response
json
{
  "success": true,
  "institution": {
    "id": 12,
    "name": "MIT Graduate Admissions",
    "email": "admissions@mit.edu",
    "walletAddress": "0x...",
    "status": "pending"
  }
}
GET/api/institutions/profile/:wallet

Look up an institution's profile and approval status by wallet address.

cURL
bash
curl https://credaxis.app/api/institutions/profile/0xYourEthAddress
Response
json
{
  "id": 12,
  "name": "MIT Graduate Admissions",
  "email": "admissions@mit.edu",
  "walletAddress": "0x...",
  "status": "approved",
  "actionAt": "2025-12-10T09:00:00.000Z"
}
POST/api/institutions/requests

An approved institution requests access to a student's transcript. The student receives an email notification and must consent before the institution can view full transcript details.

ParameterTypeRequiredDescription
institutionIdnumberYesYour institution's ID from the profile endpoint.
studentNamestringYesStudent's full name.
studentIdstringYesStudent's university ID.
studentEmailstringYesStudent's email address for the consent notification.
cURL
bash
curl -X POST https://credaxis.app/api/institutions/requests \
  -H "Content-Type: application/json" \
  -d '{
    "institutionId": 12,
    "studentName": "Ama Osei",
    "studentId": "KNUST/EE/2022/045",
    "studentEmail": "ama.osei@student.knust.edu.gh"
  }'
Response
json
{
  "success": true,
  "request": {
    "id": 88,
    "institutionId": 12,
    "studentName": "Ama Osei",
    "status": "pending"
  }
}
The student receives an email with Approve / Deny buttons. On approval, the institution receives the record ID and full transcript access for 30 days.
GET/api/institutions/requests/:wallet

Get all transcript requests made by an institution.

cURL
bash
curl https://credaxis.app/api/institutions/requests/0xYourEthAddress
PUT/api/institutions/update-profile

Update institution name, email, or wallet address.

ParameterTypeRequiredDescription
oldWalletstringYesCurrent wallet address (used for lookup).
namestringYesNew institution name.
emailstringYesNew email.
walletAddressstringYesNew wallet address.

University Registry Endpoints

GET/api/universities

Returns all registered universities and their smart contract addresses.

cURL
bash
curl https://credaxis.app/api/universities
Response (array)
json
[
  {
    "universityId": 1,
    "name": "Kwame Nkrumah University of Science and Technology",
    "contractAddr": "0x0487722E60f437F5588BC97501177d1384c84E19",
    "registrar": "0x6912bC40f1446Dd8A2201F797f2c09dca3CeB88c",
    "registrarEmail": "registrar@knust.edu.gh",
    "isActive": true,
    "deployedAt": "2025-11-15T08:00:00.000Z",
    "txHash": "0x..."
  }
]
GET/api/universities/by-address/:addr

Resolve a university by its registry smart contract address.

cURL
bash
curl https://credaxis.app/api/universities/by-address/0x0487722E60f437F5588BC97501177d1384c84E19
API Reference

Student API

Endpoints for student onboarding, profile management, and consent control over who can access their credentials.

POST/api/students

Register a new student profile. If the student's email or ID matches a registrar-whitelisted record, they are automatically approved. Otherwise, the application is queued for registrar review.

ParameterTypeRequiredDescription
walletAddressstringYesStudent's EVM wallet address.
fullNamestringYesStudent's full legal name.
studentIdstringYesUniversity-issued student ID.
universityIdnumberYesID of the university (from /api/universities).
emailstringYesStudent's email address.
cURL
bash
curl -X POST https://credaxis.app/api/students \
  -H "Content-Type: application/json" \
  -d '{
    "walletAddress": "0xC52A761304DE7DFEea1570361bf190803fF55b6c",
    "fullName": "John Ato Mensah",
    "studentId": "UG/CS/2021/001",
    "universityId": 1,
    "email": "john.mensah@student.ug.edu.gh"
  }'
Response — Auto-Approved
json
{
  "status": "approved",
  "message": "Onboarding completed. Profile automatically approved via registrar whitelist."
}
Response — Pending Review
json
{
  "status": "pending",
  "message": "Application submitted. Awaiting registrar approval."
}
GET/api/students/profile/:walletAddress

Get a student's full profile by their wallet address.

cURL
bash
curl https://credaxis.app/api/students/profile/0xC52A761304DE7DFEea1570361bf190803fF55b6c
Response
json
{
  "id": 5,
  "walletAddress": "0xC52A761...",
  "fullName": "John Ato Mensah",
  "studentId": "UG/CS/2021/001",
  "email": "john.mensah@student.ug.edu.gh",
  "universityId": 1,
  "status": "approved",
  "createdAt": "2025-11-20T10:00:00.000Z"
}
GET/api/students/profile/by-email/:email

Look up a student by email. Used primarily for the Privy email-auth embedded wallet auto-bind flow.

cURL
bash
curl https://credaxis.app/api/students/profile/by-email/john.mensah%40student.ug.edu.gh
GET/api/students/profile-by-id/:studentId

Find a student by student ID, email, wallet address, or full name (case-insensitive search across all four fields).

cURL
bash
curl https://credaxis.app/api/students/profile-by-id/UG%2FCS%2F2021%2F001
GET/api/students/search?q=:query

Full-text search across all student records (name, email, ID, wallet). Used by registrars in the dashboard search.

cURL
bash
curl "https://credaxis.app/api/students/search?q=john+mensah"
PUT/api/students/:id/self-bind-wallet

Students with a Privy embedded wallet (email login) can self-bind their wallet to a whitelisted record that has no wallet yet.

⚠️
Can only be called once per record. Once a wallet is bound, it cannot be changed by the student — only by a registrar.
ParameterTypeRequiredDescription
walletAddressstringYesNew wallet address to bind.
emailstringYesEmail must match the whitelisted record.
GET/api/student/institution-requests/:email

Returns all institution access requests for a student (by email).

cURL
bash
curl https://credaxis.app/api/student/institution-requests/john.mensah%40student.ug.edu.gh
Response
json
[
  {
    "id": 88,
    "studentName": "John Ato Mensah",
    "status": "pending",
    "institutionName": "MIT Graduate Admissions",
    "createdAt": "2025-12-05T..."
  }
]
PUT/api/student/institution-requests/:id/approve

Student approves an institution's access request. Requires the record ID.

ParameterTypeRequiredDescription
recordIdstringYesThe on-chain record ID the institution is requesting access to.
PUT/api/student/institution-requests/:id/reject

Student rejects an institution's access request.

API Reference

API Keys & Tokens

CredAxis issues institutional API tokens (prefixed ct_) for server-to-server verification. Tokens are issued by admins or registrars and can be revoked at any time.

ℹ️
Tokens are long-lived and intended for backend integrations (e.g., an HR system that automatically verifies applicant transcripts). Do NOT expose tokens in frontend code or mobile apps.
POST/api/tokens/issue🔐 Auth Required

Issue a new institutional API token. Requires Privy JWT authentication.

ParameterTypeRequiredDescription
institutionNamestringYesName of the institution receiving the token.
expiresDaysnumberNoToken expiry in days. Null = never expires.
issuerAddressstringNoWallet address of the issuer (registrar or admin).
rolestringNoRole of the issuer: 'registrar' or 'admin'.
cURL
bash
curl -X POST https://credaxis.app/api/tokens/issue \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <privy_jwt>" \
  -d '{
    "institutionName": "Accra Employment Agency",
    "expiresDays": 365,
    "issuerAddress": "0xRegistrarAddress",
    "role": "registrar"
  }'
Response
json
{
  "success": true,
  "token": "ct_x8k2m4n7p9r1j3w5l8q0v1641234567",
  "institutionName": "Accra Employment Agency",
  "expiresAt": "2026-12-01T00:00:00.000Z"
}
⚠️
Store the token securely. It is only shown once. If lost, you must revoke and reissue.
GET/api/tokens🔐 Auth Required

List all issued tokens. Admins see all tokens; registrars see only tokens they issued.

Query Parameters

ParameterTypeRequiredDescription
issuerAddressstringNoFilter by issuer wallet address.
rolestringNoPass 'admin' to see all tokens.
cURL
bash
curl -H "Authorization: Bearer <privy_jwt>" \
  "https://credaxis.app/api/tokens?role=admin"
DELETE/api/tokens/:id🔐 Auth Required

Revoke (deactivate) an institutional API token by its database ID.

cURL
bash
curl -X DELETE \
  -H "Authorization: Bearer <privy_jwt>" \
  "https://credaxis.app/api/tokens/15?operator=0xAdminAddress"
Response
json
{
  "success": true,
  "message": "Token revoked successfully"
}

Using Tokens for Verification

Once you have a ct_ token, use it in the token query parameter of the Verify API:

Verify with token
bash
curl "https://credaxis.app/api/public/verify?studentId=UG/CS/2021/001&token=ct_x8k2m4n7p9r1j3w5l8q0v1641234567"

This grants full access to the student's transcript details (name, GPA, major, etc.) without requiring individual student consent — the token represents institutional-level trust.

Blockchain

On-Chain Contracts

CredAxis deploys a Factory + Registry pattern on Base Sepolia. The Factory contract deploys individual Registry contracts for each university. All transcript records are stored immutably on-chain.

Deployed Contracts

FactoryBase Sepolia
0x9632D1a3194947CD888b37020261952A6aC52613

The master factory that deploys per-university Registry contracts. Managed by the platform admin.

View on BaseScan ↗
Registry — KNUSTBase Sepolia
0x0487722E60f437F5588BC97501177d1384c84E19

Kwame Nkrumah University of Science and Technology — registry contract for issuing and managing transcript records.

View on BaseScan ↗
Registry — UGBase Sepolia
0x8bc95ae597deaE61b087F45efCA355AF07BBF32B

University of Ghana registry contract.

View on BaseScan ↗
Registry — UCCBase Sepolia
0x862942e757351E5EB84F10d4cA3E143cdF0e2F86

University of Cape Coast registry contract.

View on BaseScan ↗

Registry Contract Interface

Each Registry contract exposes the following key functions. You can interact with them directly via ethers.js / viem or through our REST API.

Registry Contract — Key Functions
solidity
// Register a transcript record on-chain
function registerTranscript(
    bytes32 studentHash,  // keccak256(abi.encodePacked(studentAddress))
    bytes32 fileHash,     // SHA-256 of the transcript PDF
    string calldata ipfsURI
) external onlyRegistrar returns (bytes32 recordId);

// Get a transcript record
function getTranscript(bytes32 recordId) external view returns (
    bytes32 studentHash,
    bytes32 fileHash,
    string memory ipfsURI,
    uint256 issuedAt,
    TranscriptStatus status
);

// Update transcript status (Active, Revoked, Amended)
function updateTranscriptStatus(
    bytes32 recordId,
    TranscriptStatus newStatus,
    string calldata reason
) external onlyRegistrar;

// Grant access to a verifier
function grantAccess(
    bytes32 recordId,
    address verifier
) external;

// Revoke access
function revokeAccess(
    bytes32 recordId,
    address verifier
) external;

On-Chain Events (Indexed by Backend)

The backend micro-indexer listens for these events in real-time and syncs them to the PostgreSQL database:

Indexed Events
solidity
event TranscriptRegistered(
    bytes32 indexed recordId,
    bytes32 indexed studentHash,
    bytes32 fileHash,
    address indexed registrar
);

event TranscriptStatusChanged(
    bytes32 indexed recordId,
    TranscriptStatus oldStatus,
    TranscriptStatus newStatus,
    string reason
);

event AccessGranted(
    bytes32 indexed recordId,
    address indexed verifier,
    address indexed granter
);

event AccessRevoked(
    bytes32 indexed recordId,
    address indexed verifier
);

event UniversityRegistered(
    uint256 indexed universityId,
    string name,
    address registryContract,
    address registrar
);
ℹ️
Direct on-chain reads: You can read transcript data directly from the contract without using our API. However, the API provides enriched data (student names, university metadata, IPFS content) that is not available on-chain.

Reading Contracts with viem

TypeScript — Read contract directly
typescript
import { createPublicClient, http } from "viem"
import { baseSepolia } from "viem/chains"

const client = createPublicClient({
  chain: baseSepolia,
  transport: http("https://sepolia.drpc.org"),
})

// Read a transcript directly from the registry
const result = await client.readContract({
  address: "0x0487722E60f437F5588BC97501177d1384c84E19",
  abi: registryABI,
  functionName: "getTranscript",
  args: ["0xaa877681f268a7a927036de034fd930a854f2aec555795b6b612edb479ae2987"],
})

console.log(result)
// [studentHash, fileHash, ipfsURI, issuedAt, status]
Integration

SDK & Integration Guide

Step-by-step guides for integrating CredAxis verification into your existing systems — whether it's a school management system, HR platform, or government portal.

1. School Management System (LMS) Integration

If you're a school or university that wants to integrate CredAxis into your existing LMS (Moodle, Canvas, etc.), follow these steps:

A

Contact CredAxis Admin

Email support@credaxis.app to request a university registry deployment. We'll deploy a smart contract specifically for your institution.

B

Whitelist Students via CSV

Upload your student roster using the bulk whitelist endpoint. This pre-approves students so they can auto-onboard.

Bulk Student Whitelist
typescript
const response = await fetch("https://credaxis.app/api/students/bulk", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    registrarAddress: "0xYourRegistrarWallet",
    studentsList: [
      { fullName: "Kofi Asante", studentId: "KNUST/EE/2022/001", email: "kofi@student.knust.edu.gh" },
      { fullName: "Ama Osei", studentId: "KNUST/EE/2022/002", email: "ama@student.knust.edu.gh" },
      // ... hundreds of students
    ]
  })
})

const result = await response.json()
// { success: true, processed: 250, details: [...] }
C

Issue Transcripts via API

When a student graduates, upload their transcript metadata to IPFS and register it on-chain through the registrar dashboard or programmatically via the IPFS upload API.

2. HR / Employer Integration

Automate transcript verification in your hiring pipeline:

HR Platform — Auto-verify Applicant
typescript
// In your applicant processing pipeline
async function verifyApplicantCredentials(
  studentId: string,
  apiToken: string
) {
  const res = await fetch(
    `https://credaxis.app/api/public/verify?studentId=${encodeURIComponent(studentId)}&token=${apiToken}`
  )

  if (!res.ok) {
    const err = await res.json()
    return { verified: false, error: err.error, code: err.code }
  }

  const data = await res.json()

  return {
    verified: data.transcript?.status === "Active",
    studentName: data.student?.fullName,
    university: data.university?.name,
    gpa: data.transcript?.fileHash ? "Available via IPFS" : "N/A",
    issuedAt: data.transcript?.issuedAt,
    onChainRecord: data.transcript?.recordId,
  }
}

// Usage in your hiring workflow
const result = await verifyApplicantCredentials(
  "UG/CS/2021/001",
  "ct_your_institutional_token"
)

if (result.verified) {
  console.log(`✅ ${result.studentName} — verified from ${result.university}`)
} else {
  console.log(`❌ Verification failed: ${result.error}`)
}

3. Python Integration

Python — Verify Transcript
python
import requests

BASE_URL = "https://credaxis.app/api"
API_TOKEN = "ct_your_institutional_token"

def verify_transcript(record_id=None, student_id=None):
    params = {}
    if record_id:
        params["recordId"] = record_id
    elif student_id:
        params["studentId"] = student_id
        params["token"] = API_TOKEN

    resp = requests.get(f"{BASE_URL}/public/verify", params=params)
    resp.raise_for_status()
    data = resp.json()

    return {
        "is_valid": data.get("transcript", {}).get("status") == "Active",
        "student": data.get("student"),
        "university": data.get("university"),
    }

# Verify by record ID (public, no token needed)
result = verify_transcript(record_id="0xaa877681f268...")
print(result["is_valid"])  # True

# Verify by student ID (needs token)
result = verify_transcript(student_id="UG/CS/2021/001")
print(result["student"]["fullName"])  # "John Doe"

4. Webhook / Batch Processing

Batch Verification
typescript
const API_TOKEN = "ct_your_token"
const studentIds = [
  "UG/CS/2021/001",
  "KNUST/EE/2022/045",
  "UCC/BA/2023/012",
]

const results = await Promise.all(
  studentIds.map(async (id) => {
    const res = await fetch(
      `https://credaxis.app/api/public/verify?studentId=${encodeURIComponent(id)}&token=${API_TOKEN}`
    )
    const data = await res.json()
    return {
      studentId: id,
      verified: data.transcript?.status === "Active",
      name: data.student?.fullName || "Unknown",
    }
  })
)

console.table(results)
// ┌─────────────────────┬──────────┬────────────────┐
// │ studentId           │ verified │ name           │
// ├─────────────────────┼──────────┼────────────────┤
// │ UG/CS/2021/001      │ true     │ John Doe       │
// │ KNUST/EE/2022/045   │ true     │ Ama Osei       │
// │ UCC/BA/2023/012     │ false    │ Unknown        │
// └─────────────────────┴──────────┴────────────────┘
⚠️
Rate Limits: The API does not currently enforce strict rate limits, but excessive calls (> 1000 req/min) may be throttled. For bulk verification, use sequential batches of 50 with a small delay.
Notifications

Webhooks & Email Notifications

CredAxis sends automated email notifications at every critical step in the credential lifecycle. These replace the need for manual follow-up and ensure all parties stay informed.

Email Notification Triggers

📝

Student Onboarding Request

Recipient: Registrar / Admin
Trigger: Student submits a profile via POST /api/students
Contains: Student name, ID, email, university. One-click Approve/Reject buttons.

Application Approved

Recipient: Student
Trigger: Registrar clicks "Approve" (email or dashboard)
Contains: Confirmation with link to student dashboard.

Application Rejected

Recipient: Student
Trigger: Registrar clicks "Reject"
Contains: Rejection notice with guidance to contact admin.

📜

Transcript Secured (Auto-Delivery)

Recipient: Student
Trigger: Student requests transcript and an active one exists on-chain
Contains: Transcript details (name, major, GPA) with a "View Transcript" link.

🔔

Transcript Request (No Active Record)

Recipient: Registrar
Trigger: Student requests transcript but none exists on-chain
Contains: Student details with "Issue Transcript Now" button.

🔒

Access Request (External Verifier)

Recipient: Student
Trigger: Verifier calls POST /api/public/request-access
Contains: Requester details with Approve/Deny buttons. Access valid for 30 days.

🏢

Institution Access Request

Recipient: Student
Trigger: Approved institution calls POST /api/institutions/requests
Contains: Institution name and link to manage access permissions in the dashboard.

🔓

Access Granted

Recipient: External verifier
Trigger: Student approves access request
Contains: Unique link to view the full verified transcript (30-day expiry).

ℹ️
Email Provider: All emails are sent via SMTP (Gmail or custom SMTP configured by the admin). Styled in the CredAxis dark fintech template. You can customize the branding by forking the email template in backend/utils/email.ts.

One-Click Email Actions

Several emails include one-click action buttons that call backend endpoints directly from the email:

ActionEndpointDescription
Approve StudentGET /api/students/approve-via-token?token=...Registrar one-click approves a student from email.
Reject StudentGET /api/students/reject-via-token?token=...Registrar one-click rejects from email.
Approve AccessGET /api/public/access-requests/approve?token=...Student one-click approves verifier access from email.
Reject AccessGET /api/public/access-requests/reject?token=...Student one-click rejects verifier access from email.
⚠️
Tokens used in email links are single-use and tied to the specific request. They cannot be reused after the action is taken.
Reference

Error Codes & Responses

All API errors return a JSON object with an error field and an HTTP status code. Some endpoints also include a code field for programmatic error handling.

HTTP Status Codes

CodeMeaningTypical Cause
200SuccessRequest completed. Response body contains the requested data.
400Bad RequestMissing required fields, invalid parameters, or duplicate entry.
401UnauthorizedMissing or invalid Bearer token. JWT expired or malformed.
403ForbiddenValid auth but insufficient permissions. Or: token expired/invalid for verify endpoint.
404Not FoundTranscript, student, or university record does not exist.
409ConflictWallet already bound, duplicate registration.
429Too Many RequestsSemester quota exceeded (max 3 transcript requests per 6 months).
500Internal Server ErrorDatabase or server error. Contact support if persistent.
502Bad GatewayPinata/IPFS upstream failure.
503Service UnavailablePinata credentials not configured on the server.

Verify API Error Codes

The GET /api/public/verify endpoint returns a code field for specific error conditions:

CodeHTTP StatusDescription
MISSING_PARAMS400Neither recordId nor studentId was provided.
NOT_FOUND404No transcript record matches the given parameters.
INVALID_TOKEN403The provided access token does not exist or has been revoked.
EXPIRED_TOKEN403The token exists but has passed its expiration date.

Example Error Response

json
// 404 Not Found
{
  "error": "Transcript record not found in the registry.",
  "code": "NOT_FOUND"
}

// 403 Forbidden
{
  "error": "The provided access token is invalid or expired.",
  "code": "INVALID_TOKEN"
}

// 429 Rate Limited
{
  "error": "Semester quota exceeded: You have reached the maximum of 3 official transcript requests for this term."
}

// 400 Bad Request
{
  "error": "Missing required fields"
}

Contact Support

If you encounter persistent 500 errors or unexpected behaviour, please reach out:

Interactive Testing

API Playground

Simulate real-time requests directly against the live proxy API. Ensure your parameters conform to the public API requirements.

Query Parameters

recordId
studentId
token
Response Panel
// Click 'Send Request' to trigger API call...