# Razorpay payment already captured error on a second capture call

## TL;DR
Razorpay payments can only be captured once; a second capture call always errors. Check the payment status with a fetch call before capturing, and treat "already captured" as success for your order state, not as a failure. Make your capture path idempotent so retries and double webhook deliveries cannot break it.

```text
razorpay payment already captured error on a second capture call
```

## Steps

1. Before every capture call, fetch the payment and check its status. Only call capture when the status is authorized. Success check: your code never calls capture on a payment that is already captured.

2. Handle the "already captured" error explicitly: when you receive it, fetch the payment to confirm the captured status and amount, then mark your order paid. Success check: the error path ends in "order paid," not in an error state.

3. Add idempotency to your capture flow: record that a capture was attempted for the payment id, and skip re-capture if the record exists. Success check: two rapid capture attempts produce one capture and one clean skip.

4. Dedupe the triggers: webhooks, cron jobs, and manual admin actions can all fire capture for the same payment. Funnel them through one capture function with the status check from step 1. Success check: only one code path can call capture.

5. Reconcile amounts: confirm the captured amount matches your order total before fulfilling. Success check: fulfillment only runs when captured amount equals the order amount.

## When this applies

- Razorpay returns a "payment already captured" style error on your capture call.
- Your flow captures in a webhook handler, a job, or an admin action that can run twice.
- An agent built the capture logic without a status check.

## When it doesn't

- The payment failed authorization; there is nothing to capture.
- Order-id mismatch errors; the payment is tied to the wrong order.
- Refunds; those are a separate flow on captured payments.

## Tool + version compatibility

Razorpay Payments API (Orders API with manual capture), Razorpay webhooks, all current server SDKs.

### "razorpay capture already captured"
Same error. Treat it as confirmation, not failure.

### "razorpay double capture error"
The fix is the pre-capture status check plus a single capture path.

### "razorpay payment capture idempotency"
Razorpay capture is not naturally idempotent; your status check provides the idempotency.

## Why it happens

Razorpay separates authorization from capture: money is authorized at payment time and only moves on capture. Capture is a one-way state transition, so the second call has nothing to do and errors. Agent-built flows commonly call capture from both the success handler and a webhook handler (or retry it on timeout), and the second call hits the already-captured state.

## Edge cases / pitfalls

- A capture call that times out may still have succeeded; always fetch status before deciding to retry, or you will manufacture this exact error.
- Partial captures complicate the status check; if you use them, track captured amounts yourself.
- Authorized payments expire if never captured; a status of authorized on an old payment may need a fresh authorization, not a capture.
- Never treat "already captured" as a reason to refund; it means the money is correctly collected.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_gnfBivGswkRWe2x9S05VIQ
