Advanced payment capture strategies with Commerce Layer.
Payment capture isn’t just a final step. Learn how authorization and capture work in Commerce Layer, explore capture strategies, and configure flows that match real-world fulfillment.
Payment capture is one of those topics that sounds simple, until it isn't. Most developers assume it's just the last step of a transaction — you authorize, then you capture. Done. But in practice, the moment you start dealing with real-world fulfillment workflows, multiple markets, mixed payment gateways, and operational edge cases, how and when you capture money becomes one of the most consequential decisions in your commerce architecture.
This article explains what capture really is, why Commerce Layer treats it as a first-class concern, and how to configure it correctly for different business scenarios.
Authorization vs. capture: a quick primer
When a customer checks out, two distinct things happen at the payment level:
- Authorization — the payment gateway verifies the card and reserves the funds. The money hasn't moved yet, it's just been earmarked.
- Capture — the actual movement of money. This is when the funds are transferred from the customer's account to the merchant.
Most platforms collapse these two steps into one. That makes things simple for basic use cases but creates serious problems the moment your operations get more complex. What if you need to ship in multiple shipments? What if you want to charge only when the goods leave the warehouse? What if an item goes out of stock after authorization?
Commerce Layer keeps these two steps explicitly separate, giving you full control over when money moves.
Capture modes
In Commerce Layer, you configure capture behavior at the payment method level. There are three built-in patterns to know, plus a fourth — webhook-driven — for teams that need custom logic in between:
- Manual (the default)
- Automatic
- Delayed (capture after fulfillment starts)
- Webhook-driven (custom logic before capture)
Manual capture
By default, Commerce Layer requires payments to be captured before an order's fulfillment can begin. Once an order is approved, its payment status is authorized. The order stays in this state until you explicitly trigger the capture — via the Dashboard, the API, or an automated flow.
This is the right approach for merchants who want strict control: you approve the order, confirm stock, then capture when you're ready to ship.
To start a capture manually, you need to patch the related authorization and pass the _capture trigger attribute:
curl -g -X PATCH \
'https://yourdomain.commercelayer.io/api/authorizations/:id' \
-H 'Accept: application/vnd.api+json' \
-H 'Content-Type: application/vnd.api+json' \
-H 'Authorization: Bearer your-access-token' \
-d '{
"data": {
"type": "authorizations",
"id": "your-authorization-id",
"attributes": {
"_capture": true
}
}
}'
On success, Commerce Layer creates a capture transaction and updates the order's payment status to paid. At that point, fulfillment can proceed.
Auto-capture
Set auto_capture to true on the payment method and Commerce Layer will automatically capture the payment immediately after a successful authorization. The order's payment status moves straight to paid without any manual intervention.
curl -g -X PATCH \
'http://yourdomain.commercelayer.io/api/payment_methods/:id' \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer your-access-token' \
-H 'Content-Type: application/vnd.api+json' \
-d '{
"data": {
"type": "payment_methods",
"id": "your-payment-method-id",
"attributes": {
"auto_capture": true
}
}
}'
Auto-capture is particularly useful for:
- Digital products or instant-delivery use cases where fulfillment happens immediately.
- Payment gateways that don't support a separate authorization/capture flow.
- High-volume, low-risk scenarios where operational simplicity is more valuable than granular control.
You can also combine it with auto_capture_max_amount_cents to enable auto-capture only for smaller orders, while routing higher-value orders through a manual approval workflow.
Delayed capture
The third option is almost the inverse of the default: set require_capture to false on the payment method, and Commerce Layer will allow fulfillment to begin even when the payment hasn't been captured yet.
curl -g -X PATCH \
'http://yourdomain.commercelayer.io/api/payment_methods/:id' \
-H 'Accept: application/vnd.api+json' \
-H 'Authorization: Bearer your-access-token' \
-H 'Content-Type: application/vnd.api+json' \
-d '{
"data": {
"type": "payment_methods",
"id": "your-payment-method-id",
"attributes": {
"require_capture": false
}
}
}'
This is useful when your warehouse operations kick off immediately upon order approval, but you want to capture funds only when items are actually being shipped. It decouples your operational flow from your financial flow — a common requirement in B2B or subscription scenarios.
Webhook-driven capture
Sometimes none of the three built-in modes is enough. You want something in between: capture should happen automatically, but only after your own logic has run — fraud scoring, inventory checks, customer tier validation, ERP sync, you name it.
This is where Commerce Layer's webhook system shines:
- Subscribe to the
orders.placeevent. - Receive a
POSTrequest at your callback URL the moment an order is placed and run whatever logic you need. - Trigger the capture yourself via the API.
Step 1 • Register a webhook for order's placement
Create a webhook for the orders.place event and include the resources you may need:
curl -g -X POST \
'https://yourdomain.commercelayer.io/api/webhooks' \
-H 'Accept: application/vnd.api+json' \
-H 'Content-Type: application/vnd.api+json' \
-H 'Authorization: Bearer your-access-token' \
-d '{
"data": {
"type": "webhooks",
"attributes": {
"name": "capture-on-order-place",
"topic": "orders.place",
"callback_url": "https://yourapp.com/webhooks/capture",
"include_resources": [ "payment_source", "billing_address", "customer" ]
}
}
}'
Step 2 • Handle the callback and run your custom logic
Your endpoint receives a POST request from Commerce Layer with the order payload. Verify the request using the shared secret returned at webhook creation time (passed as the X-CommerceLayer-Signature header), then run your logic:
app.post('/webhooks/capture', async (req, res) => {
// Verify the webhook signature
const signature = req.headers['x-commercelayer-signature']
if (!verifySignature(signature, req.body, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Unauthorized')
}
const order = req.body.data
const authorizationId = order.relationships.payment_source?.data?.id
// Run your custom logic before deciding to capture
const fraudScore = await checkFraudScore(order)
const stockOk = await confirmInventory(order)
if (fraudScore > 80 || !stockOk) {
// Flag for manual review instead of capturing
await flagOrderForReview(order.id)
return res.sendStatus(200)
}
// All checks passed — trigger the capture
await captureAuthorization(authorizationId)
res.sendStatus(200)
})
Step 3 • Trigger the capture via the API
Once your checks pass, call the Commerce Layer API to manually capture the authorization, as explained above.
Webhook implementation notes
This pattern gives you the best of both worlds: automated capture with full programmatic control over when and whether it happens. By the way, when following it, there are a few things to keep in mind:
- Your callback must respond with a
2xxwithin Commerce Layer's timeout window. For heavy logic, respond immediately with200and process the capture asynchronously in a background job. - Commerce Layer uses a circuit breaker on webhooks: too many consecutive failures will disable the webhook. Make sure your callback is resilient.
- If an
orders.placeevent is missed or your server is briefly down, you can force it to re-fire by patching the event resource with_trigger: true.
What happens when a capture gets stuck
Real-world payment infrastructure isn't perfectly reliable. A capture might succeed at the gateway level but fail to register on the Commerce Layer side — leaving the order in a limbo state.
Commerce Layer handles this with the _forward trigger attribute on the capture resource. If you know the capture succeeded on the gateway but is stuck on your platform, you can unblock it as follows:
curl -g -X PATCH \
'https://yourdomain.commercelayer.io/api/captures/:id' \
-H 'Accept: application/vnd.api+json' \
-H 'Content-Type: application/vnd.api+json' \
-H 'Authorization: Bearer your-access-token' \
-d '{
"data": {
"type": "captures",
"id": "your-capture-id",
"attributes": {
"_forward": true
}
}
}'
There's also an amount mismatch scenario: if a capture succeeds while an order is still pending, and the order is later edited (changing the total), you can reset the transaction using the _cancel trigger on the capture.
Capture and refunds
Once a payment is captured, it can be refunded — either fully or partially. A partial refund changes the order's payment status to partially_refunded. A full refund eventually cancels the order and sets the status to refunded.
The capture resource exposes refund_amount_cents and refund_balance_cents, giving you a precise view of how much has been refunded and how much refundable balance remains.
Choosing the right capture strategy
Here's a quick decision guide:
Scenario | Recommended approach |
|---|---|
Physical goods, warehouse-dependent fulfillment | Manual capture — hold authorization until ready to ship. |
Digital goods or instant delivery | Auto-capture — simplify the flow. |
Large orders needing financial review | Manual capture with approval workflow. |
High volume, low-risk orders | Auto-capture with max amount threshold. |
B2B or "ship now, charge later" | Delayed capture. |
Custom fraud checks, inventory validation, ERP sync before capture | Webhook-driven capture on order's placement. |
The bigger picture
Capture behavior is rarely just a developer concern. It affects cash flow, customer communication, fraud risk, and how operations teams interact with orders every day. Getting it right means understanding both the technical levers and the business context they operate in.
Commerce Layer's approach — separating authorization and capture as distinct, configurable steps — reflects how payments actually work in serious commerce operations. The flexibility to configure this per payment method, per market, and per order type means you're not locked into a one-size-fits-all approach.
If you're building on Commerce Layer, take the time to think through your capture strategy early. It's one of those decisions that's easy to overlook and expensive to fix once orders start flowing.