> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dimepayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Retrying Safely

> Send an Idempotency-Key so a charge or refund that timed out can be retried without moving money twice.

## Why it matters

A charge or refund that times out on your side may still have gone through. Without a way to tell, a retry can charge or refund the customer twice.

Send an `Idempotency-Key` header with each request that moves money. If you retry with the same key, the API returns the first answer and doesn't process the request again.

## Which endpoints take it

| Endpoint | |
| - | - |
| `POST /api/transaction/charge-card` | Charge a card |
| `POST /api/transaction/charge-card-token` | Charge a saved card |
| `POST /api/transaction/charge-ach` | Charge a bank account |
| `POST /api/transaction/authorize` | Place a hold. See [Authorize and Capture](/guides/authorize-capture) |
| `POST /api/transaction/capture` | Capture a hold |
| `POST /api/transaction/refund` | Refund |
| `PATCH /api/transaction/void` | Void |

The header is optional. Without it, each request runs exactly as it always has.

<Note>
  Held-funds releases use an `idempotency_key` field in the request body instead of this header. See [Held Funds](/guides/held-funds#idempotency-keys).
</Note>

## Sending a key

```bash theme={null}
curl --request POST \
  --url https://app.dimepayments.com/api/transaction/charge-card-token \
  --header 'Authorization: Bearer your-api-token' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: order-1234-charge' \
  --data '{
    "data": {
      "sid": 1234567,
      "amount": 49.99,
      "token": "abc123def456",
      "first_name": "Jane",
      "last_name": "Doe",
      "phone": "+17701234567",
      "memo": "order 1234"
    }
  }'
```

* **Use a new key for each payment you intend to make**, such as your order ID plus the action (`order-1234-charge`, `order-1234-refund-1`). A random UUID works too.
* **Reuse the same key when you retry that payment.**
* Keys are 1 to 255 printable ASCII characters.
* Keys belong to your API account, so they don't clash with another integrator's. They still work after you rotate a token.
* Keys are kept for **7 days**. After that, the same key is treated as new.

## What a retry gets back

| Situation | Response |
| - | - |
| Same key, same request | The original response, status code included, with the header `Idempotent-Replayed: true`. Nothing is processed again |
| Same key, different request (another body or another endpoint) | `422`. Nothing is processed |
| Same key, while the first request is still running | `409`. Wait a moment and retry with the same key |
| A key that isn't 1 to 255 printable characters | `400` |

"Same request" means the same endpoint and the same JSON body. Key order in the body doesn't matter.

**Declines and errors are replayed too.** If the first request was declined, or failed after it reached the card network, the retry gets that same answer. It won't be sent again, because a request that failed partway may still have charged. To try a declined card again, use a new key.

**Refusals before processing free the key.** If the request was refused before anything was processed, the key isn't kept, and you can fix the request and send it again with the same key. That covers a validation error (an `errors` object), `401`, `403` and `429`.

### If a `409` doesn't go away

A request that dies before answering leaves its key in progress until the key expires. If the `409` persists, check the [transaction list](/api-reference) to see whether the payment went through. Only retry with a **new** key if it didn't.

## Errors

| Status | Message |
| - | - |
| `400` | `The Idempotency-Key header must be 1 to 255 printable characters.` (in `errors.Idempotency-Key`) |
| `409` | `A request with this Idempotency-Key is still in progress, or did not finish. Try again shortly; if this persists, check the transaction list before retrying with a new key.` |
| `422` | `This Idempotency-Key was already used for a different request. Use a new key for each new request.` |

## SDKs

The SDKs send a key on all seven calls. If you don't pass one, they generate a key per call and reuse it for their own automatic retries. Pass your own key to make retries safe across process restarts too. A refused key throws `IdempotencyException`.

| SDK | Version | Pass a key |
| - | - | - |
| [PHP](/guides/sdks/php) | 1.4.0+ | `idempotencyKey: 'order-1234'` (named argument) |
| [JavaScript](/guides/sdks/javascript) | 1.5.0+ | `{ idempotencyKey: 'order-1234' }` (last argument) |
| [Python](/guides/sdks/python) | 1.5.0+ | `idempotency_key='order-1234'` |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.