# Idempotency

Network calls fail. When you retry a request, you must not create a second payment or a
second refund. Paymee makes both safe to retry:

- **Session creation** is idempotent through your **`merchant_reference`**.
- **Refunds** are idempotent through the **`Idempotency-Key`** header — see
  [Refunds](/guides/refunds/#retrying-safely-idempotency-key).

## Session creation

`merchant_reference` is your unique identifier for a payment (an order id, a cart id, an
invoice number — whatever is stable on your side). It is unique per merchant account,
separately in test and live mode.

- The **first** request with a given `merchant_reference` creates the session and
  returns `201 Created`.
- A **later** request with the **same** `merchant_reference`, **`amount`** and
  **`currency`** returns the **existing** session with `200 OK` — no duplicate is
  created, even when the two requests arrive at the same moment.
- The same `merchant_reference` with a **different `amount` or `currency`** is refused
  with `409 Conflict` (`type` `conflict`); the problem document's
  `existing_session_id` names the session that already uses it.

```bash
# First call → 201 Created, new session
curl https://api.paymee.online/api/v1/gateway/sessions/ \
  -H "Authorization: Bearer sk_live_…" -H "Content-Type: application/json" \
  -d '{ "amount": "10.500", "merchant_reference": "order-0001", "first_name": "Aymen", "last_name": "Ben Salah", "email": "aymen@example.com" }'

# Same merchant_reference, amount and currency → 200 OK, the same session
```

Only `amount` and `currency` are compared. Any other field of a repeated request (buyer,
URLs, `description`, `items`, `metadata`, `max_attempts`) is **ignored**: you get the
original session, as it was created. To change those, create a new session with a new
`merchant_reference`.

### What a repeated request returns

| The existing session is… | You get |
| --- | --- |
| Still payable (`CREATED`, `PROCESSING`, `PENDING`) | The session with a working `checkout_url`: the current link, or a fresh one if it had expired. |
| Final (`SUCCEEDED`, `FAILED`, `EXPIRED`, `CANCELED`) | The session with `checkout_url: null`: there is nothing left to pay. |

So repeating the request is also how you get a fresh link for a buyer who let theirs
expire.

## Guidelines

- **Generate `merchant_reference` once per order**, before the first attempt, and reuse
  it on every retry of that order.
- Use a **new** `merchant_reference` only when you genuinely want a new payment — for
  example after `session.failed` or `session.expired`, when the buyer pays again.
- For refunds, generate one `Idempotency-Key` per refund and reuse it on every retry of
  that refund.

:::tip
With these, you can retry on timeouts, `429` and `500` responses without risking a double
charge or a double refund.
:::

Source: https://docs.paymee.online/guides/idempotency/
