Order form template that takes payment
Short answer: this is a complete QuizGen JSON definition for a small-business order form — customer details, product picks, a pickup or delivery date — with a native Stripe payment question at the end so the order and the payment happen in the same step. POST it as-is (with your own products and prices) and you get a hosted order page at a short link. If you're not on the Business plan yet, skip to the fallback section below — the rest of the template still works.
This is what an order form template is for: not a full storefront, but a single link you can text or post that takes someone from "I want one" to "paid" for a fixed, simple catalog — pre-orders, custom orders, small runs, event merch. For the wider case — what a hosted order form does that a printable one can't, and where it stops — see https://quizgen.dev/online-order-form.
The template
A print shop taking custom t-shirt orders, priced by quantity:
{
"schema_version": 1,
"kind": "form",
"title": "Riverside Print Co. — order form",
"description": "Custom screen-printed shirts. Payment is collected when you submit.",
"settings": {
"collect_respondent": "email_required",
"completion": {
"message": "Thanks! We'll confirm your order and pickup or delivery time by email."
}
},
"sections": [
{
"key": "order",
"title": "Your order",
"questions": [
{ "id": "customer_name", "type": "short_text", "prompt": "Your name",
"required": true },
{ "id": "phone", "type": "phone", "prompt": "Phone number",
"required": true, "help": "In case we need to reach you about your order." },
{ "id": "style", "type": "choice", "prompt": "Which shirt are you ordering?",
"required": true,
"options": [
{ "value": "crew_tee", "label": "Crew neck tee" },
{ "value": "hoodie", "label": "Hoodie" },
{ "value": "tank", "label": "Tank top" },
{ "value": "long_sleeve", "label": "Long sleeve" }
] },
{ "id": "fulfillment", "type": "choice", "prompt": "Pickup or delivery?",
"required": true,
"options": [
{ "value": "pickup", "label": "Pickup at the shop" },
{ "value": "delivery", "label": "Local delivery" }
] },
{ "id": "delivery_address", "type": "short_text", "prompt": "Delivery address",
"required": true,
"show_if": { "question": "fulfillment", "op": "eq", "value": "delivery" } },
{ "id": "needed_by", "type": "date", "prompt": "Date you need it by",
"required": true },
{ "id": "notes", "type": "long_text", "prompt": "Design details, logo placement, colors",
"help": "Attach nothing here — just describe it. We'll follow up by email if we need a file.",
"rows": 4 }
]
},
{
"key": "payment",
"title": "Payment",
"questions": [
{ "id": "package", "type": "payment",
"prompt": "Choose your quantity and pay now", "required": true,
"price_options": [
{ "value": "single", "label": "1 shirt", "amount_cents": 2500 },
{ "value": "five_pack", "label": "5-pack", "amount_cents": 11000,
"detail": "$22 each" },
{ "value": "ten_pack", "label": "10-pack", "amount_cents": 20000,
"detail": "$20 each" },
{ "value": "twenty_pack", "label": "20-pack (event size)", "amount_cents": 38000,
"detail": "$19 each" }
],
"button_label": "Pay & confirm order" }
]
}
]
}
What each piece is doing
kind: "form"— the order shows on one page (not one question per screen), which matches how people expect to fill in an order.collect_respondent: "email_required"— this is the "customer contact" field. You don't need a separateemailquestion; the address is captured automatically and attached to the response.styleis achoicequestion. Note that every style costs the same here — see the rule below about why it has to.fulfillmentis achoice, anddelivery_addressonly appears when they pick delivery, viashow_if.needed_byis adatequestion — always prefer it over a text field for dates; the answer comes back as"YYYY-MM-DD".packageis the onepaymentquestion this quiz is allowed to have.price_options(2–10 of them) is the right choice here instead of a singleamount_cents, because the respondent is picking their quantity and paying the exact amount for it — one dropdown, one charge, no separate invoice step.
The one rule to keep: price_options is the only place quantity lives
There is deliberately no separate "How many shirts?" question in this
template, and that is the most important thing to copy. A form takes one
payment question, and that question charges exactly the amount_cents of
the option the customer picked — nothing else on the form can change the
total. So the moment you add a free-entry field that also implies a price,
the two can disagree and the charge always wins:
A
numberquestion asking "How many shirts?" alongside aprice_optionslist is a trap. The customer types 20, picks the 1 shirt — $25 option, and the form accepts it. The order arrives withpaid: trueagainst $25 for twenty shirts, and the only way to catch it is for a human to read every row.
The same trap catches per-option surcharges. If style had a "Hoodie
+$15" label, picking the hoodie would still charge the plain bundle price,
because price_options is the entire pricing model — labels are text, not
arithmetic. Either fold the surcharge into the price list (a "5-pack
hoodies" option at its real price) or charge one price across styles, as
this template does.
The rule that follows: anything that changes what someone owes belongs in
price_options, and nowhere else. Questions outside the payment question
are for things you need in order to fulfil the order — style, colour,
address, deadline, notes — not for things that determine the total. If your
combinations won't fit in ten price options, that is the signal to reach for
a real store rather than to add a quantity box.
Payment needs the Business plan — here's the fallback
The payment question type is live, but it's gated: it only works on the
Business plan ($49/mo), and only after the creator finishes Stripe
onboarding at quizgen.dev/dashboard/payments. Until
that's done, creating a quiz with a payment question returns a 402
payments_not_ready error. Money always goes to the creator's own Stripe
account — QuizGen takes a 2% platform fee on top, nothing more.
If you're not on Business yet, the rest of this template still works —
just drop the payment section and pick one of two fallbacks:
- Collect now, invoice after. Take the order with everything above, then send an invoice with the total and a payment link once you've confirmed details (custom sizing, design proofs, whatever needs a human look first).
- Redirect to an external payment link. Add
"completion": { "redirect_url": "https://buy.stripe.com/YOUR_LINK" }tosettingsand the respondent lands on your existing Stripe Payment Link or PayPal.me page right after submitting. You lose the "pick your size, pay the right amount" convenience ofprice_options, but the order and the payment still happen in one flow.
Either fallback is a completely normal way to run this template — plenty of small shops will use redirect links even after they're eligible for native payment, especially if they already have Stripe Payment Links set up.
Reading orders back
GET /api/v1/quizzes/:id/responses returns each order's answers (style,
package, fulfillment, notes) plus, for a paid order, paid: true and the
Stripe payment_intent id — that's what you reconcile against your Stripe
dashboard if a number ever looks off. Filter with ?complete=true to skip
abandoned carts.
For same-day routing, don't poll — set a webhook on the quiz. Every completed order POSTs itself to your endpoint the moment it's paid, so you can push it straight into your fulfillment queue, a Slack channel, or a spreadsheet instead of checking the dashboard.
When a real store is the better tool
Be honest with yourself about the size of the catalog before reaching for this. QuizGen's order form is for a fixed, simple catalog — a handful of products or package sizes, no per-item options exploding into hundreds of SKUs. It has no inventory tracking, no variant matrix (size × color × style all at once), and no shipping-rate calculator. If you need any of those — real inventory counts, a cart with multiple line items, calculated shipping — use Shopify or Square; they're built for exactly that and it would be a mistake to fight this template into doing their job. Reach for this template instead for pre-orders, custom one-off orders, small production runs, and event merch — the cases where "one page, one payment, done" is the whole requirement.
Let an AI assistant fill it in
Connect QuizGen's MCP server and say:
Read https://quizgen.dev/blog/order-form-template.md and make me an order form for my candle shop: 3 scents, one size, $18 each, pickup only, needed-by date, and a notes field for gift messages. I'm on the Business plan and already connected to Stripe.
The assistant adapts the products and prices, POSTs the definition, and hands back the live link.
FAQ
Can I sell more than one product in the same order? Change style to
multi_choice so people can select several items, but keep the payment
question's price_options as fixed bundles or package sizes — there's no
per-line-item cart math, so price each option as a complete order. If
selecting a second item is supposed to cost more, that difference has to
appear as its own price option; a multi_choice selection can't add to the
total on its own.
How do I let someone order a quantity I didn't list? You don't — not in
the same submission. Add a "More than 20 / custom quantity" choice option
with no price attached and show_if a notes field off it, then quote them
separately with an invoice. A form charges one
listed amount; anything negotiated needs a second step.
What happens if someone abandons before paying? The response is saved
with complete: false and no paid field. Nothing is charged, and nothing
ships — you can safely ignore incomplete responses when you tally orders.
Can I cap how many orders I take? Yes — "max_responses": 50 in
settings closes the form automatically once you hit it, which is exactly
what a limited production run needs.
Does the order form need to be a quiz? No — kind: "form" renders
everything on one page, which is what people expect from an order form.
kind is advisory only; anything you set in settings overrides it.
$ curl quizgen.dev/blog/order-form-template.md
This guide as raw markdown — no HTML for your agent to parse.
Keep reading
- Quote template your client can approve in one clickNot a document to email — a hosted quote with a recorded approval.
- Event registration form template (with paid tickets)Ticket tiers, a capacity cap, and card payment on the registration page.
- Customer satisfaction survey template (with NPS)The NPS question is a 0–10 scale — here's the whole survey around it.