The API backbone of Kora Protocol β decentralized invoice financing on Stellar Soroban.
- Overview
- What Kora Does
- Architecture
- Tech Stack
- Project Structure
- Getting Started
- Environment Variables
- API Reference
- Core Flows
- Testing
- Health Checks
- Roadmap
- Contributing
- License
Kora Protocol bridges the gap between SMEs in emerging markets (Africa, Asia, Latin America) who need working capital and global investors seeking yield on short-duration, real-world assets.
The problem: SMEs collectively hold trillions in unpaid invoices. Traditional invoice financing is slow, expensive, and gatekept behind legacy financial infrastructure.
The solution: Kora tokenizes invoices as NFTs on Stellar Soroban. Investors fund them with USDC. Settlement is instant, transparent, and fully non-custodial.
SME Kora Backend Investor
β β β
ββ POST /auth/challenge ββββΊ β
βββ nonce ββββββββββββββββββ€ β
β (sign nonce in wallet) β β
ββ POST /auth/verify βββββββΊ validate Ed25519 sig β
βββ JWT ββββββββββββββββββββ€ β
β β β
ββ POST /invoices ββββββββββΊ validate + risk-score β
βββ invoiceId ββββββββββββββ€ store in-memory β
β β β
ββ POST /ipfs/upload ββββββββΊ upload PDF β Pinata β
βββ pdfCid βββββββββββββββββ€ β
ββ POST /ipfs/metadata ββββββΊ upload JSON β Pinata β
βββ metadataCid ββββββββββββ€ β
β β β
ββ POST /stellar/build/mintβΊ build unsigned XDR β
βββ XDR ββββββββββββββββββββ€ β
β (sign XDR in wallet) β β
β (submit to Soroban RPC) β β
ββ POST /invoices/mint ββββββΊ record tokenId, CIDs β
β β status β LISTED β
β β β
β βββ GET /marketplace ββββββββββββ€
β β (filter by risk, APR, etc.) β
β ββ paginated listings βββββββββββΊ
β β β
β βββ POST /stellar/build/fund ββββ€
β ββ unsigned XDR βββββββββββββββββΊ
β β (sign + submit to Soroban) β
β β β
β βββ POST /marketplace/fund ββββββ€
β ββ record position, update amt ββΊ
βββ USDC arrives βββββββββββ€ β
See docs/ARCHITECTURE.md for the full architecture document, including:
- Module dependency graph
- Request lifecycle diagrams
- Authentication flow
- Soroban integration pattern
- Database migration path (v0.2 roadmap)
| Layer | Technology |
|---|---|
| Framework | NestJS 10 (Express adapter) |
| Language | TypeScript 5.5 |
| Auth | JWT + Stellar Ed25519 wallet signature |
| Blockchain | Stellar Soroban via @stellar/stellar-sdk |
| File Storage | IPFS via Pinata REST API |
| Validation | KoraValidationPipe (class-validator + class-transformer) |
| API Docs | Swagger / OpenAPI (auto-generated) |
| Rate Limiting | @nestjs/throttler (global via APP_GUARD) |
| Security | helmet + CORS whitelist |
| Logging | Custom LoggerMiddleware (method, status, duration, IP) |
| Testing | Jest + @nestjs/testing |
kora-backend/
βββ src/
β βββ main.ts # Bootstrap: Swagger, CORS, helmet, pipes
β βββ app.module.ts # Root module β wires all feature modules
β β
β βββ auth/ # Wallet-based authentication
β β βββ auth.controller.ts # POST /auth/challenge, /auth/verify, GET /auth/me
β β βββ auth.service.ts # Nonce generation + Ed25519 signature verification
β β βββ auth.service.spec.ts # Unit tests
β β βββ auth.module.ts
β β βββ dto/auth.dto.ts
β β βββ guards/jwt-auth.guard.ts
β β βββ strategies/jwt.strategy.ts
β β
β βββ invoice/ # Invoice lifecycle (SME side)
β β βββ invoice.controller.ts # CRUD + search + mint-record + repay + default
β β βββ invoice.service.ts # In-memory store + risk scoring + keyword search
β β βββ invoice.service.spec.ts # Unit tests (20+ cases)
β β βββ invoice.module.ts
β β βββ dto/invoice.dto.ts
β β βββ entities/invoice.entity.ts
β β
β βββ marketplace/ # Investor marketplace
β β βββ marketplace.controller.ts # GET listings, POST fund, GET positions
β β βββ marketplace.service.ts # Filter/sort + funding logic
β β βββ marketplace.service.spec.ts # Unit tests
β β βββ marketplace.module.ts
β β βββ dto/marketplace.dto.ts
β β
β βββ ipfs/ # IPFS / Pinata integration
β β βββ ipfs.controller.ts # POST upload (multipart), POST metadata (JSON)
β β βββ ipfs.service.ts # Pinata pinFileToIPFS + pinJSONToIPFS
β β βββ ipfs.service.spec.ts # Unit tests (mocked axios)
β β βββ ipfs.module.ts
β β
β βββ stellar/ # Soroban contract interaction
β β βββ stellar.controller.ts # POST build/mint, POST build/fund, GET invoice/:tokenId
β β βββ stellar.service.ts # Unsigned XDR builders + on-chain reads
β β βββ stellar.module.ts
β β βββ dto/stellar.dto.ts
β β
β βββ analytics/ # Protocol and portfolio analytics
β β βββ analytics.controller.ts # protocol, risk, categories, investor, jurisdictions, trends
β β βββ analytics.service.ts
β β βββ analytics.module.ts
β β
β βββ health/ # Health checks
β β βββ health.controller.ts # GET /health, GET /health/ready
β β βββ health.service.ts
β β βββ health.module.ts
β β
β βββ common/
β βββ types/index.ts # Shared enums, interfaces, paginate() helper
β βββ middleware/
β β βββ logger.middleware.ts # HTTP request logger
β βββ pipes/
β β βββ validation.pipe.ts # KoraValidationPipe (structured errors)
β βββ filters/
β β βββ http-exception.filter.ts
β βββ interceptors/
β β βββ response.interceptor.ts
β βββ exceptions/
β βββ invoice-not-found.exception.ts
β
βββ docs/
β βββ ARCHITECTURE.md
β βββ API.md
β βββ CHANGELOG.md
β βββ DEPLOYMENT.md
β βββ SECURITY.md
β βββ TESTING.md
β
βββ test/
β βββ app.e2e-spec.ts
β
βββ .github/
β βββ ISSUE_TEMPLATE/
β β βββ bug_report.md
β β βββ feature_request.md
β βββ PULL_REQUEST_TEMPLATE.md
β
βββ .env.example
βββ .gitignore
βββ nest-cli.json
βββ package.json
βββ tsconfig.json
βββ tsconfig.build.json
βββ CONTRIBUTING.md
βββ LICENSE
- Node.js 20+ and npm
- A Pinata account β pinata.cloud (free tier works)
- Deployed Soroban contracts (testnet) β or leave blank to run in HTTP-only mode
# 1. Clone the repository
git clone https://github.com/king-aj-the-first/kora-backend.git
cd kora-backend
# 2. Install dependencies
npm install
# 3. Copy and configure environment variables
cp .env.example .env
# Open .env and fill in JWT_SECRET and PINATA_JWT at minimum
# 4. Start in development mode (hot-reload)
npm run start:devThe server starts on http://localhost:3001. Interactive API docs are at http://localhost:3001/api/docs.
# Build image
docker build -t kora-backend .
# Run container
docker run -p 3001:3001 --env-file .env kora-backendSee docs/DEPLOYMENT.md for full Docker and PM2 guides.
| Variable | Required | Default | Description |
|---|---|---|---|
PORT |
No | 3001 |
HTTP port |
NODE_ENV |
No | development |
development / production |
JWT_SECRET |
Yes | β | Secret for signing JWTs |
JWT_EXPIRES_IN |
No | 7d |
JWT expiry |
STELLAR_NETWORK |
No | testnet |
testnet / mainnet |
STELLAR_RPC_URL |
No | SDF testnet | Soroban RPC endpoint |
STELLAR_NETWORK_PASSPHRASE |
No | SDF testnet passphrase | Network passphrase |
INVOICE_CONTRACT_ID |
No | β | Deployed invoice NFT contract |
MARKETPLACE_CONTRACT_ID |
No | β | Deployed marketplace contract |
PINATA_JWT |
Yes (for uploads) | β | Pinata API JWT |
PINATA_GATEWAY |
No | Pinata gateway | Public IPFS gateway URL |
CORS_ORIGINS |
No | http://localhost:3000 |
Comma-separated allowed origins |
THROTTLE_TTL |
No | 60 |
Rate-limit window in seconds |
THROTTLE_LIMIT |
No | 100 |
Max requests per window |
Full interactive documentation is served at /api/docs (Swagger UI) when the server is running.
For a static reference, see docs/API.md.
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/api/v1/auth/challenge |
β | Request sign challenge |
POST |
/api/v1/auth/verify |
β | Verify signature, get JWT |
GET |
/api/v1/auth/me |
JWT | Current wallet profile |
GET |
/api/v1/invoices |
β | List all invoices (paginated) |
GET |
/api/v1/invoices/search |
β | Search invoices by keyword/status/risk |
GET |
/api/v1/invoices/my |
JWT | My invoices (SME) |
GET |
/api/v1/invoices/:id |
β | Invoice detail |
POST |
/api/v1/invoices |
JWT | Create invoice |
PATCH |
/api/v1/invoices/:id |
JWT | Update invoice (owner) |
POST |
/api/v1/invoices/mint |
JWT | Record successful mint |
POST |
/api/v1/invoices/:id/repay |
JWT | Mark invoice as repaid |
POST |
/api/v1/invoices/:id/default |
JWT | Mark invoice as defaulted |
DELETE |
/api/v1/invoices/:id |
JWT | Delete PENDING invoice |
GET |
/api/v1/marketplace |
β | Listed invoices (filterable) |
POST |
/api/v1/marketplace/fund |
JWT | Fund an invoice |
GET |
/api/v1/marketplace/positions |
JWT | My investment positions |
POST |
/api/v1/ipfs/upload |
JWT | Upload PDF to IPFS |
POST |
/api/v1/ipfs/metadata |
JWT | Upload metadata JSON |
POST |
/api/v1/stellar/build/mint |
JWT | Get unsigned mint XDR |
POST |
/api/v1/stellar/build/fund |
JWT | Get unsigned fund XDR |
GET |
/api/v1/stellar/invoice/:tokenId |
JWT | Read on-chain invoice |
GET |
/api/v1/analytics/protocol |
β | Protocol-wide stats |
GET |
/api/v1/analytics/risk |
β | Risk tier distribution |
GET |
/api/v1/analytics/categories |
β | Volume by category |
GET |
/api/v1/analytics/jurisdictions |
β | Volume by jurisdiction |
GET |
/api/v1/analytics/trends |
β | Monthly invoice trend |
GET |
/api/v1/analytics/investor |
JWT | Investor portfolio summary |
GET |
/api/v1/health |
β | Liveness probe |
GET |
/api/v1/health/ready |
β | Readiness probe |
1. POST /auth/challenge β nonce
2. Sign nonce in wallet
3. POST /auth/verify β JWT
4. POST /invoices β invoiceId (off-chain record created, status: PENDING)
5. POST /ipfs/upload β pdfCid
6. POST /ipfs/metadata β metadataCid
7. POST /stellar/build/mint β unsigned XDR
8. Sign XDR in wallet β submit to Soroban RPC directly
9. POST /invoices/mint β record tokenId + CIDs β status: LISTED
1. GET /marketplace β browse LISTED invoices (filter by risk, APR, categoryβ¦)
2. POST /auth/challenge + verify β JWT
3. POST /stellar/build/fund β unsigned XDR (tokenId + USDC amount)
4. Sign XDR in wallet β submit to Soroban RPC directly
5. POST /marketplace/fund β record off-chain position, update amountFunded
6. GET /marketplace/positions β view portfolio with expectedYield per invoice
1. Invoice reaches status: FULLY_FUNDED
2. SME initiates USDC transfer on-chain (via wallet)
3. POST /invoices/:id/repay β status: REPAID
4. Investors collect yield off-chain (v0.1) / on-chain distribution (v0.2+)
# Run all unit tests
npm run test
# Run with coverage report
npm run test:cov
# Run in watch mode during development
npm run test:watch
# Run end-to-end tests
npm run test:e2eSee docs/TESTING.md for the full test strategy, coverage expectations, and how to write new tests.
# Liveness β is the server up?
curl http://localhost:3001/api/v1/health
# Readiness β are all dependencies configured?
curl http://localhost:3001/api/v1/health/readyExample readiness response:
{
"status": "degraded",
"uptime": 120,
"timestamp": "2025-07-10T12:00:00.000Z",
"version": "0.1.0",
"services": [
{ "name": "jwt", "status": "ok", "detail": "JWT_SECRET is set" },
{ "name": "pinata_ipfs", "status": "not_configured", "detail": "PINATA_JWT missing β uploads will fail" },
{ "name": "stellar_rpc", "status": "ok", "detail": "Using SDF testnet default" },
{ "name": "invoice_contract", "status": "not_configured", "detail": "INVOICE_CONTRACT_ID not set" },
{ "name": "marketplace_contract", "status": "not_configured", "detail": "MARKETPLACE_CONTRACT_ID not set" }
]
}| Version | Feature |
|---|---|
| v0.1 | β REST API scaffold, auth, invoice CRUD + search, IPFS, Soroban XDR builders, analytics, health checks |
| v0.2 | Postgres + Prisma ORM, persistent state, testnet contract deployment |
| v0.3 | KYC/KYB webhook integration |
| v0.4 | Secondary market API endpoints |
| v0.5 | Risk oracle integration (on-chain credit scoring) |
| v1.0 | Mainnet, multi-currency (EURC, XLM), production hardening |
We welcome contributions from developers, protocol designers, and domain experts in emerging-market finance.
Read the full guide: CONTRIBUTING.md
Key steps:
- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature - Commit using Conventional Commits
- Open a pull request against
main
Use our issue templates for bug reports and feature requests, and the PR template to structure your contribution.
MIT Β© 2025 Kora Protocol Contributors
See LICENSE for full text.