Store Architecture Guide
Audience: Engineers and architects designing a Dr Green-backed storefront. This document explains the complete moving parts so you can decide where each piece of your store lives.
The big picture
Components and ownership
Owned by you (the store builder)
- Store UI — the storefront the customer sees. Web, mobile, both. Yours.
- Store backend — your service that calls Dr Green’s API on behalf of the customer. Keeps your own customer DB, cart/order state, polling jobs.
- Customer DB — typically you mirror Dr Green’s
clients/ordersrecords to your own DB so you can render fast (don’t hit Dr Green for every page load). Keep it lean: store IDs, status, last-known shape; don’t duplicate PII unless you have a clear retention reason. - Polling infrastructure — background jobs that periodically check order/KYC status and notify customers of changes.
Owned by Dr Green
- API backend (
api.drgreennft.com) — NestJS, Postgres, behind Envoy proxy - Auth — both the DAPP UI’s JWT auth flow and your API-key signature flow
- Catalogue & inventory — the strain catalogue, country-availability, pricing
- Order fulfilment — admin approval, payment processor integration, dispatch
- KYC integration — the FirstAML relationship and case management
- Smart-contract integration — NFT ownership, on-chain commission settlements
- Email — transactional emails to customers (KYC, order updates)
Owned by third parties
- FirstAML — KYC/AML verification (customer interacts directly with their portal)
- CoinRemitter — crypto payment gateway
- Payinn / PGPay — fiat payment gateways
- Sumsub ❌ — not used. (Older versions of these docs incorrectly listed Sumsub as the KYC provider; that was based on a mis-read of the codebase. The provider is FirstAML.)
Data flows in detail
Read flow (browsing the catalogue)
(countryCode, page, limit) cache key. Cache strain detail for 10 minutes per strainId. Drop on 404.
Write flow (customer onboarding)
Order lifecycle flow
See order-lifecycle.md for the detailed version.Where to put which logic
Auth boundaries
- No auth — public endpoints (
/auth/nonce,/public/healthStatus, customer-facing KYC/payment redirects) - JWT — used by the DAPP UI when the holder is logged in. Generated via wallet sign-in. Required for
/keys/*,/user/me,/dapp/users/nfts. Store builders do not have a JWT — they have the API key pair the holder generated using their JWT. - API-key + signature — used by stores. Long-lived (no expiry, no refresh), per-NFT scope, signed per-request with ECDSA secp256k1.
DualAuthGuard on /dapp/* routes accepts either JWT or API-key+signature — meaning the same endpoints serve the DAPP UI and external stores.
Scoping: per-NFT, per-key
Every API key pair is scoped to one primary NFT. If a holder owns multiple NFTs and runs separate businesses for each:- Generate one key pair per NFT
- Treat them as separate stores in your code (or as separate accounts in your multi-tenant setup)
- Don’t try to “swap NFTs” mid-session — switching primary NFT is a DAPP-UI-only operation, and doing it from your store would corrupt your in-flight state
nft.tokenId from any authenticated response tells you which NFT the current key is scoped to. Cache it on first call; verify on startup if you’ve encoded NFT-specific config.
Network topology
Production
- API base:
https://api.drgreennft.com/api/v1 - TLS enforced
- Reverse proxy: Envoy (production deployment)
- The OpenAPI spec is publicly accessible at
/api-json
Staging
- API base:
https://stage-api.drgreennft.com/api/v1 - ⚠️ Currently HTTP 503 (Envoy upstream connect error) — has been since at least 8 May 2026. If you need staging access, contact Dr Green.
Your topology (recommendations)
- Outbound from your backend → Dr Green: stable IPs are not currently required by Dr Green, but expect this to change. If your hosting rotates IPs, talk to Dr Green about IP allow-listing if/when they enforce it.
- No customer-browser → Dr Green calls. Your backend is the proxy. CORS-allowed origins are limited; call from server-side only.
- Outbound to FirstAML, payment processors: none. You do not call these directly. All third-party integrations are Dr Green’s domain.
Operational concerns
Rate limits
Not enforced as of 10 May 2026, but engineer politely:- ≤ 1 req/sec per holder for background polling
- Cache the catalogue aggressively (5–60 min TTLs)
- Use
/dapp/orders/recentas a heartbeat across all customers rather than polling each one
Failure modes you must handle
Observability
For every Dr Green API call, log:- HTTP method, path, status code
- Response time
- Your generated correlation ID (for cross-service tracing)
- Truncated
x-auth-apikey(first 16 chars) for key-rotation diagnostics
- Full
secretKeyever - Customer KYC fields (DOB, ID numbers, medical record content)
- Full
x-auth-signatureheaders (verbose; useful only for very specific debugging)
Multi-tenant store builders
If you operate stores for multiple holders (e.g. you sell a SaaS that wraps Dr Green):- Store each holder’s
(apiKey, secretKey)pair encrypted-at-rest, indexed by your tenant ID - Cache the resolved
nft.tokenIdper tenant for routing/scoping - Use a separate DAPP-Green API client instance per tenant (don’t share the long-lived signing key across requests)
- Implement bulk operations carefully — a 1000-tenant batch poll without jitter will create thundering herds
Anti-patterns to avoid
Where to next
- KYC flow — the full FirstAML integration deep-dive
- Order lifecycle — every status transition explained
- Reference index — endpoint-by-endpoint detail