---
title: "Build a checkout form"
description: "Collect order and customer details in Fillo, then hand the customer to a dedicated payment provider."
order: 8
type: "guide"
topic: "Use cases"
tags:
  - "checkout"
  - "order intake"
  - "redirect"
  - "payments"
updated: "2026-07-15"
---

A Fillo checkout form collects order intent and customer context before the payment step. Fillo doesn't process payments and has no card field — never collect card numbers, security codes, or bank credentials in a text field.

## Collect only the handoff data

```ts
const orderRequest = defineForm({
  id: "order-request",
  title: "Confirm your order details",
  pages: [{
    id: "order",
    blocks: [
      { id: "order_id", kind: "hidden", label: "Order", paramName: "order" },
      { id: "email", kind: "email", label: "Receipt email", required: true },
      {
        id: "delivery",
        kind: "select",
        label: "Delivery preference",
        required: true,
        options: [
          { id: "standard", label: "Standard" },
          { id: "express", label: "Express" },
        ],
      },
      { id: "notes", kind: "long_text", label: "Delivery notes" },
    ],
  }],
  settings: {
    submitLabel: "Continue to payment",
    successTitle: "Order details saved",
    redirectUrl: "https://shop.example.com/pay",
  },
});
```

Respondents can edit the hidden order ID, so validate the signed-in cart on your server before creating a payment session or fulfilling anything.

## Own payment state in the commerce backend

Build the payable amount and provider session from server-trusted product and price data, and treat a Fillo webhook or application callback as a signal that a request came in, nothing more. Payment success, idempotency, inventory, taxes, refunds, and fulfillment belong to the commerce system and payment provider.

A static completion redirect can send the browser on to an existing checkout route, but it isn't proof that the Fillo response, payment session, and signed-in account belong together.

## Test failure paths

Walk through an expired cart, a changed price, a duplicate submission, payment abandonment, a webhook retry, and a customer returning from the payment provider. No Fillo response should trigger fulfillment without independently verified payment state.

## Try it

[Start with a prompt](/start?from=guide-build-a-checkout-form) and your coding agent builds the first form, staged for your review — or [open the editor](/new).

## Related

- [Contact example](/examples#contact): See a compact form sitting beside application-owned content.
- [Hidden field](/docs/fields/hidden): Carry routing context without treating it as authorization.
- [Completion](/docs/completion): Redirect after Fillo accepts the response.
- [Webhooks](/docs/webhooks): Deliver a duplicate-aware response event to your backend.
