Skip to main content
You use UQP draft v0.1 (0.1-draft) to collect service requirements, calculate a non-binding estimate and request a reviewed, binding quote. This is reference, not production. The core schemas use JSON Schema draft 2020-12.

Follow the objects

  1. Publish a QuoteManifest with enabled questions, a PricingModel reference, review mode, currencies and validity settings.
  2. Use a QuestionCatalog for intake and a FactorCatalog for pricing switches. InferenceRules map answers to configured outputs; they do not authorize you to invent missing customer facts.
  3. Submit a QuoteRequest with raw answers and explicit studio consent for the selected pack and version.
  4. Return a non-binding Estimate. Both pre_price and post_price modes require a price range, sessions and deposit; explain provisional values in assumptions.
  5. Follow the Lifecycle through provider review before issuing a binding Quote with valid_until. Obtain explicit client approval before checkout handoff.
Use Discovery to advertise reference definitions, supported packs and optional routing hints. Common definitions supply shared types. REST OpenAPI, MCP OpenRPC and GraphQL bindings exchange these same objects; they do not create another lifecycle.

Browse the schemas

These versioned JSON downloads are the published schema files. Source schemas and unversioned aliases use https://uqp.dev/spec/schemas/ identifiers. The publication script rewrites each versioned download’s $id to https://uqp.dev/spec/v0.1/schemas/<file>.json. Register the selected schemas locally by $id; you do not need runtime schema fetching.

Validate beyond the schema

Validate that min <= max, pack versions agree across documents, and questions and factors belong to the selected pack. JSON Schema does not execute pricing formulas, resolve model references or enforce the lifecycle’s transitions annotation. Use spec/lifecycle.ts to check allowed edges. An incomplete intake requires mutation, not an Estimate with a missing or fabricated zero price. Preserve raw answers such as size: "unsure". Keep contact details outside answers. Known contact keys are rejected, but schema validation cannot detect all personal information in free text. Requested anonymization is not proof of deidentification; the tattoo evaluator leaves anonymized false. Every Estimate and Quote requires a price_range with min, max, currency and provenance (who stated the price and when). A logged_quotes method requires at least five observations, enforced by the schema. Pending review does not permit an absent price; use confidence and assumptions to explain uncertainty. Record explicit share_for_pricing_research and anonymize boolean preferences and an RFC 3339 captured_at timestamp in the request’s consent object, separate from raw answers. These required fields record choices, not a requirement to opt in. Research-sharing preferences are not approval to pay a deposit, and an anonymization request does not prove deidentification.

Pin versions and respect the payment boundary

Pin a repository revision and pack version, and revalidate before updating. The core is 0.1-draft; the tattoo pack is 0.1.0. Pack and core versions are separate. No stable compatibility or transport negotiation contract is published. The example seven-day expiry is a configurable business choice, not a protocol default. The provider remains merchant of record. UQP never holds funds, and only trusted processor confirmation can establish payment; client self-report cannot. Processor confirmation is not another quoting lifecycle state. See checkout handoff, discovery and the changelog.