The online flow has three parts: create a payment on your server, collect it in the browser, and confirm the result from a webhook.
1. Create the payment (server-side)
curl https://payments.leffelconsulting.com/v1/payments/intents \
-H "X-Api-Key: lc_live_XXXXXXXXXXXXXXXXXXXX" \
-H "Idempotency-Key: order-10432" \
-H "Content-Type: application/json" \
-d '{
"amountCents": 4999,
"currency": "usd",
"orderRef": "10432"
}'
Omit paymentMethodTypes to enable automatic payment methods (cards, Apple Pay, Google Pay), or set
it explicitly, e.g. ["card"]. The response returns:
{
"lcPaymentId": "lcpay_9f2c4b1e8a7d4c0fb1e2a3d4c5b6a7f8",
"clientSecret": "pi_3AbC..._secret_xyz",
"status": "requires_payment_method",
"connectedAccountId": "acct_1Nvo...",
"publishableKey": "pk_live_..."
}
Store the lcPaymentId against your order. Send clientSecret, connectedAccountId, and
publishableKey to the browser.
2. Collect payment (browser)
Initialize Stripe.js on the merchant’s connected account and mount the Payment Element:
const stripe = Stripe(publishableKey, { stripeAccount: connectedAccountId });
const elements = stripe.elements({ clientSecret });
elements.create("payment").mount("#payment-element");
const { error } = await stripe.confirmPayment({
elements,
confirmParams: { return_url: "https://acme.com/order/complete" },
});
if (error) {
// Show error.message to the customer
}
3. Confirm and fulfill
Fulfill on the webhook, not the browser
The browser result tells you the confirmation was submitted — not that money moved. Fulfill the
order when you receive the payment_intent.succeeded
callback, or by polling GET /v1/payments/{id}
until status is succeeded.
curl https://payments.leffelconsulting.com/v1/payments/lcpay_9f2c... \
-H "X-Api-Key: lc_live_XXXXXXXXXXXXXXXXXXXX"
Related
- Authorize now, capture later — for ship-then-charge flows.
- ACH bank payments — lower fees, asynchronous settlement.
- Refunds — refund a completed payment.