---
title: "Create a hosted or embedded checkout session"
method: POST
path: "/api/v1/checkout-sessions"
tags: ["Checkout"]
---

# Create a hosted or embedded checkout session

`POST /api/v1/checkout-sessions`

## Request

- Base URL: `https://merchant.zahlo.eu`
- URL: `https://merchant.zahlo.eu/api/v1/checkout-sessions`
- Auth: API key in header `x-api-key`

Create a hosted or embedded checkout session. Use the response status and request ID to decide whether to retry, reconcile, or ask the customer for action.

## Headers

- `Idempotency-Key` string

## Request body

- CheckoutSessionCreateRequest: Send exactly one of lineItems or amountMinor.
  - `mode` 'hosted' | 'embedded'
  - `lineItems` union[]
    - union
      - object
        - `priceId` string, required
        - `quantity` integer, required
        - `adjustableQuantity` object: One-time sessions: the payer may change this line's quantity on Zahlo's details page; the total and the payment link are re-made.
          - `enabled` boolean, required
          - `minimum` integer
          - `maximum` integer
      - object
        - `name` string, required
        - `unitAmountMinor` integer, required
        - `quantity` integer, required
        - `imageUrl` string, uri
        - `adjustableQuantity` object: One-time sessions: the payer may change this line's quantity on Zahlo's details page; the total and the payment link are re-made.
          - `enabled` boolean, required
          - `minimum` integer
          - `maximum` integer
  - `amountMinor` integer: Simple mode: one total, no line items.
  - `currency` string: Required with amountMinor or ad-hoc line items; defaults to the prices' currency.
  - `description` string
  - `reference` string
  - `customerEmail` string, email
  - `customerId` string: An existing customer. Required with setupFutureUsage and type setup.
  - `setupFutureUsage` 'off_session': Save the card to customerId for later off-session charges (type payment, card only). You must have shown the customer your terms for later charges.
  - `paymentMethodTypes` string[]: Default: the merchant's default methods, else everything enabled for the currency.
  - `method` 'card' | 'sepa_direct_debit' | 'klarna' | 'ideal' | 'bancontact' | 'apple_pay' | 'google_pay' | 'paypal': Deprecated single-method form of paymentMethodTypes.
  - `locale` 'auto' | 'cz' | 'de' | 'en' | 'es' | 'fr' | 'hr' | 'hu' | 'il' | 'it' | 'kr' | 'lt' | 'pl' | 'ro' | 'ru' | 'tr'
  - `expiresInSeconds` integer
  - `successUrl` string, uri: May contain {CHECKOUT_SESSION_ID}; must be on a registered checkout domain.
  - `failureUrl` string, uri
  - `cancelUrl` string, uri
  - `type` 'payment' | 'setup' | 'subscription': subscription: a recurring price (the first one), further recurring prices as add-ons billed with it every period, and optional one-time prices charged once with the first period (setup fees, never discounted), paymentMethodTypes ["card"] and customerEmail. A price with a trial charges nothing now (paymentStatus no_payment_required). setup: saves a card to customerId without charging it; no lineItems or amountMinor.
  - `couponId` string: Applies to lineItems; on a subscription it discounts the periods its duration covers.
  - `promotionCode` string: A coupon's code as the customer typed it (case-insensitive), instead of couponId. Applies to lineItems; an unknown code is 404 resource_missing.
  - `taxIdCollection` object: Card and wallet sessions. A hosted `url` (or the embedded checkout, before `embedUrl` is given) first shows a Zahlo page that asks for the billing name, address and an optional VAT ID, then continues to payment; on a subscription the details are saved on the customer and printed on receipts.
    - `enabled` boolean, required
  - `phoneNumberCollection` object: Card and wallet sessions, hosted or embedded: the details page asks for a phone number (6 to 20 digits, optional +); it comes back in `customerDetails.phone`.
    - `enabled` boolean, required
  - `nameCollection` object: Card and wallet sessions, hosted or embedded: a full name field and/or a business name field (optional next to the full name); they come back in `customerDetails`.
    - `individual` object
      - `enabled` boolean, required
    - `business` object
      - `enabled` boolean, required
  - `consentCollection` object: Card and wallet sessions, hosted or embedded.
    - `promotions` 'auto' | 'none': `auto`: an optional marketing checkbox; the answer is `consent.promotions` (`opt_in` or `opt_out`).
    - `termsOfService` 'required' | 'none': `required`: a checkbox the payer must tick, linking the terms of service in Checkout → Store policies (400 when none is set); `consent.termsOfService` is `accepted`.
  - `allowPromotionCodes` boolean: One-time sessions with lineItems, hosted or embedded: the details page shows a promotion code field with an Apply button and a live total; the total and the payment link are re-made. Not with promotionCode or couponId.
  - `submitType` 'auto' | 'pay' | 'book' | 'donate': The details page's button label: `auto` Continue to payment, `pay`, `book` or `donate`.
  - `brandingSettings` object: Overrides Account → Branding on Zahlo pages (and `appearance`) for this session.
    - `brandColor` string
    - `logoUrl` string, uri: https only.
    - `displayName` string
  - `shippingAddressCollection` object: Card and wallet sessions, hosted or embedded. A Zahlo page (the hosted `url`, or the embedded checkout's first step) asks for a shipping name and address in one of these countries, then continues to payment; the address comes back as `shippingDetails`.
    - `allowedCountries` string[], required: ISO 3166-1 alpha-2 codes the payer may ship to.
  - `shippingOptions` object[]: One-time sessions with lineItems and shippingAddressCollection. Zahlo's page lists the options, the first preselected, and the payer may switch; the chosen rate is added to the total and never discounted.
    - `shippingRate` string: An active shipping rate in the session currency.
    - `shippingRateData` ShippingRateCreateRequest
      - `displayName` string, required
      - `type` 'fixed_amount'
      - `fixedAmount` object, required
        - `amount` integer, required: Minor units, VAT included.
        - `currency` string, required
      - `deliveryEstimate` object, nullable: Either bound may be omitted; the minimum may not exceed the maximum.
        - `minimum` object, nullable
          - `unit` 'business_day' | 'day' | 'hour' | 'week' | 'month', required
          - `value` integer, required
        - `maximum` object, nullable
          - `unit` 'business_day' | 'day' | 'hour' | 'week' | 'month', required
          - `value` integer, required
      - `metadata` object: Up to 50 key-value pairs; keys up to 40 characters, values strings up to 500 characters.
  - `customFields` CustomFieldDefinition[]: Up to 3 questions. Card and wallet sessions, hosted or embedded: a Zahlo page (the hosted `url`, or the embedded checkout's first step) asks them, then continues to payment. The answers come back in `customFields` and on `checkout.session.completed`.
    - `key` string, required: Unique within the list.
    - `label` object, required
      - `type` 'custom', required
      - `custom` string, required
    - `type` 'dropdown' | 'text', required
    - `optional` boolean
    - `dropdown` object
      - `options` object[], required
        - `label` string, required
        - `value` string, required: Unique within the options.
      - `defaultValue` string: One of the option values.
    - `text` object
      - `minimumLength` integer
      - `maximumLength` integer
      - `defaultValue` string
  - `metadata` object: Up to 50 key-value pairs; keys up to 40 characters, values strings up to 500 characters.

## Response `201`

Checkout session created

- CheckoutSession
  - `id` string, required
  - `object` 'checkout_session', required
  - `livemode` boolean
  - `createdAt` string, date-time
  - `type` 'payment' | 'setup' | 'subscription', required
  - `mode` 'hosted' | 'embedded', required
  - `status` 'open' | 'complete' | 'expired' | 'failed', required
  - `paymentStatus` 'unpaid' | 'paid' | 'no_payment_required', required
  - `url` string, uri, nullable: Hosted only, while open: redirect the customer here.
  - `clientToken` string, nullable: Embedded only, while open: pass it to the browser SDK.
  - `detailsRequired` boolean: Embedded only: true until the payer completed Zahlo's details step (the browser SDK mounts it first); embedUrl is null meanwhile.
  - `embedUrl` string, uri, nullable
  - `expiresAt` string, date-time, required
  - `currency` string, required
  - `amountSubtotal` integer
  - `amountDiscount` integer
  - `amountShipping` integer: The chosen shipping option, inside amountTotal; 0 without one.
  - `amountTotal` integer, required
  - `shippingOptions` object[]: The offered shipping rates with their amount at session create, in order.
    - `shippingRate` string, required
    - `shippingAmount` integer, required
  - `shippingCost` object, nullable: The chosen shipping option. amountTax is 0: VAT is inside the amount. Discounts never apply to shipping.
    - `amountSubtotal` integer, required
    - `amountTax` integer, required
    - `amountTotal` integer, required
    - `shippingRate` string, required
  - `lineItems` object[], required
    - `name` string
    - `quantity` integer
    - `unitAmountMinor` integer
    - `amountMinor` integer
    - `priceId` string, nullable
    - `adjustableQuantity` object: Present when the payer may change this line's quantity.
      - `enabled` boolean
      - `minimum` integer
      - `maximum` integer
  - `customerId` string, nullable
  - `setupFutureUsage` 'off_session', nullable: Set when the session saves the card for off-session charges.
  - `customerEmail` string, nullable
  - `couponId` string, nullable
  - `paymentId` string, nullable
  - `subscriptionId` string, nullable
  - `reference` string, nullable
  - `customFields` CustomField[]: The session's custom fields with the payer's answers; empty when it asks none.
    - `key` string, required
    - `label` object, required
      - `type` 'custom', required
      - `custom` string, required
    - `type` 'dropdown' | 'text', required
    - `optional` boolean, required
    - `dropdown` object, nullable, required
      - `options` object[], required
        - `label` string, required
        - `value` string, required
      - `defaultValue` string, nullable, required
      - `value` string, nullable, required
    - `text` object, nullable, required
      - `minimumLength` integer, nullable, required
      - `maximumLength` integer, nullable, required
      - `defaultValue` string, nullable, required
      - `value` string, nullable, required
  - `phoneNumberCollection` object: The details page asks for a phone number.
    - `enabled` boolean, required
  - `nameCollection` object: The details page asks for a full name and/or a business name.
    - `individual` object, required
      - `enabled` boolean, required
    - `business` object, required
      - `enabled` boolean, required
  - `consentCollection` object
    - `promotions` 'auto' | 'none', required
    - `termsOfService` 'required' | 'none', required
  - `allowPromotionCodes` boolean
  - `submitType` 'auto' | 'pay' | 'book' | 'donate'
  - `brandingSettings` object, nullable: This session's branding override; null fields fall back to Account → Branding.
    - `brandColor` string, nullable
    - `logoUrl` string, nullable
    - `displayName` string, nullable
  - `taxIdCollection` object
    - `enabled` boolean, required
  - `customerDetails` object: What the payer entered on the details page; null until then.
    - `email` string, nullable, required
    - `phone` string, nullable, required
    - `individualName` string, nullable, required
    - `businessName` string, nullable, required
  - `consent` object
    - `promotions` 'opt_in' | 'opt_out', nullable, required
    - `termsOfService` 'accepted', nullable, required
  - `shippingDetails` object, nullable: The shipping address the payer entered on Zahlo's page, for a payment link or a session with `shippingAddressCollection`.
    - `name` string, required
    - `address` object, required
      - `line1` string, required
      - `line2` string, nullable, required
      - `city` string, required
      - `postalCode` string, required
      - `country` string, required: ISO 3166-1 alpha-2
  - `successUrl` string
  - `cancelUrl` string
  - `locale` string
  - `paymentMethodTypes` string[]
  - `appearance` CheckoutAppearance
    - `theme` 'light' | 'dark' | 'auto'
    - `logoUrl` string, uri
    - `iconUrl` string, uri
    - `fontFamily` string
    - `colors` object
    - `spacing` 'compact' | 'normal' | 'comfortable'
    - `customCss` string
  - `metadata` object: Up to 50 key-value pairs; keys up to 40 characters, values strings up to 500 characters.

## Other responses

- `400`: Invalid request
- `401`: Authentication failed
- `404`: Resource not found
- `409`: Request conflicts with existing state

---

[API](https://skmtc.dev/zahlo/apis/zahlo-merchant-api.md) - [All operations](https://skmtc.dev/zahlo/apis/zahlo-merchant-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zahlo/apis/zahlo-merchant-api/revisions/8fcbef981e0d?raw)
