Whichever way you take payment — redirecting to Hosted checkout or embedding Payment components on your own page — it starts the same way: create a Checkout Session on your backend. The response carries both handoff values: the hosted url and the clientSecret.
POST to /checkoutsessions/create from your backend. All authentication and routing values are passed as HTTP headers; the body holds the Checkout Session configuration. For a fixed-price payment, a single line item is enough — amount.total is in major units (10 = $10.00), and the Checkout Session currency is inferred from the line items.
curl -X POST https://api.shift4.com/api/rest/v1/checkoutsessions/create \
-H "AccessToken: YOUR_ACCESS_TOKEN" \
-H "InterfaceVersion: 1.0" \
-H "InterfaceName: YourApp" \
-H "CompanyName: YourCompany" \
-H "Content-Type: application/json" \
-d '{
"checkoutSession": {
"lineItems": [
{
"product": {
"name": "Order #1234",
"currencyCode": "USD",
"amount": { "total": 10 }
}
}
]
}
}'The response wraps a single result. The checkoutSession carries the id (chse_…), the clientSecret (chcs_…, for Payment components), the hosted url, and status (active):
{
"result": [
{
"checkoutSession": {
"id": "chse_wMCUGVZgpf45fWHzKbYWMKmZ",
"clientSecret": "chcs_II2TvLWBrzFniRdjLpgo2zIflaTCzZ5BGPngPZEu0XasgwYRBCHEpyqE0tO9pYoc",
"url": "https://pay.shift4.com/chse_wMCUGVZgpf45fWHzKbYWMKmZ",
"status": "active"
}
}
]
}This is a trimmed example showing only the handoff fields you act on right away. The full Checkout Session object is much richer — it echoes back everything you configured (line items, customer, addresses, custom and static fields, capture and locale settings) plus server-set fields like expiresAt and, once paid, lastTransaction. See the Create Checkout Session reference for the complete schema.
A Checkout Session is valid for one hour. After that it moves to expired status and can no longer be paid — its expiresAt timestamp records exactly when. If a Checkout Session expires before the customer pays, create a new one.
To authenticate, follow the Quick Start to exchange your Client GUID and Auth Token for an Access Token, then include AccessToken, InterfaceVersion, InterfaceName, and CompanyName on every request.
API reference: Create Checkout Session.
The minimal call above is rarely all you want. The most useful checkoutSession options are below.
A line item's product.amount takes one of two shapes. Use total for a fixed amount — the same price every customer pays. Use options and/or custom for a customer-chosen amount, where the customer decides what to pay — useful for donations, tips, or pay-what-you-want pricing. total is mutually exclusive with the customer-chosen shapes.
For a fixed amount, set a fixed total (major units):
{
"product": {
"name": "Premium Plan",
"currencyCode": "USD",
"amount": { "total": 49.99 }
}
}For a customer-chosen amount, present preset amounts with options, a custom amount range with custom (min/max), or both together — give options and custom in the same amount to show the preset amounts alongside an "other amount" field:
{
"product": {
"name": "Contribution",
"currencyCode": "USD",
"amount": {
"options": [5, 10, 25],
"custom": { "min": 1, "max": 1000 }
}
}
}For a no-code way to collect customer-chosen amounts, see Payment Links.
Set collectBillingAddress or collectShippingAddress to true to ask the customer for the address (both default to false). Collected addresses appear on the Checkout Session's lastTransaction after payment.
{
"checkoutSession": {
"lineItems": [ /* … */ ],
"collectBillingAddress": true,
"collectShippingAddress": true
}
}How the address is collected depends on the integration. With Hosted checkout, the form asks for it. With Payment components card payments, your page must supply it in the billing/shipping objects passed to continue() — see Card payments. For wallet payments (Apple Pay / Google Pay), it is fetched from the wallet automatically.
Use customFields to ask the customer for extra information — up to 3 text inputs, each with a key (your identifier) and label (shown to the customer, max 20 chars); set optional: true to make one non-mandatory. Use staticFields to display read-only context (for example an invoice number) — a key-value object of up to 10 entries.
{
"checkoutSession": {
"lineItems": [ /* … */ ],
"customFields": [
{ "key": "shoe_size", "label": "Shoe size", "optional": false }
],
"staticFields": { "Invoice number": "ORD-4421" }
}
}The values the customer enters come back on the Checkout Session's customFields when you retrieve it.
Associate a customer in one of three mutually exclusive ways: pass customer with an existing id, pass customer with inline details (emailAddress required), or set checkoutSession.customerCreationPolicy to create to let Shift4 create one.
{
"checkoutSession": { "lineItems": [ /* … */ ] },
"customer": { "id": "cust_oM1i4j7EsIY7W5vqqF76diGw" }
}localesets the checkout language (defaults to the customer's browser language).vendorReferenceis a merchant-defined descriptor reportable on the merchant portal and settlement extract.allowSavedCards(defaultfalse) lets the customer use a card on file.capture(defaulttrue) controls whether the resulting charge is captured immediately. Set it tofalsefor an auth-only Checkout Session — the charge is authorized now and you capture it later; see Capturing Sales.webhookUrlis a destination URL this Checkout Session's webhooks (checkout_session_created,checkout_session_completed,checkout_session_expired) are sent to. Set it to receive them — see Confirm the payment.metadatais a flat key-value object for your own use, echoed back on the Checkout Session and never shown to the customer.
To authorize a card — confirm it's valid and save it on file without charging — set action: "card_verification". These Checkout Sessions take no lineItems, but require a top-level currency, allowSavedCards: true, and a defined customer. Leave capture unset or false — a verification charges nothing, and capture: true is rejected. When action is omitted, the Checkout Session defaults to a line-items payment.
{
"checkoutSession": {
"action": "card_verification",
"currency": "USD",
"allowSavedCards": true
},
"customer": { "id": "cust_oM1i4j7EsIY7W5vqqF76diGw" }
}