A REST API for issuing and verifying educational certificates using a custom blockchain and IPFS.
Built with FastAPI, SQLAlchemy (SQLite), and a from-scratch Python blockchain.
app/
main.py # FastAPI entry point, logging config, global error handler
config.py # Centralised settings
database.py # SQLAlchemy engine & session
models/
certificate.py # SQLAlchemy Certificate model
schemas/
certificate.py # Pydantic request/response schemas
verification.py
blockchain.py
services/
certificate_service.py # Issuance orchestration (hash, IPFS, chain, DB)
blockchain_service.py # Lazy blockchain singleton & helpers
ipfs_service.py # IPFS upload wrapper (graceful fallback)
verification_service.py # Verification with block-integrity checks
blockchain/
block.py # Block data structure & SHA-256 hashing
blockchain.py # Chain management, mining, validation, thread-safe I/O
api/
health.py # GET /health (includes DB & chain diagnostics)
certificates.py # POST /certificates, GET /certificates/{id}
verification.py # POST /certificates/verify/file, POST /certificates/verify/id
blockchain.py # GET /blockchain, GET /blockchain/validate
utils/
hashing.py # Shared SHA-256 helper
- Python 3.11+
- IPFS daemon (optional — the app works without it; uploads are skipped gracefully)
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txtipfs daemonIf IPFS is not running, certificates will still be issued but the ipfs_cid field will be null.
uvicorn app.main:app --reloadThe server starts at http://127.0.0.1:8000.
Open http://127.0.0.1:8000/docs for the interactive Swagger UI.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Liveness probe |
POST |
/certificates |
Issue a new certificate (multipart/form-data) |
GET |
/certificates/{certificate_id} |
Retrieve certificate metadata |
POST |
/certificates/verify/file |
Verify by uploading the original file |
POST |
/certificates/verify/id |
Verify by certificate UUID |
GET |
/blockchain |
View the full blockchain |
GET |
/blockchain/validate |
Validate blockchain integrity |
- An institution issues a certificate by uploading a PDF with student details.
- The file is hashed (SHA-256) and optionally uploaded to IPFS.
- A blockchain transaction is created and a new block is mined.
- Certificate metadata is persisted in SQLite.
- Anyone can verify a certificate by re-uploading the file or using its UUID — the system checks the database, confirms the transaction exists on the blockchain, and verifies the containing block's integrity.
Environment variables (all optional — sensible defaults are provided):
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
sqlite:///certificates.db |
SQLAlchemy connection string |
BLOCKCHAIN_FILE |
blockchain.json |
Path to the chain's JSON file |
IPFS_API_URL |
/ip4/127.0.0.1/tcp/5001 |
IPFS HTTP API multiaddr |
MINING_DIFFICULTY |
2 |
Number of leading zeros required for proof-of-work |