Skip to content

API Reference

Two HTTP APIs, both NestJS (Fastify), both under the global prefix /v1, both with interactive Swagger UI at /docs.

API Base URL Auth Source
Customer API https://api.aimgold.org/v1 Bearer JWT (user); some routes public aim-digigold-real/apps/api
Admin API https://admin-api.aimgold.org/v1 Bearer JWT (admin) + role aim-digigold-real/apps/admin-api

The parked Go backend (aim-gold-backend) exposes a separate /api/v1 surface documented in its own OpenAPI spec (GET /openapi.yaml) — it is not deployed and not covered here.

Conventions

  • Auth: a global JwtAuthGuard protects every route unless marked @Public() (libs/common/src/guards/jwt-auth.guard.ts). Send Authorization: Bearer <accessToken>. Payload is {sub, phone, deviceId}; the admin API additionally runs RolesGuard and per-route @Roles(...).
  • Admin roles: SUPER_ADMIN > ADMIN > SUPPORT. A route lists the roles allowed.
  • Pagination: list endpoints take ?page (default 1) and ?limit (default 20, max 100) and return {items, total, page, limit} (libs/common/src/dto/pagination.dto.ts).
  • Webhooks are @Public() but verify an HMAC signature over the raw request body (captured via Fastify rawBody); a bad signature is 401.
  • Rate limiting: the customer API enforces 100 requests / 60 s per client IP globally (ThrottlerGuard); exceeding it returns 429. Provider webhooks, /health, and /metrics are exempt (@SkipThrottle) so callbacks and scrapes are never dropped. The client IP is resolved via one trusted proxy hop (Caddy), so it can't be spoofed with X-Forwarded-For.
  • 501 Not Implemented marks endpoints that exist as contracts but are not built yet — they are called out below.

Customer API (api.aimgold.org/v1)

Auth (modules/auth)

Method Path Auth Summary
POST /auth/send-otp public Send login OTP. Body {phone}{sent, expiresInSec:600}.
POST /auth/verify-otp public Verify OTP; creates user on first login. Body {phone, otp, deviceId?, deviceName?}{accessToken, refreshToken, user, isNewUser, mpinSet}. 401 invalid/deleted/blocked.
POST /auth/set-mpin JWT Set/replace MPIN. Body {mpin(4-6)}{updated:true}.
POST /auth/login-mpin public Phone+MPIN login. 429 after 5 fails in 15 min (30-min lockout).
POST /auth/forgot-mpin public Send MPIN-reset OTP (uniform response, anti-enumeration).
POST /auth/reset-mpin public Reset MPIN with OTP. Body {phone, otp, newMpin}.
POST /auth/biometric-token JWT Issue device-bound biometric token. 400 if no active session for the device.
POST /auth/login-biometric public Login with a biometric token. Body {phone, deviceId, biometricToken}.
POST /auth/refresh public Rotate refresh token (old one revoked). Body {refreshToken}.
POST /auth/logout JWT Revoke the session for a refresh token. 204.
GET /auth/sessions JWT List active sessions.
DELETE /auth/sessions/:id JWT Revoke one session + its biometric token.

Users (modules/users)

Method Path Auth Summary
GET /users/me JWT Caller profile (credential hashes stripped).
PATCH /users/me JWT Update {full_name?, email?}.
POST /users/me/fcm-tokens JWT Register an FCM push token.
DELETE /users/me/fcm-tokens/:token JWT Remove an FCM token.
POST /users/me/deletion/request JWT Send deletion OTP to own phone. 429 if >3 per 15 min.
POST /users/me/deletion/confirm JWT Confirm deletion: {otp, confirmation:"DELETE"} → purges sessions/notifications, anonymizes PII, tombstones user. 409 if active orders/payouts/SIP.
GET /users/me/deletion/status JWT {status:'none'} or {status:'deleted', deletedAt}.

Gold orders & SIP (modules/orders)

