ProofCert

ProofCert API Reference

REST API v1 — Solana Devnet

Authentication

Write operations require an X-Api-Key header. To obtain a key, visit /api-demo and request access.

X-Api-Key: <your-institution-api-key>
POST/api/v1/certificatesAuth required

Issue a new certificate and register it on-chain.

Request Body

{
  "issuerSlug":       string  // Your unique institution slug (2-48 chars)
  "issuerName":       string  // Display name
  "recipientName":    string  // Certificate recipient
  "recipientEmail":   string? // Hashed for privacy (never stored plain)
  "recipientWallet":  string? // Optional Solana wallet pubkey
  "title":            string  // Certificate title
  "courseName":       string? // Course or event name
  "certificateType":  "course_completion" | "attendance" | "workshop" |
                      "bootcamp" | "language_level" | "event_participation" | "custom"
  "description":      string? // Max 500 chars
  "competencies":     string[] // List of skills/competencies
  "issuedAt":         string  // ISO 8601 datetime
  "expiresAt":        string? // ISO 8601 datetime or null
}

Response 201

{
  "certificateId":     "CERT-MY-SCHOOL-2026-XXXXX",
  "status":            "registered_onchain",
  "certificateHash":   "sha256:...",
  "solanaTxSignature": "5xH3...kP9q",
  "solanaExplorerUrl": "https://explorer.solana.com/tx/...",
  "verificationUrl":   "https://proofcert.app/verify/...",
  "onchain":           true
}
GET/api/v1/certificatesPublic

List all on-chain certificates. Paginated.

Query Params

?issuer=my-school   // Filter by issuer slug
?limit=50           // Max results (default 50, max 200)
?offset=0           // Pagination offset

Response 200

{
  "certificates": [ { "certificateId": "...", "status": "issued", ... } ],
  "total": 42,
  "limit": 50,
  "offset": 0
}
GET/api/v1/certificates/:idPublic

Fetch a single certificate by its unique certificateId.

Response 200

{
  "certificateId":   "CERT-MY-SCHOOL-2026-XXXXX",
  "certificateHash": "sha256:...",
  "issuerSlug":      "my-school",
  "authority":       "HxK3...base58",
  "issuedAt":        "2026-05-10T09:00:00.000Z",
  "expiresAt":       null,
  "revokedAt":       null,
  "status":          "issued",
  "solanaAddress":   "8xP2...base58",
  "explorerUrl":     "https://explorer.solana.com/address/..."
}
POST/api/v1/certificates/:id/verifyPublic

Verify that a certificate hash matches the on-chain record.

Request Body

{ "expectedHash": "sha256:a1b2c3..." }

Response 200

{
  "valid":       true,
  "hashMatch":   true,
  "onChainHash": "sha256:a1b2c3...",
  "status":      "issued",
  "revokedAt":   null
}

Local Setup

# 1. Clone and install
git clone https://github.com/your-org/proofpass
cd proofpass && npm install

# 2. Configure environment
cp .env.example .env.local
# Edit .env.local — see required variables below

# 3. Run dev server
npm run dev

# 4. (Optional) Build and deploy contract
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"
anchor build
anchor deploy --provider.cluster devnet

Required Environment Variables

NEXT_PUBLIC_APP_URL=http://localhost:3000
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_ISSUER_SECRET_KEY=[1,2,3,...]      # JSON array from solana-keygen
PROOFCERT_ENABLE_ONCHAIN_REGISTRY=true
PROOFCERT_REGISTRY_PROGRAM_ID=6Adp72HQ38UEmqbvyDT5xxMFumcbkMaacRsS2aiAML2N
PROOFCERT_ADMIN_KEY=your-secret-admin-key
PROOFCERT_EXTERNAL_API_KEY=your-api-key-for-institutions
CERTIFICATE_HASH_SALT=change-me

Smart Contract

Program ID: 6Adp72HQ38UEmqbvyDT5xxMFumcbkMaacRsS2aiAML2N (Solana Devnet)

Built with Anchor 0.32.1. Source at programs/proofcert_registry/.

Instructions

InstructionAccessDescription
initialize_registryAdmin (once)Creates the Registry PDA and sets admin wallet
set_issuer_requirementAdminToggle whitelist enforcement on/off
add_issuerAdminAuthorize a wallet to issue certificates
remove_issuerAdminRevoke a wallet's issuer authorization
issue_certificateIssuer / Any*Register a certificate hash on-chain
revoke_certificateCertificate authorityMark a certificate as revoked

* Any wallet can issue when whitelist is disabled.