API (api-v2)
Integrations & environment
Every third-party service is optional in development and degrades predictably. Mailgun is the exception: production refuses to boot without it. All configuration goes through src/config/env.ts.
Third-party services
| Service | Purpose | Env vars | If missing |
|---|---|---|---|
| PostgreSQL (Stackhero in prod) | Primary database | DATABASE_URL, TEST_DATABASE_URL, DBMATE_* | Required |
| Mailgun (EU region) | OTP emails | MAILGUN_API_KEY, MAILGUN_DOMAIN, MAILGUN_BASE_URL, MAIL_FROM | Production exits. Dev logs the codes. |
| Redis (Redis Cloud in prod) | Read-through cache | REDIS_URL (REDISCLOUD_URL also on prod), CACHE_PREFIX | No cache; every read goes to Postgres |
| RabbitMQ / CloudAMQP | Ledger postings, search reindex | RABBITMQ_URL, CLOUDAMQP_URL, RABBITMQ_EXCHANGE, WEB_CONSUMES_QUEUE | Events dispatched in-process |
| Algolia | Search rollback backend | ALGOLIA_APP_ID, ALGOLIA_API_KEY, ALGOLIA_INDEX_PREFIX, SEARCH_BACKEND | No-op |
| Cloudinary | Product and section media; catalogue XLSX as raw uploads | CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET, MEDIA_MAX_IMAGE_BYTES, MEDIA_MAX_VIDEO_BYTES | Uploads return 503 |
| Google Maps (Places, Geocoding, Time Zone) | Address lookup | GOOGLE_MAPS_API_KEY, PLACES_BIAS_CENTER, PLACES_BIAS_RADIUS_M | Empty results |
| Apple App Store | In-app purchase verification | APPLE_BUNDLE_ID, APPLE_ROOT_CA_PEM, APPLE_ENVIRONMENT | 503 |
| Google Play | In-app purchase verification | GOOGLE_PLAY_PACKAGE_NAME, GOOGLE_PLAY_SERVICE_ACCOUNT_JSON, GOOGLE_PLAY_ENVIRONMENT | 503 |
| BetterStack (Logtail) | Request logs: never bodies, auth headers or cookies | BETTERSTACK_SOURCE_TOKEN, BETTERSTACK_INGEST_URL | stdout |
| open.er-api.com (in progress) | Daily FX rates | FX_SYNC_URL, FX_SYNC_TIMEOUT_MS | Default feed |
| GitHub Packages | Contract packages | NPM_TOKEN | npm install fails |
Core settings
| Variable | Notes |
|---|---|
JWT_SECRET | ≥ 32 characters. Also the key discount PIN HMACs are derived from, so rotating it invalidates every PIN. |
ACCESS_TOKEN_TTL, REFRESH_TOKEN_TTL_DAYS | Defaults: 15 minutes and 30 days |
COOKIE_SECURE | Cookie flag |
CORS_ORIGINS | Allowed origins. Locally, the apps run on 5173 / 5273. |
OPS_TOKEN | Mounts /internal/ops/* |
INTERNAL_SECRET_KEY | Mounts /internal/* |
PORT, NODE_ENV | NODE_ENV ∈ development, test, production |
Front-end variables
| App | Variable | Notes |
|---|---|---|
| Dashboard | VITE_API_BASE_URL | Empty means same-origin (expected in production) |
| Dashboard | VITE_API_PROXY_TARGET | Dev proxy target, default http://localhost:3000 |
| Dashboard | VITE_POS_URL, VITE_ACCOUNTING_URL | Launch targets; defaults https://pos.totlob.com, https://accounting.totlob.com |
| Dashboard | VITE_MAP_STYLE_URL | Defaults to OpenFreeMap (keyless) |
| Dashboard | VITE_ASSISTANT_ENABLED | Exactly true enables the assistant panel |
| POS | VITE_API_BASE_URL | Baked into the bundle |
| POS | VITE_API_PROXY_TARGET | Dev proxy, default http://localhost:3000 |
| Both | NPM_TOKEN | Install-time only |
Not integrated
- Live courier labels and rates (Wakilni). Deferred.
- Stripe
- Push, websocket or email notifications
- An online card gateway, for both the storefront and the POS card terminal