Capture
Capture an authorized payment to charge the customer. By default, payments use auto-capture — authorization and capture happen in a single step. Use manual capture when you need to authorize first and charge later.
When to use manual capture
Manual capture is useful when the final charge amount may differ from the authorization, or when you want to delay the charge until fulfillment:
- Hotels and rentals — authorize at booking, capture at checkout with the final amount.
- Pre-orders — hold funds now, charge when the item ships.
- Marketplace holds — authorize when the buyer commits, capture after the seller confirms.
- Custom or made-to-order goods — authorize upfront, capture when production is complete.
How it works
- Set
captureMethodto"manual"when creating the payment or checkout session. - The payment reaches
requires_capturestatus — funds are held on the customer's card. - Call
POST /v1/payments/{id}/captureto charge the held amount. - On success the payment moves to
captured. If the provider rejects the capture, the payment transitions tofailed— check theerrorobject for the reason.
If you decide not to charge, call POST /v1/payments/{id}/cancel instead. See Cancel / Void.
Create a payment with manual capture
When creating the payment, include captureMethod: "manual":
{
"amount": { "currency": "USD", "valueMinor": 15000 },
"merchantReference": "order-5678",
"captureMethod": "manual",
"paymentMethod": { ... }
}The same field works on checkout sessions:
{
"amount": { "currency": "USD", "valueMinor": 15000 },
"lineItems": [ ... ],
"merchantReference": "order-5678",
"successUrl": "https://your-site.com/success",
"cancelUrl": "https://your-site.com/cancel",
"captureMethod": "manual"
}Capture the payment
Once the payment is in requires_capture status, call capture to charge the customer.
Full capture
By default, capture charges the full authorized amount. Send an empty body:
curl -X POST https://api.miracle.com/v1/payments/pay_abc123/capture \
-H "Authorization: Bearer sk_test_your_secret_key" \
-H "Idempotency-Key: capture-order-5678"const response = await fetch('https://api.miracle.com/v1/payments/pay_abc123/capture', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_your_secret_key',
'Idempotency-Key': 'capture-order-5678',
},
});
const result = await response.json();
if (!response.ok) {
// Capture was rejected — inspect the error
console.error(result.error.code, result.error.message);
} else {
const { data: payment } = result;
// payment.status === 'captured'
}The response returns the updated Payment object with status: "captured".
Partial capture
To capture less than the authorized amount, pass an amount in the request body. The remaining held amount is released automatically.
curl -X POST https://api.miracle.com/v1/payments/pay_abc123/capture \
-H "Authorization: Bearer sk_test_your_secret_key" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: capture-order-5678-partial" \
-d '{
"amount": {
"currency": "USD",
"valueMinor": 12000
}
}'const response = await fetch('https://api.miracle.com/v1/payments/pay_abc123/capture', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_your_secret_key',
'Content-Type': 'application/json',
'Idempotency-Key': 'capture-order-5678-partial',
},
body: JSON.stringify({
amount: {
currency: 'USD',
valueMinor: 12000,
},
}),
});
const { data: payment } = await response.json();
// payment.status === 'captured'
// Captured $120.00 out of $150.00 authorized. $30.00 released.Only a single capture is supported per payment. After capture, any remaining authorized amount is released.
The capture amount must not exceed the original authorization amount. Requests that exceed it are rejected with a validation error.
Authorization validity
Card authorizations expire — typically 7 days, though the exact window varies by card network and issuing bank. If you do not capture or cancel within this window:
- The authorization hold is released automatically by the issuing bank.
- The payment transitions to
canceledstatus. - You receive a
payment.canceledwebhook.
Do not rely on the authorization hold lasting the full 7 days. Some issuers release holds earlier. Capture as soon as you are ready to charge.
Webhook
A successful capture triggers the payment.captured webhook event:
{
"id": "evt_xyz789",
"type": "payment.captured",
"data": {
"id": "pay_abc123",
"tenantId": "ten_...",
"capturedAmount": {
"currency": "USD",
"valueMinor": 12000
}
},
"occurredAt": "2026-04-09T14:30:00Z"
}Related
- Payment Lifecycle — full status flow and auto vs manual capture
- Cancel / Void — release an authorization without charging
- Refunds — return funds after capture
- Idempotency — safe retries for capture calls