AEVION Fintech API — Developer reference
33+ REST endpoints across 6 modules. Shared JWT auth. PostgreSQL-backed. Production-ready and live on api.aevion.app.
Quickstart
→ Interactive quickstart: 6 curl examples with copy-buttons → · SDK reference → · Webhooks → · Error codes → · Troubleshooting → · Rate limits → · Code examples → · Migration guide → · Changelog → · API Playground →
Every fintech module gates writes behind the platform JWT. Bootstrap a token once, then use it as Authorization: Bearer <token> on subsequent calls. Read endpoints are unauthenticated where the resource is public (campaign listings, chain head, leaderboards) and JWT-bound everywhere else.
# 1. Register (or POST /api/auth/login if you already have an account)
curl -X POST https://api.aevion.app/api/auth/register \
-H 'Content-Type: application/json' \
-d '{ "email": "you@example.com", "password": "supersecret" }'
# Response: { "token": "<JWT>", "user": { "id": "...", "email": "..." } }
# 2. Export the token and call any fintech endpoint
export AEV_TOKEN='<JWT>'
curl https://api.aevion.app/api/qpaynet/me/dashboard \
-H "Authorization: Bearer $AEV_TOKEN"Conventions
- All bodies and responses are JSON.
Content-Type: application/jsonrequired on writes. - Money is sent and returned in minor units (KZT tiyin, USD cents). Field name is
amountKzt/amountCents; never floats. - Idempotency:
Idempotency-Keyheader onPOST /qpaynet/transfer,/withdraw,/deposit— replays return the original transaction. - Pagination:
?cursor=&limit=on list endpoints, capped at 200. Response includesnextCursorwhen more results exist. - Rate limits: per-IP read 240/min, write 20-60/min, money-moving 30/min.
429on overflow,RateLimit-*headers always present. - Errors:
{ "error": "code", "message": "..." }with accurate HTTP status (400 / 401 / 403 / 404 / 409 / 422 / 429 / 500).
1. QPayNet — fiat wallet rails
End-to-end fiat wallet system with Stripe-backed deposits, P2P transfers, payouts, merchant charge API, payment requests with public pay pages, KYC, refunds, admin reconciliation, and a real-time SSE event stream. The largest fintech surface area in the platform — /api/qpaynet owns the ledger of record for KZT/USD.
- JWT bearer on every owner-scoped route. Admin routes (
/admin/*) additionally require the caller email to appear inQPAYNET_ADMIN_EMAILS. - Merchant API keys (issued via
POST /merchant/keys) authenticatePOST /merchant/chargeviaX-API-Key— no JWT needed for server-to-server billing. - Public pages —
/wallets/:id/public,/requests/:token— are rate-limited but unauthenticated. - Stripe webhook —
/deposit/webhookvalidates theStripe-Signatureheader againstQPAYNET_STRIPE_WEBHOOK_SECRET.
Key endpoints
Example — P2P transfer with idempotency
curl -X POST https://api.aevion.app/api/qpaynet/transfer \
-H "Authorization: Bearer $AEV_TOKEN" \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: transfer-2026-05-10-001' \
-d '{
"fromWalletId": "wal_8f2a...",
"toEmail": "alice@example.com",
"amountKzt": 50000,
"memo": "Coffee debt"
}'
# 200 OK
# {
# "transactionId": "tx_b3c1...",
# "feeKzt": 50,
# "fromBalanceKzt": 1249950,
# "toBalanceKzt": 620050,
# "createdAt": "2026-05-10T14:33:08Z"
# }STRIPE_SECRET_KEY— Stripe live/test secret for Checkout sessions.QPAYNET_STRIPE_WEBHOOK_SECRET— rawwhsec_...for signature verification.QPAYNET_ADMIN_EMAILS— comma-separated allowlist for/admin/*.QPAYNET_DAILY_DEPOSIT_CAP(default 500000) — per-user daily KZT cap pre-KYC.QPAYNET_MAX_TRANSFER(default 100000) — per-tx KZT cap pre-KYC.QPAYNET_KYC_THRESHOLD(default 1000000) — monthly cumulative KZT before KYC mandatory.QPAYNET_PII_SALT— HMAC salt for redacted audit log lookups.SMTP_HOST/SMTP_USER/SMTP_PASS/SMTP_FROM— transaction email delivery.FRONTEND_URL— base URL embedded in receipt + request links.QPAYNET_ALERT_URL— webhook target for reconcile drift > 0.
POST /withdraw— emits VeilNetX-Ledgerwithdrawalentry + Z-Tide eventqpaynet-payout(+3).POST /transfer— emits VeilNetX-Ledgertransferentry; sender and receiver each receive Z-Tideqpaynet-active(+1).POST /deposit/webhookon Stripe success — appends VeilNetXdepositentry + Z-Tideqpaynet-deposit(+2).
2. QMaskCard — virtual payment masks
Meta-tokenization layer that sits between users and the real card rail. Each mask is a unique aev-mask-<32hex>sentinel with its own spend limit, optional merchant-lock or category-lock, and per-charge AI risk score. Merchants never see real PAN/CVV — the mask routes to QPayNet / Stripe for settlement.
- JWT bearer on every endpoint. Masks are bound to
userId— no admin allowlist; users can only see and revoke their own masks. - Charges are authorized server-side by the merchant integration after fraud-score evaluation. Hard declines for risk ≥ 80.
Key endpoints
Example — issue a merchant-locked mask
curl -X POST https://api.aevion.app/api/qmaskcard/masks \
-H "Authorization: Bearer $AEV_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"label": "Spotify monthly",
"kind": "merchant-locked",
"lockedToMerchant": "spotify.com",
"currency": "USD",
"spendLimitCents": 1200,
"expiresAt": "2027-01-01T00:00:00Z"
}'
# 201 Created
# {
# "id": "msk_4f1a...",
# "virtualPan": "aev-mask-3c1f9a8e8b1c4d5e9f0a1b2c3d4e5f60",
# "remainingCents": 1200,
# "status": "active"
# }- None mask-specific beyond shared
DATABASE_URLandAUTH_JWT_SECRET. Settlement-side env (STRIPE_SECRET_KEY) lives in QPayNet.
POST /chargeswhenstatus: authorized— emits VeilNetX-Ledgermask-chargeentry. Decremented balance settles via QPayNet wallet under the hood (when configured).- High-risk charges (score ≥ 70) emit a Z-Tide
qmaskcard-risk-flagevent (-2) on the merchant's userId.
3. VeilNetX-Ledger — settlement chain
Append-only, hash-chained ledger of every fintech state change across the platform. Each entry carries a SHA-256 of the previous head — tampering is detectable end-to-end via GET /chain/verify. The chain is the canonical evidence trail for audits, refunds, and compliance reviews.
- JWT bearer for
POST /entries— only platform-internal services (called from inside other routers) emit entries; user code does not write directly. - Reads (
/entries,/chain/head,/chain/verify,/stats) are public-safe and require no auth — tampering visibility is a feature.
Key endpoints
Example — verify chain integrity
curl https://api.aevion.app/api/veilnetx-ledger/chain/verify
# 200 OK
# {
# "valid": true,
# "height": 18429,
# "headHash": "9c2e8f...3b1a",
# "verifiedAt": "2026-05-10T14:35:22Z",
# "msToVerify": 142
# }
# If tampered:
# { "valid": false, "brokenAt": 8112, "expectedPrevHash": "...", "foundPrevHash": "..." }VEILNETX_SALT— HMAC salt mixed into every hash. Required in production (process refuses to boot without it). Falls back toSHARD_HMAC_SECRETfor legacy installs.
- Acts as the sink, not a source. Receives entries from QPayNet (deposit/withdraw/transfer), QMaskCard (charge), QGood (donation), QChainGov (proposal-close).
- Bureau-grade certificate emission references
chain/headat certificate-issue time as a notarization anchor.
4. Z-Tide — reputation layer
Cross-product reputation system. Every user has a single score (signed int) and a rank label (seedling / sprout / steady / strong / titan). Events from any module add weighted deltas; ranks promote/demote at fixed thresholds. Designed for inbound writes from the platform — not directly from user code.
- Service-key OR admin JWT for
POST /events. Service mode:X-ZTide-Service-Key: $ZTIDE_SERVICE_KEY. Admin mode: caller email inZTIDE_ADMIN_EMAILS. - Open reads:
/leaderboard,/rank/:userId,/statsare public. GET /merequires a JWT bearer — returns the caller's score with recent events.
Key endpoints
Example — ingest a reputation event (service-key mode)
curl -X POST https://api.aevion.app/api/ztide/events \
-H "X-ZTide-Service-Key: $ZTIDE_SERVICE_KEY" \
-H 'Content-Type: application/json' \
-d '{
"userId": "usr_8a2f1b...",
"kind": "qpaynet-payout",
"sourceModule": "qpaynet",
"weight": 3,
"meta": { "transactionId": "tx_b3c1...", "amountKzt": 50000 }
}'
# 201 Created
# {
# "eventId": "evt_4f1a...",
# "newScore": 142,
# "previousRank": "sprout",
# "newRank": "steady",
# "promoted": true
# }ZTIDE_SERVICE_KEY— 32+ char secret for backend-to-backend ingestion. Compared withcrypto.timingSafeEqual.ZTIDE_ADMIN_EMAILS— comma-separated allowlist that can ingest events via JWT instead of service key.
- Pure sink. Every other fintech module ingests events here on state changes (transfer, deposit, donation, vote, mask-charge). Score promotions are surfaced back to the user dashboard via the QPayNet notifications router.
5. QChainGov — on-chain governance
Proposal-vote-execute lifecycle for protocol/treasury/module/partnership decisions. Three vote modes: yes-no-abstain, ranked-choice, weighted. Proposals lock atopen, tally at close, append an entry to VeilNetX-Ledger on outcome.
- JWT bearer for all writes. Anyone can
POST /proposals(as draft);openandcloserequireQCHAINGOV_ADMIN_EMAILS. - One vote per
(proposalId, userId); idempotency enforced at the unique index level. - Reads are public: anyone can list proposals, view votes-so-far, see results.
Key endpoints
Example — cast a yes-no-abstain vote
curl -X POST https://api.aevion.app/api/qchaingov/proposals/prop_8c1a2f/votes \
-H "Authorization: Bearer $AEV_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"choice": "yes",
"reason": "Aligns with the treasury policy ratified Q1 2026."
}'
# 201 Created
# {
# "voteId": "vote_a1b2c3...",
# "tallyNow": { "yes": 87, "no": 12, "abstain": 3 },
# "quorumMet": true,
# "passing": true
# }QCHAINGOV_ADMIN_EMAILS— comma-separated allowlist that can/openand/closeproposals.
POST /proposals/:id/close— emits VeilNetX-Ledgergovernance-decisionentry with full tally + Z-Tideqchaingov-author(+5 if proposal passed, +1 if rejected with quorum, 0 if no quorum).POST /proposals/:id/votes— emits Z-Tideqchaingov-voter(+1) on first vote of the proposal.
6. QGood — charity campaigns
Public campaign listings with admin moderation, donations via QPayNet wallets, transparent on-chain donation receipts (VeilNetX entry per donation). Bonus 6th module — reuses the platform's identity and fintech rails rather than running parallel infra.
- Public reads —
GET /campaignsandGET /campaigns/:idneed no auth. Used for the marketing site. - JWT bearer for
POST /campaigns(anyone can propose) andPOST /campaigns/:id/donations(donor must be authenticated). POST /campaigns/:id/approverequires caller email inQGOOD_ADMIN_EMAILS— otherwise campaigns staypendingand invisible to public reads.
Key endpoints
Example — donate to an active campaign
curl -X POST https://api.aevion.app/api/qgood/campaigns/cmp_2f1a8b/donations \
-H "Authorization: Bearer $AEV_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"walletId": "wal_8f2a...",
"amountKzt": 10000,
"anonymous": false,
"message": "For the kids. Keep going."
}'
# 201 Created
# {
# "donationId": "don_4f1a...",
# "ledgerEntryId": "vnx_b3c1...",
# "transactionId": "tx_a1b2...",
# "campaignTotalKzt": 8420000,
# "thankYouUrl": "https://aevion.app/qgood/cmp_2f1a8b/thanks/don_4f1a..."
# }QGOOD_ADMIN_EMAILS— comma-separated allowlist that can/approvepending campaigns.
POST /campaigns/:id/donations— debits the donor's QPayNet wallet, credits the campaign treasury wallet, appends a VeilNetX-Ledgerdonationentry, and emits Z-Tideqgood-donor(+4).- On campaign approval — emits Z-Tide
qgood-organizer(+2) to the proposer.
OpenAPI spec
The full machine-readable spec for all six modules is generated from the backend at build time and served at GET /api/openapi.json. The source of truth lives in:
aevion-globus-backend/src/lib/openapiFintechSpec.ts
Editing that file extends or amends the surface for any of the six modules. The frontend Stoplight UI at /developers/openapi consumes it directly — no separate sync step. Per-module specs (/api/qpaynet/openapi.json etc.) are scoped slices of the same spec, useful for partner integrations that only touch one module.
Smoke testing
Each fintech module ships a black-box smoke script that exercises its critical path against a running backend (local or production). Combined runner:
# Local: start the backend first cd aevion-globus-backend && npm run dev # leaves http://localhost:4001 running # Then in another shell, from the monorepo root: npm run smoke:all # Or run a single module npm run smoke:qpaynet npm run smoke:qmaskcard npm run smoke:veilnetx-ledger npm run smoke:ztide npm run smoke:qchaingov npm run smoke:qgood # Production: override the base URL SMOKE_BASE=https://api.aevion.app npm run smoke:all
Individual scripts live in aevion-globus-backend/scripts/:
- scripts/qpaynet-smoke.js — 21 steps: wallet, deposit-stub, transfer, request, payout, webhook delivery, admin reconcile.
- scripts/qmaskcard-smoke.js — 7 steps: issue mask, authorize charge, revoke, fraud-score boundary.
- scripts/veilnetx-ledger-smoke.js — 5 steps: append entries, fetch head, verify chain integrity.
- scripts/ztide-smoke.js — 6 steps: service-key auth, ingest events, leaderboard pagination, rank promotion.
- scripts/qchaingov-smoke.js — 9 steps: propose, open, vote x3, close, verify tally + VeilNetX entry.
- scripts/qgood-smoke.js — 6 steps: propose, approve, donate, refund, verify ledger trail.
- scripts/fintech-cross-module-smoke.mjs — 7 steps: cross-module health audit (all 5 fintech modules).
- scripts/fintech-onboarding-guide.mjs — integrator walk-through;
--probehits live health endpoints. - scripts/fintech-stats-aggregator.mjs — CLI stats dashboard;
--jsonemits machine-readable. - scripts/fintech-uptime-monitor.mjs — long-running monitor with p50/p95 latency.
- scripts/fintech-weekly-report.mjs — markdown weekly digest.
Smoke failures exit non-zero and dump the failing step + response body. CI runs the suite on every push against a Postgres + Stripe-test backend; production smokes run post-deploy against api.aevion.app.