Checkout API

REST API endpoints for checkout bootstrapping, transient quote pricing, field resolution, order submission, receipt lookup, and pay-order flows.

Overview

The WooNooW Checkout API powers the customer-facing checkout application. It coordinates quote estimation, field rendering, multi-currency verification, fraud protection, order creation, session clearing, and existing order payments.

  • Controller: WooNooW\Api\CheckoutController
  • Namespace: woonoow/v1
  • Base URL: https://your-store.com/wp-json/woonoow/v1

Response Envelopes & Error Semantics


Endpoints

1. Checkout Bootstrap

Delivers personalized, non-cacheable configuration and cart state for the initial checkout page render.

http
GET /wp-json/woonoow/v1/checkout/bootstrap

Headers Sent by Server

http
Cache-Control: no-store, no-cache, must-revalidate, max-age=0
Pragma: no-cache

Permission

  • anon_or_wp_nonce: Open to anonymous customers; verifies X-WP-Nonce if provided.

Response (HTTP 200)

json
{
  "ok": true,
  "cart": {
    "currency": "USD",
    "items": [...],
    "subtotal": "99.00",
    "total": "99.00",
    "needs_shipping": true
  },
  "fields": [
    {
      "key": "billing_first_name",
      "fieldset": "billing",
      "type": "text",
      "label": "First name",
      "required": true,
      "hidden": false,
      "priority": 10
    }
  ],
  "countries": [
    { "code": "US", "name": "United States" }
  ],
  "states": {
    "US": { "NY": "New York", "CA": "California" }
  },
  "default_country": "US",
  "addresses": [],
  "customer": {
    "is_logged_in": false,
    "id": 0
  },
  "currency": {
    "base_currency": "USD",
    "currency": "USD",
    "symbol": "$",
    "decimals": 2,
    "rate": "1.0",
    "rate_id": "base"
  },
  "requires_shipping": true,
  "is_digital_only": false,
  "security": {
    "captcha_provider": "turnstile",
    "recaptcha_site_key": "",
    "turnstile_site_key": "0x4AAAAAA..."
  }
}

2. Fast Quote Calculation

Calculates transient line totals, discounts, taxes, and shipping estimates for a pending checkout without mutating the server-side session.

http
POST /wp-json/woonoow/v1/checkout/quote
Content-Type: application/json

Request Payload

json
{
  "items": [
    {
      "product_id": 42,
      "variation_id": 0,
      "qty": 2
    }
  ],
  "billing": {
    "country": "US",
    "state": "NY",
    "postcode": "10001"
  },
  "shipping": {
    "country": "US",
    "state": "NY",
    "postcode": "10001"
  },
  "coupons": ["DISCOUNT10"],
  "shipping_method": "flat_rate:1"
}

Success Response (HTTP 200)

json
{
  "ok": true,
  "items": [
    {
      "product_id": 42,
      "name": "WooNooW Pro License",
      "qty": 2,
      "price": 99.0,
      "line_total": 198.0
    }
  ],
  "totals": {
    "subtotal": "198.00",
    "discount_total": "19.80",
    "shipping_total": "5.00",
    "tax_total": "0.00",
    "grand_total": "183.20",
    "currency": "USD",
    "currency_symbol": "$",
    "currency_pos": "left",
    "decimals": 2,
    "decimal_sep": ".",
    "thousand_sep": ","
  }
}

Error Response (HTTP 200)

json
{
  "error": "Product not purchasable"
}

3. Get Checkout Fields

Returns checkout fields formatted with labels, validation rules, and classes after applying WordPress filters and addon extensions.

http
POST /wp-json/woonoow/v1/checkout/fields
Content-Type: application/json

Request Payload

json
{
  "is_digital_only": false
}

Success Response (HTTP 200)

json
{
  "ok": true,
  "fields": [
    {
      "key": "billing_first_name",
      "fieldset": "billing",
      "type": "text",
      "label": "First name",
      "placeholder": "",
      "required": true,
      "hidden": false,
      "class": ["form-row-first"],
      "priority": 10,
      "custom": false
    }
  ],
  "is_digital_only": false
}

4. Countries and States

Returns allowed selling countries and administrative regions.

http
GET /wp-json/woonoow/v1/countries

Permission

  • Public (__return_true)