Method Path Auth Summary
POST /gold/buy JWT Create a buy: SafeGold verify + Razorpay order; allocation on payment webhook. Body {unit:'INR'\|'GRAMS', amount, idempotency_key}{order, payment, sg_tx_id, expires_at}. 409 duplicate.
POST /gold/sell JWT Sell gold: balance-locked SafeGold confirm, TDS, holding debit, payout queued. Body {unit, amount, bank_account_id, idempotency_key}. 400 insufficient balance.
POST /gold/sip JWT Create a SIP plan. Body {amount_inr>=10, frequency, duration_installments(1-240), start_date?, idempotency_key}.
GET /gold/sip JWT List caller's SIP plans.
GET /gold/sip/:id JWT Get one SIP plan.
POST /gold/sip/:id/cancel JWT Cancel a SIP plan.
GET /gold/sip/:id/installments JWT List a plan's installment orders.
GET /gold/orders JWT List gold orders (?status, ?type filters).
GET /gold/orders/:id JWT Get one gold order.

Portfolio (modules/portfolio)

Method Path Auth Summary
GET /portfolio JWT Summary at live sell price (30 s cache): balance, invested, current value, P&L.
GET /portfolio/history JWT Paginated gold-order history.
GET /portfolio/passbook JWT 501 — not implemented.
GET /portfolio/statement JWT 501 — not implemented.

Price (modules/price)

Method Path Auth Summary
GET /price/current public Live SafeGold buy/sell/spot price. Upstream failure → 5xx.
GET /price/history public Snapshots for ?range=1d\|1w\|1m\|1y (max 5000 rows).

There is also a socket.io gateway on namespace /price (no auth) that broadcasts price_update every 10 s — not an HTTP endpoint, and unused by the shipped clients.

Products & product orders (modules/products, modules/product-orders)

Method Path Auth Summary
GET /products public Active catalogue (?q, ?category).
GET /products/:id public One product.
GET /products/:id/image public Image proxy from MinIO (1-day cache).
POST /product-orders JWT Place a COD order. Body {items:[{productId, quantity}], shippingAddress, idempotencyKey?}; prices recomputed server-side. 400 product unavailable.
GET /product-orders JWT List caller's product orders.
GET /product-orders/:id JWT One product order.

KYC (modules/kyc)

Method Path Auth Summary
POST /kyc/submit JWT Submit PAN/Aadhaar + doc key; PII encrypted at rest.
POST /kyc/aadhaar-otp JWT 501 — not implemented.
POST /kyc/aadhaar-otp/verify JWT 501 — not implemented.
GET /kyc/status JWT Status with masked last4.
POST /webhooks/kyc HMAC x-signature KYC provider webhook (event parsing is still a TODO).

Payouts & bank accounts (modules/payouts)

