Document types
The reference implementation ships nine document types. This canon is deliberately frozen: the type identifiers (doc_type) are shared vocabulary between your blueprint, schemas, templates, data transformations, and the QA harness. You change labels, content, and styling freely — you do not rename or re-spell the types. (The one exception is the regulatory certificate slot, supporting_document_example, which is renamed to the relevant scheme when you adopt it — see below.)
doc_type | Label | Generated by | Channel gating |
|---|---|---|---|
option | Proposal | User action (create_quote, create_option, create_no_price_quote, create_agent_proposal) | Agent variant trade-only |
booking_confirmation | Booking Confirmation | Automatic, on booking_confirmed trigger | None |
invoice | Invoice | User action (create_invoice) | None — every channel |
cancel_invoice | Cancellation Invoice | User action (create_cancel_invoice, shipped disabled) | None |
commission_invoice | Commission Invoice | User action (create_commission_invoice) | Trade channels only |
commission_statement | Commission Statement | User action (create_commission_statement) | Trade channels only |
financial_summary | Financial Summary | Automatic, on payment_received trigger | None |
final_travel_docs | Travel Documents | User action (create_final_docs) | None |
supporting_document_example | Certificate | User action (shipped disabled — regulatory slot) | None |
All nine, as rendered from the reference baseline:









The proposal family: option
The core guest document. Its doc_type is option but it is labelled "Proposal" everywhere a user or guest sees it (doc_type_label: Proposal). One schema and one template flex across escorted touring, tailor-made (FIT), cruising, and hybrid programmes — the differences are expressed in data, not in forked document types.
The baseline proves this flexibility with five sample datasets, all validating against the same option-1.0 schema and all rendering through the same template:
| Variant | Vertical | Itinerary mode | Distinctive data |
|---|---|---|---|
| Touring | Fixed-departure escorted tour | days | Day-by-day itinerary, accommodations, inclusions |
| FIT | Anyday tailor-made journey | services | Service entries, flights, journey overview |
| Cruising | Fixed cruise sailing | days | Port-call days, GTY and assigned staterooms, typed price lines |
| Hybrid (domestic) | Rail-spine programme | days | Package pricing rows plus add-on price lines, three installments |
| Hybrid (trade) | Same programme via a trade channel | days | Trade channel metadata, agent context, price lines |
Four shipped actions generate it, each with different section visibility and enable conditions:
create_quote— the default proposal. Enabled for Quote-record-type itineraries that are not in Option status.create_option— proposal with an option-hold banner ("Held for you until ..."). Enabled only when the itinerary is in Option status; the expiry date is pre-filled from the option hold end date. The in-page payment button is hidden while inventory is on hold.create_no_price_quote— a proposal that shows no monetary amounts anywhere. Hides the pricing panel, the payment buttons, travel protection, and payment terms (the latter two are hidden because their copy carries amounts — "From £x per person", "A deposit of £x"). This rule is proven in production with a live touring tenant.create_agent_proposal— the trade variant. Only offered on Travel Agent channels. Switches on the line-level price breakdown and a trade-partner banner, both hidden by default.
Action-driven vs auto-generated
Most documents are created deliberately by a user running an action from the itinerary. Two types are instead produced by platform triggers, configured under auto_generated_documents in the blueprint:
| Trigger | Document | Behaviour |
|---|---|---|
booking_confirmed | booking_confirmation | Generated and emailed to the primary contact immediately when the booking confirms |
payment_received | financial_summary | Regenerated whenever a payment lands, so the guest's statement stays current |
Everything else — proposals, invoices, the commission family, travel documents, certificates — is action-driven, gated by the enable conditions described below and configured in the blueprint.
booking_confirmation
Generated automatically when a booking is confirmed (the booking_confirmed trigger) and sent immediately to the primary contact. It is its own contract — confirmation-first: booking reference, status, what happens next, financial position, how to pay — not a proposal with sections removed. See Document data reference.
invoice
The universal guest billing document: line items, credits, discounts, totals, payment schedule. Offered for Booking-record-type itineraries on every channel — direct and trade alike. This is a deliberate design decision: invoices are never channel-gated. Only the commission family below is restricted to trade.
cancel_invoice
Cancellation confirmation with banded cancellation charges and the refund position. The baseline ships the schema, template, sample data, and a create_cancel_invoice action — but the action is disabled (is_enabled: false) until your cancellation workflow goes live. Its enable conditions are modelled on the invoice action (ungated record_type: Booking) plus a status_contains: Cancelled gate. Enable it by flipping one flag; see structured-disabled configuration.
The commission family: commission_invoice and commission_statement
Trade documents for agent partners:
commission_invoice— the agent invoice with line-level commission (commissionPercent,commissionAmount,commissionGroupper line) and a commission summary block (total commission, GST, total payable).commission_statement— a pro-forma commission estimate, typically issued at option stage, with option expiry, deposit information, and a disclaimer.
Both are gated to Travel Agent channels in two independent ways:
- Action-level: the
create_commission_invoiceandcreate_commission_statementactions carrychannel_contains: Travel Agentenable conditions, so the actions are not even offered on direct channels. - Data-level: commission fields exist only in the commission document schemas. No guest document schema — proposal, confirmation, invoice — declares a commission field of any kind. A guest document cannot leak commission data because the data contract has nowhere to put it. This is the data-level trade firewall, and it is the most important gating rule in the system.
financial_summary
Charges, payment history, and the outstanding balance for a booking — generated automatically when a payment is received (the payment_received trigger). Useful as a running statement for part-paid bookings.
final_travel_docs
The operational pre-departure pack for confirmed bookings: trip summary, traveler list, supplier service confirmations, important information, and emergency contacts. Generated by the create_final_docs action, enabled when the itinerary is a Booking in Booking Confirmed status. Its expiry is long (365 days) because guests refer to it up to and during travel. It deliberately contains no pricing sections.
supporting_document_example
A regulatory certificate slot. Jurisdictional schemes (such as ATOL, TICO, or ABTA) prescribe flat certificate layouts that sit outside the normal section registry. The baseline ships one deliberately thin example — booking reference, passenger names, total cost, currency, issue date, certificate number — with its action disabled.
When your business needs a scheme certificate: rename the doc_type to the scheme, replace the schema and template with the regulator's prescribed layout, and flip is_enabled to true. Note that enabling the action also requires giving the renamed document type a data source (its own data-transformation file); see the notes in Blueprint.
Gating and expiry at a glance
The full enable-condition and expiry matrix for the shipped actions, as configured in the baseline blueprint:
| Action | Record type | Status condition | Channel condition | Expiry |
|---|---|---|---|---|
create_quote | Quote | not containing "Option" | — | 30 days |
create_option | Quote | containing "Option" | — | 30 days (pre-filled from hold end date) |
create_no_price_quote | Quote | not containing "Option" | — | 30 days |
create_agent_proposal | — | — | containing "Travel Agent" | 30 days |
create_final_docs | Booking | containing "Booking Confirmed" | — | 365 days |
create_invoice | Booking | — | — | 30 days |
create_commission_invoice | Booking | — | containing "Travel Agent" | 30 days |
create_commission_statement | — | — | containing "Travel Agent" | 30 days |
create_cancel_invoice (disabled) | Booking | containing "Cancelled" | — | 30 days |
create_supporting_document (disabled) | Booking | — | — | 365 days |
Default document names are templated per action (for example {{tour_name}} - Proposal {{date}} for proposals, {{booking_reference}} - Invoice for invoices); the placeholders resolve through the data transformation's cross-references.
When you fork the baseline, you typically adjust labels, statuses, and expiry windows to match your sales process — but the shape of the gating (proposals on quotes, finance documents on bookings, commission documents on trade channels) carries over unchanged for most operators.
Key design principles
Three rules cut across every document type and are worth internalising before you customise anything:
- Commission data exists only in commission schemas. The trade firewall is enforced at the data level, not just by hiding sections. If you find yourself wanting commission figures in a guest document, the answer is a commission-family document instead.
- Invoices are never channel-gated. A trade booking still gets a normal guest invoice; the commission invoice is an additional document, not a replacement.
- All pricing in document data is numeric with an ISO currency. Document data carries
4500, never"£4,500". Symbols, separators, and decimal conventions are applied at render time from the document's locale (meta.locale) and currency (meta.currency). This keeps one dataset renderable across locales and keeps amounts machine-checkable in QA.
Related pages
- Data contracts per type: Document data reference
- How actions, gating, and triggers are configured: Blueprint
- How the QA harness verifies each type renders correctly: QA overview