Skip to content

Submit the customer's details

The checkout.hosted.submit_details operation: POST /api/v1/public/checkout_sessions/{sessionId}/details in the REST API and the checkout_hosted_submit_details tool in the MCP server.

POST/api/v1/public/checkout_sessions/{sessionId}/details

The hosted page's first step: the customer's email, country and, for a business, the company name, tax ID and address. The tax ID is checked with its register (VIES, HMRC, the Swiss UID register). Then the tax engine quotes the sale from the location evidence: the billing country, the IP country the page captured, and the card's country once a payment method is chosen (spec §13.2).

  • A sale Ownrecord can tax is quoted (a new quote version; valid for 30 minutes): the customer, their evidence set and the quote are stored.
  • A sale it can't tax with confidence is paused (spec §1.3): the session becomes blocked with the reason and checkout.session.blocked is emitted; the page offers the waitlist and, where it helps, buying as a business. Nothing about the customer is stored then.

Submitting again (other details, or after the quote expired) quotes again. Public: the hosted page calls it with the session key.

At a glance

  • REST: POST /api/v1/public/checkout_sessions/{sessionId}/details
  • MCP tool: checkout_hosted_submit_details
  • Operation ID: checkout.hosted.submit_details
  • Scope: Brand
  • Permission: checkout:write
  • Risk tier: write
  • Dry run: Not supported
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: None (a public endpoint, rate-limited per IP address)
  • Since: M4

Request

Path parameters

FieldTypeDescription
sessionIdcs_… IDThe checkout session's ID (cs_…).

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
keystringNoThe session key from the hosted URL (?key=…). Required without an API key; signed-in callers with checkout:write don't need it.
emailstringYesThe customer's email: receipts and invoices go there.
namestringNoThe customer's name.
countrystringYesThe country the customer lives in (pre-filled from the IP address).
subdivisionstringNoThe state or region, where the regime needs it (US).
businessobjectNoBuying for a business: company name, tax ID and billing address (spec §13.2).
business.namestringYes
business.taxIdobjectNoThe company's VAT or tax ID, checked with its register.
business.taxId.typestringYesThe tax ID's type: eu_vat, gb_vat, ch_uid/ch_vat, no_org/no_vat or us_ein. Other types are kept but can't be checked (unverified).
business.taxId.valuestringYesThe number as the customer gave it, with or without the country prefix and separators.
business.taxId.countrystringYesThe country that issued the tax ID (ISO 3166-1 alpha-2; EL = Greece).
business.addressobjectYes
business.address.line1stringYes
business.address.line2stringNo
business.address.citystringYes
business.address.postalCodestringNo
business.address.regionstringNo
business.address.countrystringYes
evidenceTokenstringNoThe IP-country evidence the hosted page captured (signed by the server; opaque to clients).
promotionCodestring or nullNoSubscription sessions: a promotion code to apply (null or empty removes the applied one).
quantitiesarray of objectNoNew quantities of line items created with adjustableQuantity.
quantities[].lineItemIdstringYes
quantities[].quantityinteger (1 to 1000)Yes
localeone of en, de, fr, hr, it, esNoThe language the customer sees the page in (en, de, fr, hr, it, es). The session keeps it when it has no language yet: the customer, the invoice and the emails use it.

Response

200 OK with a JSON object:

FieldTypeDescription
idcs_… ID
object"checkout.hosted_session"
livemodeboolean
statusone of open, processing, complete, expired, blocked
modeone of payment, subscription, topup, setup
currencystring
brandobject
brand.slugstring
brand.namestring
brand.primaryColorstring or null
brand.termsUrlstring or null
brand.privacyUrlstring or null
brand.supportEmailstring or null
sellerobjectThe merchant disclosure: “Sold by {legal name}, {address}, {VAT ID}” (spec §29.1).
seller.legalNamestring
seller.addressstring
seller.taxIdstring
lineItemsarray of object
lineItems[].idstring
lineItems[].descriptionstring
lineItems[].quantityinteger
lineItems[].amountmoney
lineItems[].recurringobject or null
lineItems[].adjustableQuantityobject or null
lineItems[].discountmoney or null
subscriptionobject or nullSubscription sessions: the trial, what is due today and the promotion code.
topupobject or nullTop-up sessions (spec §14.3): what the customer's wallet receives.
setupobject or nullSetup sessions: whether saving the card also pays the subscription's first invoice.
collectBusinessDetailsone of auto, required, never
prefillobject
prefill.emailstring or null
prefill.namestring or null
prefill.countrystring or null
prefill.subdivisionstring or null
prefill.businessobject or null
quoteobject or null
blockedobject or null
waitlistobject or null
paymentobject
payment.startedboolean
payment.intentone of payment, setup or nullpayment: a charge now; setup: the card is saved without a charge.
payment.componentone of fake, stripe_payment_element, redirect or nullHow the payment details are collected: the fake processor's test cards, the Stripe Payment Element, or redirect (the buyer pays on the processor's page, Mollie; confirm answers its address).
payment.publishableKeystring or null
payment.paymentMethodobject or null
payment.upToDatebooleanThe prepared payment is for the current quote's total.
legalobject
legal.termsAcceptedboolean
legal.immediatePerformanceRequiredboolean
legal.immediatePerformanceTextstring
successUrlstring or nullSet once the session is complete: successUrl?cs_id=….
cancelUrlstring or null
expiresAtdate-time
localeobjectWhat decides the page's language (spec §14.2): an explicit choice on the page, then preferred, then the browser's languages, then brand, then English.
locale.preferredarray of stringThe session's language, then its customer's, where set (BCP 47): the page's language before the visitor's.
locale.brandarray of stringThe brand's checkout languages; the first is its default.