Method Path Auth Summary
GET /payouts JWT List caller's payouts.
GET /payouts/:id JWT One payout.
POST /webhooks/payout HMAC x-razorpay-signature RazorpayX payout + fund-account-validation events.
GET /bank-accounts JWT List (masked last4).
POST /bank-accounts JWT Add (encrypted); fires penny-drop validation.
PATCH /bank-accounts/:id/primary JWT Set primary.
DELETE /bank-accounts/:id JWT Delete.
PATCH /bank-accounts/:id/verify JWT Re-trigger penny-drop (scoped to the caller's own account).

Payments webhook (modules/payments)

Method Path Auth Summary
POST /webhooks/payment HMAC x-razorpay-signature payment.captured/order.paid → mark order paid (triggers SafeGold allocation); payment.failed → mark failed.

Transactions, notifications, referrals

Method Path Auth Summary
GET /transactions JWT Unified feed (gold + product orders + payouts, merged in memory).
GET /notifications JWT Paginated notifications.
PATCH /notifications/:id/read JWT Mark one read.
GET/POST /notifications/preferences JWT 501 — not implemented.
GET /referrals/me JWT Caller's referral code.
POST /referrals/apply JWT Apply a code once.
GET /referrals/rewards JWT Referrals where caller is referrer.

Ops

Method Path Auth Summary
GET /health public Liveness.
GET /metrics internal only (Caddy returns 404 publicly; scraped container-to-container on aim_edge) Prometheus metrics.

Admin API (admin-api.aimgold.org/v1)

Every route below is JWT + role-guarded unless noted. Seed the first admin with npm run seed:admin (writes admin_users with a bcrypt password).

Auth & ops

Method Path Roles Summary
POST /auth/login public Email/password → admin JWT.
POST /auth/logout any admin Stateless no-op (client discards token).
GET /health public Liveness.
GET /metrics public (internal) Prometheus metrics.

DevOps / Build Tools (modules/devops)

Method Path Roles Summary
GET /devops/runs SUPER_ADMIN, ADMIN Recent GitHub Actions runs per target (?target=backend\|website\|admin-portal\|monitoring, ?per_page). 503 if GITHUB_PAT unset.
POST /devops/deploy SUPER_ADMIN Trigger workflow_dispatch on main for a target. Body {target}. 429 if fired < 60 s ago (Redis lock). Audited devops.deploy.trigger.

Dashboard, users, KYC

Method Path Roles Summary
GET /dashboard/overview all Headline KPIs.
GET /dashboard/gmv all Daily GMV series (?days).
GET /dashboard/user-growth all Daily signups.
GET /users all List/search customers.
GET /users/:id all One user + holding/kyc/banks.
PATCH /users/:id/block SUPER_ADMIN, ADMIN Block/unblock.
PATCH /users/:id/force-kyc-reverify SUPER_ADMIN, ADMIN Force KYC back to PENDING.
GET /kyc all Review queue (default SUBMITTED).
GET /kyc/:id all One KYC record.
POST /kyc/:id/approve SUPER_ADMIN, ADMIN Approve; registers user with SafeGold on first approval.
POST /kyc/:id/reject SUPER_ADMIN, ADMIN Reject with reason.
POST /kyc/:id/request-resubmit SUPER_ADMIN, ADMIN Send back to PENDING.

Orders, payouts, products

Method Path Roles Summary
GET /orders / /orders/:id all List/get gold orders.
POST /orders/:id/reconcile SUPER_ADMIN, ADMIN 501 stub (audits first).
POST /orders/:id/refund SUPER_ADMIN, ADMIN 501 stub (Razorpay refund pending).
GET /payouts all List (default PENDING+PROCESSING).
POST /payouts/:id/approve SUPER_ADMIN, ADMIN Dispatch IMPS payout via RazorpayX. ADMIN capped at ₹100,000.
POST /payouts/:id/retry SUPER_ADMIN, ADMIN Reset FAILED→PENDING and re-approve as the retrying admin's role (an ADMIN retry is still subject to the ₹1L cap).
GET /product-orders all List physical orders.
PATCH /product-orders/:id/status SUPER_ADMIN, ADMIN Set status (no audit log written).
GET /products / /products/:id all List/get.
POST /products SUPER_ADMIN, ADMIN Create.
PATCH /products/:id SUPER_ADMIN, ADMIN Update.
POST /products/:id/image SUPER_ADMIN, ADMIN Upload image (raw base64).
DELETE /products/:id SUPER_ADMIN, ADMIN Soft delete (is_active=false).

Price, config, reports, audit

Method Path Roles Summary
GET /price/config SUPER_ADMIN, ADMIN Read spread config (Redis).
POST /price/config SUPER_ADMIN Set spread config.
POST /price/override SUPER_ADMIN Partial stub: saves a MANUAL price row then 501 (cache push + broadcast pending).
GET /price/live all SafeGold live price passthrough.
GET /config/feature-flags SUPER_ADMIN, ADMIN Read flags (Redis).
PUT /config/feature-flags SUPER_ADMIN Upsert a flag.
GET /config/limits SUPER_ADMIN, ADMIN Read limits.
PUT /config/limits SUPER_ADMIN Replace limits.
GET /config/banners SUPER_ADMIN, ADMIN Read CMS banners.
PUT /config/banners/:id SUPER_ADMIN, ADMIN Upsert a banner.
GET /reports/aum all AUM snapshot from gold_holdings.
GET /reports/daily-transactions SUPER_ADMIN, ADMIN Stub.
GET /reports/gst SUPER_ADMIN, ADMIN Stub.
GET /reports/tds SUPER_ADMIN, ADMIN Stub.
GET /reports/safegold-reconciliation SUPER_ADMIN, ADMIN Stub.
GET /transactions all Unified admin-wide feed.
GET /audit SUPER_ADMIN, ADMIN Audit log, newest first, with filters.