Success Response (HTTP 200)

json
{
  "countries": [
    { "code": "US", "name": "United States (US)" },
    { "code": "GB", "name": "United Kingdom (UK)" }
  ],
  "states": {
    "US": { "CA": "California", "NY": "New York" }
  },
  "default_country": "US"
}

5. Calculate Shipping Rates

Computes matching shipping zone methods for a given address and package contents.

http
POST /wp-json/woonoow/v1/checkout/shipping-rates
Content-Type: application/json

Request Payload

json
{
  "shipping": {
    "country": "US",
    "state": "NY",
    "city": "New York",
    "postcode": "10001"
  },
  "items": [
    {
      "product_id": 42,
      "quantity": 1
    }
  ]
}

Success Response (HTTP 200)

json
{
  "ok": true,
  "rates": [
    {
      "id": "flat_rate:1",
      "label": "Standard Shipping",
      "cost": 5.0,
      "method_id": "flat_rate",
      "instance_id": 1
    }
  ],
  "zone_name": "United States Domestic"
}

6. Submit Order

Creates a WooCommerce order, evaluates security checks, provisions accounts, links payment methods, and purges the active cart.

http
POST /wp-json/woonoow/v1/checkout/submit
Content-Type: application/json

Request Payload

json
{
  "items": [
    {
      "product_id": 42,
      "variation_id": 0,
      "qty": 1,
      "meta": []
    }
  ],
  "billing": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "phone": "555-0199",
    "address_1": "123 Main St",
    "city": "New York",
    "state": "NY",
    "postcode": "10001",
    "country": "US"
  },
  "shipping": {
    "ship_to_different": false
  },
  "coupons": ["SUMMER10"],
  "shipping_method": "flat_rate:1",
  "shipping_cost": 5.0,
  "shipping_title": "Standard Shipping",
  "payment_method": "stripe",
  "customer_note": "Please leave at front door",
  "custom_fields": {},
  "referral_code": "AFFILIATE10",
  "captcha_token": "0.abcdef..."
}

Submission Execution Order

  1. Cart Hydration: Invokes CartController::ensure_cart_initialized() to load session data and obtain any active guest session ID.
  2. Rate Limiting: Checks SecuritySettingsProvider::is_rate_limited().
  3. Invisible CAPTCHA: Validates captcha_token via SecuritySettingsProvider::validate_captcha().
  4. Subscription Check: Disallows guest subscription checkout (You must be logged in to purchase a subscription).
  5. Multi-Currency Validation: Checks exchange rate freshness (currency_rate_stale) and verifies payment gateway currency support (currency_gateway_mismatch).
  6. Order Creation: Calls wc_create_order(['created_via' => 'checkout']).
  7. Auto-Registration:
    • If auto_register_members is enabled and billing email is new: creates user account, calls wp_set_auth_cookie() and wp_set_current_user(), and flags user_logged_in: true.
    • If email matches an existing user: links $order->set_customer_id(), but keeps user_logged_in: false for security.
  8. Items & Addresses: Appends items, recurring price metadata, and billing/shipping addresses. Auto-saves addresses to user meta via auto_save_checkout_addresses().
  9. Coupon Re-validation: Validates coupons against the persisted order. If validation fails, deletes the order immediately to prevent orphans.
  10. Hooks & Snapshots: Executes woocommerce_checkout_create_order (captures multi-currency audit snapshot), saves order, and fires woocommerce_checkout_order_processed.
  11. Cart Purge: If order succeeds, calls WC()->cart->empty_cart(true), saves session, and purges the old guest session ID via WC()->session->delete_session($guest_session_id). If order fails, the cart is preserved.
  12. Quota Tracking: Increments rate-limit counter via SecuritySettingsProvider::record_order_attempt().
  13. Payment Completion Hand-off: The endpoint returns pay_url and thankyou_url. Credit cards and tokens are not charged synchronously inside /checkout/submit; the client navigates to pay_url (or the order-pay flow) for gateway processing, or directly to thankyou_url for offline payment methods (e.g. BACS, COD).

Success Response (HTTP 200)

