Backend services
Every service is a NestJS app exposing routes under /api/v1/<service>/…, reached only through the API gateway. All paths below are relative to that prefix. Each service also exposes GET …/health.
API Gateway
The single public entry point (port 3000). Responsibilities:
- Proxy
/api/v1/<service>/*to the right internal service over keep‑alive‑pooled HTTP; re‑serialise JSON, pass binary (PDF/CSV) through verbatim. - Auth — global
JwtAuthGuard(HS256, timing‑safe) with an anchored‑prefix public allowlist (/auth/*,/kyc/webhook,/admin/login,/health*). - Rate‑limit — fixed‑window per IP, by path class (auth ~20/min, AI ~40/min, default ~300/min).
- Hygiene — strip internal headers (
x-axon-service-token,x-axon-admin-user) on ingress, gzip/brotli compression, Helmet, CORS (strict whitelist in prod), Swagger. GET /health,GET /health/services(fans out to every service).
service-auth
SIWE authentication and session management.
| Method · Path | Purpose |
|---|---|
GET /auth/nonce/:walletAddress |
Issue a single‑use nonce to sign |
POST /auth/login |
Verify SIWE signature → access JWT + refresh token; upserts User + personal Profile |
POST /auth/refresh |
Rotate tokens (single‑use; reuse revokes the family) |
Owns: User, Nonce, RefreshToken. Integrations: Privy (provisions embedded wallets, HD index 0 personal / 1 business). Workers: none.
service-kyc
Identity (KYC) and business (KYB) verification via Sumsub.
| Method · Path | Purpose |
|---|---|
POST /kyc/init |
Create a Sumsub applicant; return a WebSDK token |
GET /kyc/status/:walletAddress |
Public KYC status lookup |
GET /kyc/business-status |
Current user's KYB status (re‑fetches Sumsub) |
POST /kyc/business/wallet |
Bind the generated business wallet (requires APPROVED) |
POST /kyc/webhook |
Sumsub webhook (HMAC over raw body) |
Owns: KycVerification, business Profile rows. Integrations: Sumsub. Workers: none.
service-wallet
Read‑only chain reads. No database tables.
| Method · Path | Purpose |
|---|---|
GET /wallet/:address/balances |
USDC + ETH balances |
GET /wallet/:address/usdc |
USDC only |
GET /wallet/network |
Active network (Base Sepolia / Mainnet) |
Integrations: Base RPC (ethers).
service-transactions
Transfers, top‑ups, and history. KYC‑gated.
| Method · Path | Purpose |
|---|---|
POST /transactions/quote |
Preview platform fee + net amount |
POST /transactions/send |
Record a signed USDC transfer (KYC hard‑gate outbound) |
POST /transactions/record-topup |
Record a completed top‑up |
GET /transactions/tx/:txHash |
Lookup by hash |
GET /transactions/:walletAddress |
Paginated history |
Owns: Transaction. Integrations: Base RPC; MoonPay (top‑up webhooks via onramp).
service-agreements
Milestone‑escrow lifecycle and notifications.
| Method · Path | Purpose |
|---|---|
GET /agreements/counterparty?email= |
Does an AXON user exist for this email? |
POST /agreements |
Create draft agreement (KYC‑gated) |
GET /agreements |
List for current profile |
GET /agreements/:id |
One agreement |
POST /agreements/:id/actions/:intent |
Prepare an action (accept/fund/mark‑complete/release/dispute/propose‑/accept‑resolution/cancel) |
POST /agreements/:id/confirm |
Confirm an action — verify txHash on‑chain, mutate state |
POST /agreements/:id/discard |
Off‑chain cancel of an unfunded draft |
GET/POST /notifications… |
Unread count, list, mark read |
POST /agreements/maintenance/backfill-settlements |
Internal: replay escrow events into the ledger (service‑token auth) |
Owns: Agreement, AgreementMilestone, Notification. Integrations: AXONEscrow (create/accept/fund/mark/release/dispute/resolution/cancel), settlements (records ESCROW_FUND/RELEASE). Workers: none in‑service (escrow drift handled by reconciliation).
service-distributions
Batch cash‑out planning and routing.
| Method · Path | Purpose | ||
|---|---|---|---|
GET /distributions/corridors |
Catalogue of countries/vendors/rates | ||
GET /distributions/stats |
90‑day auto‑pick coverage & savings | ||
GET /distributions/quote · POST /distributions/quote/batch |
Ranked vendor quotes (single / many corridors) | ||
POST /distributions |
Create a plan from routes (business‑scoped) | ||
GET /distributions · GET /distributions/:id |
List / detail | ||
GET /distributions/:id/report · …/routes/:routeId/report |
PDF audit reports | ||
| `POST …/routes/:routeId/start | complete | fail` | Drive a route's lifecycle |
DELETE /distributions/:id |
Cancel (only if no route settled) |
Owns: Distribution, DistributionRoute, RoutingDecision, PolicyConfig. Integrations: ramp router (MoonPay/Wise…), settlements (DISTRIBUTED_ROUTE). Workers: none (reconciliation drives stuck routes).
service-settlements
The money‑movement ledger.
| Method · Path | Purpose |
|---|---|
POST /settlements |
Record a settlement (idempotent on source+sourceId) |
GET /settlements · GET /settlements/:id |
List / detail |
GET /settlements/summary |
Totals for the active profile |
GET /settlements/verify |
Recompute hash chain (tamper check) |
GET /settlements/anchors · POST /settlements/anchor |
List / pin head to Base |
PATCH /settlements/:id/status |
Advance a settlement (validated transitions) |
Owns: Settlement (+ hash‑chained ledger rows), LedgerAnchor. Integrations: Base (anchor head hash). Workers: reconciliation (60 s) reconciles open settlements; anchor (30 min) pins the head.
Gotcha: the canonical recording URL is read from
SERVICE_SETTLEMENTS_HOST. If it's wrong, cross‑service settlement recording (and backfills) silently fail.
service-funding (Instant Funding)
Facility‑based instant settlement.
| Method · Path | Purpose |
|---|---|
GET /funding/facility |
Active facility + coverages (business‑scoped) |
GET /funding/fee-quote?amount= |
Preview the fee on a draw |
POST /funding/facility/request |
Request a facility (creates a FUNDING_FACILITY agreement) |
POST /funding/facility/:id/accept |
Accept terms (→ ACCEPTED, awaits admin) |
POST /funding/facility/:id/activate |
Activate after approval |
GET /funding/facility/report?format= |
Coverages audit (CSV/PDF) |
POST /funding/coverage |
Route an inbound transfer through the facility |
POST /funding/internal/* |
Settlement‑status sync, admin activate/decline (service auth) |
Owns: FundingFacility, FundingCoverage (incl. collectionStatus), CollectionLedgerEntry. Integrations: Base (Transfer log watching, transferFrom sweeps), Lydiam (fiat), settlements (INSTANT_FUNDING). Workers: CoverageWatcher (30 s) detects inbound transfers and retries unswept coverages; CollectionSweeper executes the USDC sweep and flips collectionStatus → COLLECTED atomically with the ledger entry.
service-onramp
Fiat on/off‑ramp provider pool.
| Method · Path | Purpose |
|---|---|
POST /onramp/buy-quotes · POST /onramp/buy-session · GET /onramp/buy-status |
Buy (on‑ramp) flow across providers |
POST /onramp/sell-session · GET /onramp/sell-status · POST /onramp/sell-session/:id/... |
Sell (off‑ramp) flow |
POST /onramp/offramp-quotes · POST /onramp/offramp-requirements |
Off‑ramp quotes + dynamic recipient fields |
GET /onramp/assets |
Supported fiat + crypto |
Owns: SellSession, WebhookEvent. Integrations: MoonPay, Onramper, Transak, Crossmint, Wise. Workers: none (MoonPay drives state via webhooks).
service-ai
AI assistant. Provider‑switchable; default OpenAI gpt‑4o (AI_PROVIDER=openai).
| Method · Path | Purpose |
|---|---|
POST /ai/chat |
Chat with wallet context |
POST /ai/summarise-document |
Summarise an agreement attachment |
POST /ai/agreements/draft-contract |
Draft a balanced contract body (Markdown) |
Integrations: OpenAI (Anthropic kept as a switchable fallback).
service-admin
Staff operations plane (session via POST /admin/login → 8 h token, AdminAuthGuard).
| Area | Endpoints | ||
|---|---|---|---|
| Facilities | GET /admin/facilities, `POST …/:id/activate |
decline` | |
| Lydiam simulator | GET /admin/lydiam/payouts, POST …/:id/drive |
||
| Overview / alerts | GET /admin/overview, GET /admin/collection, GET /admin/alerts, POST …/:id/ack |
||
| Policies | GET/PATCH /admin/policies |
||
| Distribution overrides | GET /admin/distributions[/:id], `POST …/routes/:routeId/force-complete |
force-fail | re-route` |
| Reports | `GET /admin/{funding | lydiam | collection}/report?format=` |
Owns: AdminAlert, PolicyConfig, AuditLog. Integrations: funding, distributions, settlements. Workers: none.
service-reconciliation
Background safety net (no user‑facing endpoints beyond health).
- Reconciler (30 s): inspects every
PLANNED/IN_PROGRESSdistribution route, checks vendor status, and advances or fails it; scans escrow events for drift (DB behind/ahead of chain), heals what it can and raisesAdminAlert(RECON_FAILURE/ESCROW_DRIFT) otherwise. - Self‑disables cleanly if escrow isn't configured.
Its health endpoint lives at
/api/v1/health(not/api/v1/reconciliation/health), and it isn't wired into the gateway's/health/servicesaggregator yet — so it may show "unreachable" there even while running. Verify withdocker compose ps service-reconciliation.