Skip to content

Breeze 3D Secure Checkout

Wire your checkout to complete Breeze's required 3D Secure authentication — load the Risk SDK, handle the redirect, and capture the order on return.

Breeze authenticates every customer card payment with 3D Secure (3DS) — both new cards and previously saved cards. Unlike traditional gateways (NMI, Authorize.net), a Breeze card charge is not approved silently: the customer completes a short bank authentication step before the payment is captured.

This guide shows how to wire your checkout so Breeze payments complete correctly. It applies only to the initial customer purchase — subscription rebills are merchant-initiated and process automatically without any redirect.

Prerequisite: A Breeze gateway configured in Spark CRM with an API Key (the only credential the form requires), plus a Risk SDK Key and a Webhook Secret — both optional in the form, but the Risk SDK Key is needed for the risk session on every card payment, and without the Webhook Secret Spark CRM rejects Breeze’s webhooks. See Payment Gateways.


How It Works

A Breeze card checkout is a redirect flow, the same shape as PayPal: the customer is sent to Breeze to authenticate, then returns to your funnel to complete the order.

Load Risk SDK  → get risk session

Process Payment  (card + risk_session_id + return_url + cancel_url)

Breeze needs 3DS → response returns redirect_required + redirect_url

Redirect the customer to redirect_url  (Breeze's hosted 3DS page)

Customer authenticates → Breeze redirects back to your return_url

Capture  (finalizes the order)

Order complete  → subscriptions, fulfillment, and webhooks fire

A backend webhook from Breeze also finalizes the order automatically, so the sale still completes even if the customer closes the browser before returning — as long as the Breeze gateway has a Webhook Secret saved in Spark CRM, which is what Spark CRM verifies the webhook against.


Step 1: Load the Risk SDK

On your checkout page, load Breeze’s Risk JS SDK using your gateway’s Risk SDK Key. The SDK produces a risk session ID that Breeze requires on every card payment for fraud scoring.

Capture the session ID from the SDK and include it when you submit the checkout form.

The Risk SDK Key is the one you entered on the Breeze gateway — Spark CRM stores it for your checkout page to use and never validates it. If the SDK is not loaded and no payment.risk_session_id is sent, the charge is forwarded to Breeze with no risk object and Breeze declines it at the gateway, so check your checkout page first when card payments start failing.


Step 2: Process the Payment

When the customer submits the checkout form, call Checkout API > Orders > Process Payment (POST /checkout/orders/payment) and include three extra fields alongside the card details:

Field Description
payment.risk_session_id The risk session ID from the Risk SDK (Step 1)
payment.return_url Where Breeze returns the customer after successful authentication
payment.cancel_url Where Breeze returns the customer after failed or abandoned authentication

Point return_url and cancel_url at pages on your own funnel — the customer lands there after 3DS, and your success page then calls the Capture endpoint (Step 4).

All three are required for a Breeze card payment. If the order is routed directly to a Breeze gateway — you passed gateway_id, or the campaign has a Breeze gateway set — and return_url or cancel_url is missing, Spark CRM rejects the request with a clear 422: “This gateway requires 3D Secure. Include payment.return_url and payment.cancel_url…” Orders routed through a Payment Orchestrator are not pre-checked, because the gateway is resolved after this point — there a missing return URL comes back as a Breeze decline (“threeDs is required”) instead, so always send both URLs.


Step 3: Handle the Redirect Response

When Breeze needs the customer to authenticate, Process Payment responds with a redirect instruction instead of an immediate approval:

{
  "success": true,
  "message": "Payment initiated - customer redirect required",
  "data": {
    "payment_status": "pending_redirect",
    "redirect_required": true,
    "redirect_url": "https://pay.breeze.cash/hosted-three-ds?d=..."
  }
}

When you see redirect_required: true, send the customer’s browser to redirect_url. This is Breeze’s hosted 3D Secure page, where the customer completes authentication (often instant/“frictionless” for low-risk cards, or a quick bank challenge otherwise).

Do not advance to the upsell or confirmation page yet — the payment is not captured until the customer returns and you call Capture.


Step 4: Confirm the Result (Capture)

After authentication, Breeze redirects the customer back to your return_url. On that page, call Checkout API > Orders > Capture (POST /checkout/orders/capture) with the order_number.

Capture re-checks the payment with Breeze and returns one of three results:

HTTP Body What it means
200 success: true Approved. The order is completed — subscriptions, fulfillments, and order webhooks fire. Show the success page and continue the funnel.
422 success: false, “Payment was not completed” Declined. Send the customer back to checkout.
202 success: true, payment_status: "pending_external_confirmation" Breeze is reviewing the payment. Do not treat this as approved and do not advance to upsells — the webhook completes or declines the order when Breeze resolves it.

Because a 202 also carries success: true, branch on the HTTP status or on data.payment_status, not on success alone.

If the customer arrives at your cancel_url instead (they failed or abandoned 3DS), treat it as a declined payment and return them to the checkout to try again.

Is calling Capture required?

Not for the order to complete — Breeze also sends a PAYMENT_SUCCEEDED webhook to Spark CRM that finalizes the order (subscriptions, fulfillments, events) in exactly the same way. The two are idempotent: whichever happens first completes the order, and the other becomes a no-op. So an order is never lost, even if the customer closes the tab and never returns — provided the Breeze gateway has a Webhook Secret saved in Spark CRM and the webhook URL is set in your Breeze dashboard. Without the secret, Spark CRM cannot verify Breeze’s webhooks and rejects them with a 403, leaving your Capture call as the only way an order completes.

The difference is who gets told the result:

Completes the order Tells the customer’s browser
Capture (you call it on return) Yes — unless Breeze answers 202 (still reviewing) Yes — instantly
Webhook (automatic) Yes No — it reaches Spark CRM, not the shopper’s screen

A webhook is server-to-server, so it can’t tell the shopper’s browser anything. That’s the one thing Capture is for.

Recommendation:

  • Call Capture on return so the customer immediately sees success/decline and your funnel can advance to upsells.
  • Keep the webhook configured as the backstop that completes any order where the customer never returns. Make sure your Breeze webhook URL is set and that the gateway’s Webhook Secret is saved in Spark CRM (see Payment Gateways).

In short: the webhook guarantees the order completes; Capture is what shows the customer the result right away. If you don’t have upsells or an on-screen confirmation to drive, you can rely on the webhook alone — but only if the Breeze gateway has a Webhook Secret saved in Spark CRM, since Spark CRM rejects any Breeze webhook it cannot verify with a 403. For a standard funnel, call Capture.


Subscriptions & Rebills

3D Secure applies to the initial customer purchase only. Once the first payment succeeds, Breeze saves a token for the card. All future rebills (subscription renewals) are merchant-initiated and process automatically with no redirect and no 3DS — you don’t need to do anything for them.

Spark CRM also automatically chains each rebill to the original authenticated payment (via the card network’s scheme transaction ID), which improves renewal approval rates and strengthens dispute defense — again, nothing to configure.

This is the same “authenticate once, then bill silently” model as PayPal reference transactions.


Sandbox Testing

With Test Mode enabled on the Breeze gateway (or a sk_test_ API key), use Breeze’s test cards:

Scenario Card number
Successful payment 4000020000000000
Failed payment 4024007181869214
3DS challenge 4010061700000021
  • Any future expiry date and any 3-digit CVV.
  • On the hosted 3DS challenge page, enter the sandbox password Checkout1!.

Troubleshooting

“This gateway requires 3D Secure…” (or Breeze “threeDs is required”)

Your checkout did not send the 3DS return URLs or the risk session:

  • Confirm you are passing payment.return_url and payment.cancel_url on Process Payment — for a Breeze card payment these are required. Spark CRM returns a 422 naming them when the order is routed straight to a Breeze gateway; when it is routed through a Payment Orchestrator you get Breeze’s own “threeDs is required” decline instead.
  • Confirm the Risk SDK is loaded and you are passing payment.risk_session_id.

Customer redirected but the order never completes

  • Make sure your return_url page calls Capture (POST /checkout/orders/capture) with the order_number.
  • Check that your Breeze webhook URL is configured in the Breeze dashboard and that the Breeze gateway in Spark CRM has a Webhook Secret saved (see Payment Gateways) — the webhook is the backup that completes the order, and without the secret Spark CRM rejects it with a 403.

“billingEmail, firstName, and lastName must be present”

Breeze requires the customer’s name and a valid email on the first card payment. Ensure the customer record has a first name, last name, and a valid email before processing.


Navigation

Type to search…

↑↓ navigate↵ selectEsc close