# 01 · Product ## Vision 0pt is the most flexible, honest data-services platform for the Nordic + European B2B market. Customers order any kind of data work — from ready-made datasets to bespoke pipelines — and get full visibility into where every value came from and how confident it is. The differentiator is **honest accuracy**: provenance per field, freshness tracking, source transparency. Incumbents (Apollo, Cognism, ZoomInfo) overclaim; 0pt shows its work. ## The three flows (everything reduces to these) Every service maps to one of three intake/delivery flows (`Flow` in `lib/services.ts`: `catalog` | `custom` | `subscription`). *Correction: this section previously said "nine categories (scraping, structuring, datasets, ICP/leads, BI, ML, documents, subscriptions, custom)" — that list doesn't match `lib/services.ts`'s actual catalog and never did (no `structuring`, `datasets`, `subscriptions`, or `custom` service id exists there). The real catalog today (`lib/services.ts`, `SERVICES`) has 11 entries: data delivery, web scraping, mapping & matching, normalization, consolidation → CRM/ERP, documents & OCR, enrichment, ICP & leads, ML jobs, BI & market analysis, feeds & monitoring.* These are **tags/filters within the three flows**, not separate machinery — each entry carries a `flow` field pointing back to `catalog` / `custom` / `subscription`. 1. **Catalog product** — ready-made, browse → sample → buy → deliver. Exists in Postgres or produced fast from the pipeline. Margin + scale. 2. **Custom job** — does not exist yet; must be scoped. `configure (AI-assist) → estimate → manual scope/quote confirm → produce → QA → validate → deliver`. The hero flow. Consulting in a portal. 3. **Subscription / feed** — recurring product or job: lead feeds, freshness monitoring, ongoing enrichment. `configure → recurring payment → recurring delivery/webhook`. ## Order lifecycle (state machine) ``` DRAFT → QUOTED → DEPOSIT_PENDING → IN_PRODUCTION → REVIEW → (REVISION → IN_PRODUCTION)* → ACCEPTED → DELIVERED → [SUBSCRIPTION_ACTIVE] ``` - **DRAFT**: configurator in progress. - **QUOTED**: estimate produced (catalog = instant; custom = after scope confirm). - **DEPOSIT_PENDING**: awaiting 50 % deposit. - **IN_PRODUCTION**: deposit captured → workers run. Customer watches live. - **REVIEW**: QA passed threshold → customer validates (table/map/schema/quality). - **REVISION**: customer requested changes → escrow untouched → back to production. - **ACCEPTED**: customer approves → remaining 50 % released from escrow. - **DELIVERED**: exports + destinations unlocked; provenance log + quality report attached. - **SUBSCRIPTION_ACTIVE**: if converted to a feed. This is real, working code today, not just a spec: `app/api/orders/[id]/route.ts`'s `PATCH` handler enforces exactly this sequence (lowercase: `draft`, `quoted`, `deposit_pending`, `in_production`, `review`, `revision`, `accepted`, `delivered`) as its allowed-status list. One gap: `SUBSCRIPTION_ACTIVE` is **not** in that allowed list yet — feed conversion (Phase 7, `docs/09-build-plan.md`) isn't wired into the order status machine. ## Business / escrow model - **50 / 50.** Deposit (50 %) captured to start production. Balance (50 %) **held** and only captured/released on **ACCEPTED**. Revision never moves the held amount. - Pricing models: pay-per-job, volume, subscription (monthly), custom quote. - Estimate is a function of: selected field weights × markets × volume × entity multiplier × confidence-target multiplier + enrichment. Custom jobs get a manual scope/quote gate before DEPOSIT_PENDING. - Stripe: deposit = capture now (`app/api/payments/[order_id]/deposit/route.ts`); balance = **a second Stripe Checkout session created on accept**, keyed to the order (`app/api/payments/[order_id]/release/route.ts`). *Correction: earlier drafts of this doc left the balance mechanism open ("either a held authorization … or a second invoice"). The second-Checkout-session approach is what's actually implemented — there is no held-PaymentIntent-capture path in the code.* Both routes are env-guarded on `STRIPE_SECRET_KEY` and return `501` until it's configured (`lib/stripe.ts`). ## Customer DB access (designed, not a checkbox) Default: the customer **pushes** data (upload/export) — we rarely need to read their DB. If we must: a **read-only, table-scoped, time-boxed** role the customer creates, IP-allowlisted, ideally against a replica. Creds encrypted, deleted after the job. Everything logged. This is a selling point to compliance-heavy buyers, and it requires a DPA. ## Personas (brief — for copy + prioritization) SaaS-Martin (RevOps, wants clean ICP/leads), Bilhandlar-Bengt (vehicle + company data via VehIQ), Rekryterar-Rebecka (people/firmographics), Investor-Ivar (diligence, sanctions/UBO, scrutinizes compliance), Ekonomi-Erik (financials, scrutinizes compliance), Data-David (raw datasets + API). Ivar and Erik are *why* honest sourcing + DPA must be airtight. ## First-launch scope (de-risked) Do **not** ship "20 markets × 11 categories." Ship the thinnest sellable slice: **Nordic company data** (the open stuff — GLEIF + Brreg + verified sources) + **vehicle data** (VehIQ synergy) as a couple of catalog datasets, **plus the custom-job intake**, Stripe, and delivery to download + into FiveCRM/Data Loader. First customers are Protosell internally + existing dealer relationships — services you already deliver, productized. Then expand markets as the sourcing map fills in.