Examples

A consumer in Germany

HTTP
POST /api/v1/public/checkout_sessions/cs_01m4tx5nj8emwbyf7y9vcf48aa/details
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "key": "Zk3tq8Vb2xQ9mN4rP7sL1yH6cJ0wE5aD-uT_fG8hK2o",
  "email": "anna@example.com",
  "country": "DE"
}

Response (200):

JSON
{
  "id": "cs_01m4tx5nj8emwbyf7y9vcf48aa",
  "object": "checkout.hosted_session",
  "livemode": false,
  "status": "open",
  "mode": "payment",
  "currency": "EUR",
  "brand": {
    "slug": "genno",
    "name": "Genno",
    "primaryColor": null,
    "termsUrl": "https://genno.example/terms",
    "privacyUrl": "https://genno.example/privacy",
    "supportEmail": null
  },
  "seller": {
    "legalName": "Etna Labs AG",
    "address": "Dammstrasse 16, 6300 Zug, Switzerland",
    "taxId": "CHE-181.927.786 MWST"
  },
  "lineItems": [
    {
      "id": "1",
      "description": "Genno credits",
      "quantity": 1,
      "amount": {
        "amount": "100000000",
        "currency": "EUR"
      },
      "recurring": null,
      "adjustableQuantity": null,
      "discount": null
    }
  ],
  "subscription": null,
  "topup": null,
  "setup": null,
  "collectBusinessDetails": "auto",
  "prefill": {
    "email": "anna@example.com",
    "name": null,
    "country": "DE",
    "subdivision": null,
    "business": null
  },
  "quote": {
    "id": "tq_01m4tx5nj8emwbyf7y9vcf48ab",
    "decision": "charge",
    "customerType": "b2c",
    "country": "DE",
    "lines": [
      {
        "id": "1",
        "description": "Genno credits",
        "quantity": 1,
        "treatment": "charge",
        "net": {
          "amount": "84033613",
          "currency": "EUR"
        },
        "tax": {
          "amount": "15966387",
          "currency": "EUR"
        },
        "gross": {
          "amount": "100000000",
          "currency": "EUR"
        },
        "ratePpm": "190000",
        "jurisdictionId": "DE",
        "jurisdictionName": "Germany",
        "taxName": "VAT",
        "regimeId": "EU_OSS_NON_UNION",
        "pendingRegistration": false,
        "taxBehavior": "inclusive"
      }
    ],
    "totals": {
      "net": {
        "amount": "84033613",
        "currency": "EUR"
      },
      "tax": {
        "amount": "15966387",
        "currency": "EUR"
      },
      "gross": {
        "amount": "100000000",
        "currency": "EUR"
      }
    },
    "inclusive": true,
    "reverseCharge": false,
    "reverseChargeWording": null,
    "validUntil": "2026-10-14T10:30:00.000Z",
    "unverifiedRules": false
  },
  "blocked": null,
  "waitlist": null,
  "payment": {
    "started": false,
    "intent": null,
    "component": null,
    "publishableKey": null,
    "paymentMethod": null,
    "upToDate": false
  },
  "legal": {
    "termsAccepted": false,
    "immediatePerformanceRequired": true,
    "immediatePerformanceText": "I want the service to start now, and I understand that I lose my right to withdraw once it has started."
  },
  "successUrl": null,
  "cancelUrl": "https://shop.example/cart",
  "expiresAt": "2026-10-15T10:00:00.000Z",
  "locale": {
    "preferred": [],
    "brand": ["en"]
  }
}

