FloPayFloPay
Guides

Pre-authorisation and capture

Reserve funds for an eligible card checkout, then capture the full amount from a trusted server when the order is ready.

Pre-authorisation and capture

Use manual capture when you need to confirm that a customer's funds are available at checkout but collect them only after stock or fulfilment is confirmed. Upgrade every FloPay SDK package used by the checkout to FloPay SDK 1.4.20 or later before opting in.

Authorised funds are not captured funds. An authorized result confirms a temporary hold; it is not payment and must not be recorded as revenue. Do not fulfil the order until capture succeeds and your integration receives item.purchased. Schedule capture or cancellation before authorizationExpiresAt.

If you omit captureMethod, or set captureMethod: 'automatic', immediate capture remains the default. FloPay uses the existing authorise-and-capture checkout behavior and a successful payment reports succeeded.

1. Create an authorisation-only checkout

Set captureMethod: 'manual' on an item-only card checkout. The option is supported by Node, browser, detached, inline, and React session creation.

Manual capture preserves the normal cardholder authentication journey. If the issuing bank requires 3-D Secure (3DS), the buyer completes that challenge before the SDK can return authorized. A decline or incomplete authentication never creates a usable authorisation.

import { FloPayCheckout } from '@flopay/react';

export function Checkout() {
  return (
    <FloPayCheckout
      createSession={{
        clientId: 'your-client-id',
        captureMethod: 'manual',
        currency: 'GBP',
        products: [{ code: 'order_123', quantity: 1 }],
        account: {
          userId: 'customer_123',
          email: 'customer@example.com',
        },
        successUrl: '/order/accepted',
        cancelUrl: '/checkout',
      }}
      onComplete={(result) => {
        if (result.status === 'authorized') {
          saveAuthorisationOnYourServer({
            paymentId: result.paymentId,
            sessionId: result.sessionId,
            authorizationExpiresAt: result.authorizationExpiresAt,
          });
        }
      }}
    />
  );
}

After any required cardholder authentication, the terminal SDK result is:

{
  status: 'authorized',
  paymentId: '3c54b6ac-7ad5-4e56-9c2c-5a80c2ef40d0',
  sessionId: 'fd4475e4-dc19-4439-b830-c9c8f67a35e7',
  authorizationExpiresAt: '2026-08-11T14:30:00.000Z',
}

Persist paymentId and authorizationExpiresAt with your order. The payment id is a FloPay UUID, not a provider PaymentIntent id.

Authorisation expiry

FloPay returns the provider-derived authorizationExpiresAt deadline for that payment. Do not hard-code a universal authorisation window: network, card, account, and provider rules can differ. Capture before the returned timestamp, allow operational margin for retries, and treat payment.authorization_expired as terminal.

If the order will not proceed, release the hold rather than waiting for expiry:

Client Basic authentication uses the client UUID as the username and an active user-owned API token as the password. The placeholder below represents that encoded clientUuid:apiToken pair.

PUT /v1/payments/{paymentId}/cancel
Authorization: Basic {base64(clientUuid:apiToken)}
Idempotency-Key: order_123-cancel
Content-Type: application/json

{}

2. Capture from a trusted server

When the order is ready to fulfil, call the merchant-authenticated API from trusted server code. Capture is intentionally not an SDK or browser operation.

PUT /v1/payments/{paymentId}/capture
Authorization: Basic {base64(clientUuid:apiToken)}
Idempotency-Key: order_123-full-capture
Content-Type: application/json

{}

Use the paymentId returned by the authorised checkout. A successful response is the payment resource with status: 'succeeded'; that is FloPay's captured and paid state.

Keep one stable, nonblank Idempotency-Key for this logical capture. If the response is lost or times out, retry the same request body with the same key. Do not create a fresh key for an uncertain outcome.

If capture fails, FloPay returns 502 Bad Gateway and emits payment.capture_failed. No payment is collected, and the authorisation remains inspectable. Keep the order unfulfilled, re-read the payment, then decide whether to retry the same request with the same key or cancel the hold. See the error table.

Fulfil only after capture

For this item-only flow, treat item.purchased as the canonical fulfilment event. FloPay emits it only after the full capture reaches the existing successful-purchase path. There is deliberately no separate payment.captured event. Make your webhook handler idempotent and deduplicate deliveries by eventId.

Supported boundary

The first release supports one later capture for the full amount of an eligible one-time card checkout.

CapabilityAvailability
Immediate card captureSupported and the default
One later full card captureSupported with captureMethod: 'manual'
Partial captureUnsupported
Incremental authorisationUnsupported
Multiple capturesUnsupported
Subscription captureUnsupported
Non-card capture, including PayPal and alternative payment methodsUnsupported
Dashboard capture as an integration workflowUnsupported; use the trusted-server API

Do not use checkoutMode (full, confirm, or auto) to select capture behavior. It controls checkout presentation and saved-method behavior; only captureMethod selects immediate or manual capture.

On this page