---
title: "Idempotent requests"
description: "Retry QuotWay API POSTs safely with the Idempotency-Key header: replays, 24-hour window, and the 409 and 422 cases."
url: "https://www.quotway.com/ja/docs/api/idempotency"
type: "documentation"
category: "api"
updated: "2026-09-30"
locale: "ja"
source: "QuotWay - B2B Quote & Negotiation App for Shopify"
---

# Idempotent requests

**Read time:** 4 minutes.
**Who it's for:** Developers who need retries to be safe - so a timeout never creates two quotes,
two messages or two proposal versions.

## How do I make a POST safe to retry?

Send an `Idempotency-Key` header with every `POST`. QuotWay follows the IETF
`Idempotency-Key` draft:

```bash
curl https://api.quotway.com/v1/quotes/clz8k2x9f0001qw7h3m4n5p6r/messages \
  -H "Authorization: Bearer $QUOTWAY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0b8f6c1e-2a47-4c9d-8e3f-5a6b7c8d9e0f" \
  -d '{"body": "Thanks — revised pricing is on its way."}'
```

The header is optional but strongly recommended on all four POST endpoints: create a quote, post a
message, send a proposal and create a webhook endpoint. It's ignored on `GET` and `DELETE`, which
are already safe to repeat.

## What happens when I retry?

| Situation | Response |
|---|---|
| First request with a key | Runs normally; the response is stored. |
| Same key, **same** request, first one finished | The **stored response is replayed** - same status, same body - with the header `Idempotent-Replayed: true`. Nothing runs twice. |
| Same key, same request, first one **still running** | `409` [`idempotency_key_in_use`](/docs/api/errors#idempotency_key_in_use), usually with `Retry-After: 2`. Retry shortly. |
| Same key, **different** request | `422` [`idempotency_key_reused`](/docs/api/errors#idempotency_key_reused). |
| Key isn't 1–255 printable ASCII characters | `400` [`invalid_idempotency_key`](/docs/api/errors#invalid_idempotency_key). |

"Same request" means the same method, path and JSON body. Key order and whitespace in the body
don't matter; values do.

A replayed body is exactly the original - including its `request_id` - while the response headers
(`X-Request-Id`, rate-limit headers) belong to the new request.

## Which responses are stored?

- **Successes and `4xx` errors are stored** and replayed. If your request failed validation, fix it
  and send it with a **new** key - re-using the old key replays the old error (or, with a changed
  body, returns `422`).
- **`5xx` errors are not stored.** The key is released, so retrying with the same key really runs
  the request again. That's the case idempotency exists for.

## How long do keys last?

Keys are remembered for **24 hours**, and are scoped to the **API key** that sent them - two
different API keys can use the same idempotency key without colliding.

If a request never finishes (for example the server was interrupted mid-request), its key is
released after **5 minutes**, so a retry with the same key runs again instead of getting `409`
for the rest of the day.

## Rules of thumb

- Generate a fresh UUID v4 for each logical operation, store it with the operation, and re-use it
  only for retries of that operation.
- **Never re-use a key for a different operation**, even after 24 hours. For `POST /v1/quotes`
  in particular, the idempotency key is also recorded on the quote itself: re-sending an old key
  from the same API key returns the quote it originally created rather than creating a new one.
- Retry `5xx` responses and network timeouts with the same key and exponential backoff.
- Rolling an API key starts a new namespace - finish any in-flight retries before you switch to the
  new key.

## Related

- [Create quotes](/docs/api/create-quotes)
- [Messages and proposals](/docs/api/messages-and-proposals)
- [Errors](/docs/api/errors)
