Checkout session
id: woocommerce-woo-store-checkoutsession owner: woocommerce method: POST path: /wp-json/headlesswp/v1/store/checkout-session title: Checkout session usedBySite: true
POST /wp-json/headlesswp/v1/store/checkout-session
Creates a checkout session via the HWP WooCommerce checkout bridge.
Auth + CSRF
- Auth: public (guest checkout can be enabled by plugin settings).
- Proxy nonce required: yes.
- CSRF: required at the site proxy boundary.
- The site sends requests through
/api/secure/**, andX-WP-Nonceis attached by the secure request builder for this mutating endpoint. See request builder.
Request schema
Query parameters (optional):
ref(string): affiliate ref ID for tracking cookies.campaign(string): optional campaign slug for tracking cookies.utm_source(string): optional non-affiliate UTM source attribution value.utm_medium(string): optional non-affiliate UTM medium attribution value.utm_campaign(string): optional non-affiliate UTM campaign attribution value.utm_content(string): optional non-affiliate UTM content attribution value.
JSON object fields accepted by the fixture controller:
items(required): array of 1..30 objects.productId(required, integer > 0)quantity(required, integer 1..50)variationId(optional, integer > 0)
couponCode(optional, string)couponCodes(optional, string[])returnUrl(required fortoken_handoff; optional forredirect_to_woo; http/https URL)cancelUrl(optional, http/https URL)notes(optional, string)paymentToken(optional, string; required only for token handoff strategy)customer(optional object; shape depends on auth + checkout account creation settings)billingAddress(optional object)shippingAddress(optional object)strategy(optional string)
Notes:
itemsis mandatory; missing/invalid payloads returnVALIDATION_FAILEDwithfieldErrors.- Unknown top-level fields are rejected by the controller allowlist policy.
- The sales site sends only upstream-supported request fields and does not include any local checkout mode field.
- The sales site sends affiliate attribution via query params only and never includes an
attributionfield in the JSON body. - Attribution query params (
ref,campaign,utm_source,utm_medium,utm_campaign,utm_content) are forwarded through the secure proxy allowlist when present. - Affiliate attribution retains precedence for Woo order attribution meta. When
refis present, Woo attribution fields are stamped from affiliate data. - Non-affiliate orders with any UTM query params stamp Woo order attribution with
source_type=utmand the provided UTM values. - Non-affiliate orders without UTM query params default Woo attribution
source_typetotypein.
Response schema
Success envelope:
{
"data": {
"checkoutUrl": "https://...",
"orderId": "123"
},
"meta": {
"correlationId": "...",
"correlation_id": "...",
"request_id": "...",
"timestamp": "2025-01-01T00:00:00Z"
}
}
-
orderIdmay benull. -
metafollows the standard HWP response envelope fields. -
This endpoint supports both
redirect_to_wooandtoken_handoffstrategies. -
Token handoff uses a two-step Stripe PaymentIntent flow under the hood: create (
payment_intents) then confirm (payment_intents/{id}/confirm). -
returnUrlis required for token handoff because some Stripe configurations requirereturn_urlduring confirm. -
When
returnUrlis provided, token handoff forwards it to Stripe asreturn_urlon the confirm call. -
utm_source,utm_medium,utm_campaign, andutm_contentquery params are accepted for both affiliate and non-affiliate checkouts. -
Token handoff order creation stamps Woo attribution meta before gateway processing: affiliate requests keep precedence (
source_type=referral,utm_source=affiliatewp,utm_medium=affiliate, campaign/content from referral context); non-affiliate requests with UTM query params setsource_type=utm; non-affiliate requests without UTM query params default_wc_order_attribution_source_typetotypein(Direct in Woo admin). -
Valid marketing UTM values are also persisted on the order as additive HeadlessWP meta (
marketingUtmSource,marketingUtmMedium,marketingUtmCampaign,marketingUtmContent) so campaign context is retained even when affiliate attribution takes precedence.
Token handoff success example:
{
"data": {
"orderId": 123,
"mode": "token_handoff",
"strategy": "token_handoff",
"provider": "stripe",
"paymentStatus": "paid",
"status": "succeeded"
},
"meta": {
"correlationId": "...",
"correlation_id": "...",
"request_id": "...",
"timestamp": "2025-01-01T00:00:00Z"
}
}
Error envelope:
{
"error": {
"code": "VALIDATION_FAILED",
"message": "Validation failed.",
"details": {}
},
"meta": {
"correlationId": "...",
"correlation_id": "...",
"request_id": "...",
"timestamp": "2025-01-01T00:00:00Z"
}
}
Token handoff gateway error example (sanitized):
Safe Stripe fields for token handoff failures:
details.gatewayError.code(string): sanitized Stripe error code when available.details.gatewayError.decline_code(string | null): sanitized Stripe decline code when available (for exampleinsufficient_funds,lost_card).details.gatewayError.code = "fraud"maps topayment_fraud_blockedfor customer-safe checkout copy.lost_card,stolen_card,fraudulent, andmerchant_blacklistdecline codes map topayment_card_declined_genericto avoid leaking sensitive decline details.- The headless site can show deterministic Stripe decline messaging only for
token_handofffailures, becauseredirect_to_woocompletes payment on WordPress and does not expose Stripe decline details to the headless site in time for checkout messaging.
{
"error": {
"code": "CHECKOUT_FAILED",
"message": "Checkout failed.",
"details": {
"safeReason": "stripe_error",
"phase": "checkout_session",
"step": "stripe_request",
"gatewayError": {
"type": "invalid_request_error",
"code": "parameter_invalid_empty",
"decline_code": null,
"param": "payment_method",
"message": "Payment method is required."
},
"gatewayRequestId": "req_123"
}
}
}
Error codes
Fixture-backed codes seen for this endpoint:
CHECKOUT_NOT_IMPLEMENTEDCHECKOUT_DISABLEDCHECKOUT_STRIPE_NOT_CONFIGUREDVALIDATION_FAILEDCHECKOUT_FAILEDCSRF_FAILEDRATE_LIMITEDNOT_AUTHENTICATEDIDEMPOTENCY_KEY_REUSE_CONFLICT