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_PROGRESS distribution route, checks vendor status, and advances or fails it; scans escrow events for drift (DB behind/ahead of chain), heals what it can and raises AdminAlert (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/services aggregator yet — so it may show "unreachable" there even while running. Verify with docker compose ps service-reconciliation.

results matching ""

    No results matching ""