json
{
  "ok": true,
  "order_id": 1054,
  "order_key": "wc_order_65e9c0a1b2c3d",
  "status": "pending",
  "pay_url": "https://your-store.com/checkout/order-pay/1054/?pay_for_order=true&key=wc_order_65e9c0a1b2c3d",
  "thankyou_url": "https://your-store.com/checkout/order-received/1054/?key=wc_order_65e9c0a1b2c3d",
  "user_logged_in": true
}

Error Envelopes

ConditionResponse Body
Missing items{"error": "No items provided"}
Rate limited{"error": "Too many orders. Please try again later."}
CAPTCHA failed{"ok": false, "error": "CAPTCHA verification required", "error_code": "captcha_missing"}
Stale currency exchange rate{"error": "The exchange rate for this currency has expired. Refresh the page and try again.", "error_code": "currency_rate_stale"}
Incompatible currency gateway{"error": "The selected payment method is not available for EUR. Please choose the mapped payment method.", "error_code": "currency_gateway_mismatch"}
Coupon validation error{"error": "Coupon \"SUMMER10\" has expired.", "error_code": "coupon_failed"}
Multi-currency snapshot error{"error": "Exchange rate could not be locked.", "error_code": "order_currency_failed"}
Order status failed{"ok": false, "error": "Order processing failed. Please try again.", "order_id": 1054, "order_key": "wc_order_...", "status": "failed"}

7. Order Receipt Lookup

Retrieves order details for the thank you / order confirmation page.

http
GET /wp-json/woonoow/v1/checkout/order/{id}?key={order_key}

Access Validation

Requires at least one of the following:

  • Query parameter key matches the order key via hash_equals().
  • Logged-in customer owns the order (get_current_user_id() === $order->get_customer_id()).
  • Current user has administrative rights (manage_woocommerce).

Success Response (HTTP 200)

json
{
  "ok": true,
  "id": 1054,
  "number": "1054",
  "status": "processing",
  "created_via": "checkout",
  "subtotal": 99.0,
  "discount_total": 0.0,
  "shipping_total": 5.0,
  "tax_total": 0.0,
  "total": 104.0,
  "currency": "USD",
  "currency_symbol": "$",
  "payment_method": "Credit Card (Stripe)",
  "needs_shipping": true,
  "shipping_lines": [
    {
      "id": 45,
      "method_title": "Standard Shipping",
      "method_id": "flat_rate",
      "total": "$5.00"
    }
  ],
  "tracking_number": "1Z9999999999999999",
  "tracking_url": "https://www.ups.com/track?tracknum=1Z...",
  "billing": {
    "first_name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "phone": "555-0199"
  },
  "items": [
    {
      "id": 12,
      "product_id": 42,
      "name": "WooNooW Pro License",
      "qty": 1,
      "price": 99.0,
      "total": 99.0,
      "image": "https://your-store.com/wp-content/uploads/pro.png"
    }
  ],
  "subscription": null,
  "available_gateways": []
}

Error Response (HTTP 200)

json
{
  "error": "Unauthorized access to order"
}

8. Pay Existing Order

Processes payment for an unpaid order or subscription renewal invoice.

http
POST /wp-json/woonoow/v1/checkout/pay-order/{id}
Content-Type: application/json

Request Payload

json
{
  "key": "wc_order_65e9c0a1b2c3d",
  "payment_method": "stripe"
}

Validation Rules

  1. Access: Validated via key or authenticated order owner / admin.
  2. Paid Check: Rejects if order has already been paid (Order already paid).
  3. Renewal Payment Window: If order is a renewal (SubscriptionManager::get_order_type() === 'renewal'), checks SubscriptionManager::is_renewal_payment_window_open($order).
    • If the collection window has expired, cancels all linked renewal invoices and returns:
      json
      {
        "error": "This renewal invoice has expired. Purchase a new subscription at the current catalog price, or contact support if an exception is appropriate.",
        "error_code": "renewal_window_expired"
      }
      
  4. Gateway Locking: Must match the order's original gateway ID (This order must be paid using its original payment gateway.).

Success Response (HTTP 200)

json
{
  "ok": true,
  "redirect": "https://your-store.com/checkout/order-received/1054/?key=wc_order_..."
}

Failure Response (HTTP 200)

json
{
  "error": "Payment failed: Card was declined",
  "messages": ["Your card was declined. Please use a different card."]
}

Last updated Sep 11, 2026