Tax & compliance
Age Verification (Alcohol/Tobacco)
Indicative price, not an offer: €34/mo; credential: age-verification API integration, audit trail
Generated from docs/plan/paid/age-verification/PLAN.md in the AstroBaaS repository. Nothing described below is implemented — it is the written plan for it.
A paid service for merchants selling age-restricted goods (alcohol, tobacco, cannabis). Integrates with third-party age-verification APIs, blocks checkout for unverified customers, maintains audit trail for regulatory inspection, and supports multiple verification methods (ID scan, age-gate question).
The problem
A German online alcohol merchant has no age verification system. She sells beer to anyone. When revenue crossed €100k, a regulator sent a fine (€5k) for selling to minors 7 times in a year. She now needs a documented age-verification system that creates audit trails for inspection.
What it does
- Age-gate question: require customer to confirm they are ≥21/18 (configurable per product)
- ID verification integration: Verify, IDology, or AgeGate API (merchant chooses provider)
- Checkout block: if product is age-restricted and customer unverified, block purchase
- Customer age verification status: track which customers have verified age, when, which method
- Audit log: all verification attempts (passed/failed), timestamp, method, customer
- Regulatory report: exportable list of verified customers (for inspection), includes timestamp
- Retry logic: if verification fails, customer can retry (e.g., image of ID is blurry)
- Multi-product support: different age limits per product (e.g., beer 18+, spirits 21+)
- Admin override: staff can mark customer as verified manually (e.g., in-store verified)
What it deliberately does NOT do
Each boundary carries its reason. A boundary without a reason gets crossed by the next person who reads this.
- ID document scanning or OCR (integration with third-party, not built here)—partner API handles
- Age calculation or birthday field—just verify via third-party
- Biometric age estimation—not supported, too unreliable
- Shipping validation (ensuring adult signs for delivery)—logistics partner handles
- Recall handling (if customer verified as age but turns out to be minor)—manual process, support ticket
Data model
Extend Customer: age_verified, age_verified_at, age_verification_method. Extend Product: age_minimum_years. New: AgeVerification(id, customerId, productId, status, method, verification_data_json, verified_at). Schema migration required.
API
- POST /customers/:id/verify-age — submit age verification (via gate or ID scan)
- GET /customers/:id/age-status — return age verification status
- POST /products/:id/set-age-minimum — set minimum age for product
- GET /checkout/age-required — return list of age-restricted items in cart
- GET /age-verification/audit — list all verifications (for regulatory report)
- POST /age-verification/report — export list of verified customers (CSV)
Every route added here must also appear in src/pages/openapi.json.ts — a test
fails the build if it does not.
Admin
Age verification dashboard: customer list with age-verification status, verification history (timestamp, method, result), product list with age minimums, audit log (all verification attempts), regulatory report generator (export verified customers for inspection)
The seam — why this is paid
Core owns: age verification fields, checkout block, audit trail. Paid pack owns: third-party API integration (Verify, IDology, etc.), compliance documentation, regulatory reporting format.
Credential: age-verification vendor (Verify, Intellicheck), compliance documentation
Dependencies
- customer schema (age_verified, age_verified_at fields)
- product schema (age_minimum_years field)
- checkout flow (must block if age verification failed)
Acceptance checks
Each of these must be able to fail. Before claiming this is done, break the code deliberately and watch each one go red.
- A customer adds an age-restricted beer to cart; checkout requires age verification
- Clicking ‘I am 21+’ question and confirming marks customer age_verified=true
- ID scan verification via Verify API returns status ‘verified’; customer is marked age_verified=true
- If ID scan fails, customer can retry immediately (no cooldown)
- Admin can mark a customer age_verified=true manually (override)
- Audit log shows: customer 123 verified on 2025-09-02 via ‘age_gate_question’, passed
- Regulatory report for Sept 2025 shows all verified customers (100 rows), CSV format, columns: customer_id, verification_date, method
- A product with age_minimum_years=21 blocks checkout for customers with age_verified=false; customers with age_verified=true proceed
Risks
Age verification provider API fails/times out during checkout—must have fallback (manual verification, or allow checkout with flag). Third-party stores customer ID data (privacy risk)—must clarify data handling. False positives: customer fails verification, but is actually adult (e.g., bad lighting on ID scan)—must allow retry/override. Regulatory audit: if we delete audit logs prematurely, merchant faces fines for non-compliance.
Commercial context
| Suggested price | €34/mo; credential: age-verification API integration, audit trail |
| Rival anchor | Age Gate: €30-50/mo; Verify: €100-500/mo; custom: €2000+ |
The anchor is what the nearest equivalent charges on Shopify or Magento today. It is context for a pricing decision, not the decision.
Generated from the commerce plan. See docs/COMMERCE-PLAN.md for the full
catalogue and ../../AI-GUIDE.md for how to work on this repository.