A consumer where the seller can't sell yet

The UK needs a registration before the first consumer sale: the waitlist is offered.

HTTP
POST /api/v1/public/checkout_sessions/cs_01m4tx5nj8emwbyf7y9vcf48aa/details
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "key": "Zk3tq8Vb2xQ9mN4rP7sL1yH6cJ0wE5aD-uT_fG8hK2o",
  "email": "oliver@example.com",
  "country": "GB"
}

Response (200):

JSON
{
  "id": "cs_01m4tx5nj8emwbyf7y9vcf48aa",
  "object": "checkout.hosted_session",
  "livemode": false,
  "status": "blocked",
  "mode": "payment",
  "currency": "EUR",
  "brand": {
    "slug": "genno",
    "name": "Genno",
    "primaryColor": null,
    "termsUrl": "https://genno.example/terms",
    "privacyUrl": "https://genno.example/privacy",
    "supportEmail": null
  },
  "seller": {
    "legalName": "Etna Labs AG",
    "address": "Dammstrasse 16, 6300 Zug, Switzerland",
    "taxId": "CHE-181.927.786 MWST"
  },
  "lineItems": [
    {
      "id": "1",
      "description": "Genno credits",
      "quantity": 1,
      "amount": {
        "amount": "100000000",
        "currency": "EUR"
      },
      "recurring": null,
      "adjustableQuantity": null,
      "discount": null
    }
  ],
  "subscription": null,
  "topup": null,
  "setup": null,
  "collectBusinessDetails": "auto",
  "prefill": {
    "email": "oliver@example.com",
    "name": null,
    "country": "GB",
    "subdivision": null,
    "business": null
  },
  "quote": null,
  "blocked": {
    "reason": "registration_required",
    "country": "GB",
    "countryName": "United Kingdom",
    "waitlistOffered": true,
    "businessOffered": true
  },
  "waitlist": null,
  "payment": {
    "started": false,
    "intent": null,
    "component": null,
    "publishableKey": null,
    "paymentMethod": null,
    "upToDate": false
  },
  "legal": {
    "termsAccepted": false,
    "immediatePerformanceRequired": true,
    "immediatePerformanceText": "I want the service to start now, and I understand that I lose my right to withdraw once it has started."
  },
  "successUrl": null,
  "cancelUrl": "https://shop.example/cart",
  "expiresAt": "2026-10-15T10:00:00.000Z",
  "locale": {
    "preferred": [],
    "brand": ["en"]
  }
}

Errors

CodeHTTP statusWhenWhat to do
resource_not_found404No such checkout session for this brand and mode, or (on the hosted page) the session key is missing or wrong.Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
checkout_session_not_open409The session is complete, expired, or a payment for it is being processed (details.status).The session is complete, expired or waiting for a payment's outcome (details.status). Create a new session for a new purchase.
checkout_business_details_required400The session sells to businesses only and no company was given.Give the company name and the billing address (street, city, country) when buying as a business (spec §13.2).
tax_id_invalid400The business tax ID is malformed for its type (details.reason).Check the number and its country for typing errors (details.reason says what is wrong), then send it again. A Northern Ireland business enters its GB VAT number.
validation_failed400A field is missing or malformed, or the email isn't the session's customer's.Fix the fields listed in details.issues and send the request again.
upstream_timeout502The tax-ID register didn't answer in time. Nothing changed.Retry the request with the same Idempotency-Key after a short wait.
checkout_promotion_code_not_allowed400A promotion code on a session that doesn't take them (allowPromotionCodes).Create the session with allowPromotionCodes: true, or with promotionCode to apply one for the customer. Promotion codes apply to subscription sessions.
promotion_code_not_redeemable409The promotion code is inactive, expired, used up or not valid for this customer (details.reason).Check details.reason and tell the customer: the code may have expired, be used up, belong to another customer, need a larger purchase or be for first-time customers only.
checkout_quantity_not_adjustable400A new quantity for a line created without adjustableQuantity (details.line_item_id).Only line items created with adjustableQuantity take a new quantity on the hosted page, within its min and max.
checkout_amount_invalid400A new quantity is outside the line's adjustableQuantity bounds.Give a quantity from 1 to 1,000 for fixed prices; for a custom-amount price give customAmount within the price's minimum and maximum, in whole minor units of its currency, with quantity 1. param names the line item.
customer_deleted400A top-up's customer was deleted after the session was created.Create a new customer for this buyer. Deleted customers stay readable for the records they belong to, but can't be changed.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, scope_required, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, dry_run_not_supported, rate_limited, internal_error.