Idempotency
Learn how to safely retry mutations using the Idempotency-Key header to prevent duplicate side effects
When network failures or timeouts occur, retrying a mutation can accidentally create duplicate side effects — for example, creating the same item twice. The Idempotency-Key header lets you safely retry mutations without worrying about duplicates.
How it works
Send a unique Idempotency-Key header with any mutation request. The API uses this key to deduplicate retries:
- First request: Executes normally and caches the response for 30 minutes.
- Retry with same key: Returns the cached response with an
Idempotency-Replayed: trueheader — no duplicate side effect occurs. - Concurrent duplicate: Returns
409 Conflictwith aRetry-Afterheader indicating when to retry.
Best practiceAlways include an
Idempotency-Keyheader when retrying mutations in production, especially for operations likecreate_item,create_board, or any mutation that creates or modifies resources.
Using the Idempotency-Key header
Idempotency-Key headerInclude a unique string value (e.g., a UUID) in the Idempotency-Key request header:
fetch("https://api.monday.com/v2", {
method: "post",
headers: {
"Content-Type": "application/json",
"Authorization": "{API_TOKEN}",
"API-Version": "2025-07",
"Idempotency-Key": "YOUR_UNIQUE_IDEMPOTENCY_KEY"
},
body: JSON.stringify({
query: `mutation { create_item(board_id: 123456, item_name: "New item") { id } }`
})
});curl -X POST 'https://api.monday.com/v2' \
-H "Authorization: {API_TOKEN}" \
-H "Content-Type:application/json" \
-H "API-Version:2025-07" \
-H "Idempotency-Key:YOUR_UNIQUE_IDEMPOTENCY_KEY" \
--data-raw '{"query":"mutation { create_item(board_id: 123456, item_name: \"New item\") { id } }"}'Response headers
| Header | Description |
|---|---|
Idempotency-Replayed | Set to true when the response is served from cache (i.e., this is a replayed retry, not a fresh execution). |
Rules and constraints
| Rule | Detail |
|---|---|
| Mutations only | The header is ignored on queries (reads are inherently idempotent). |
| POST only | Only applies to POST requests. |
| Cache duration | Cached responses expire after 30 minutes. After expiration, the same key will execute fresh. |
| Key format | Any non-empty string. We recommend UUIDs. |
| Per-user budget | Each user+app combination has a memory budget for cached responses. If the budget is exceeded, new responses will execute but won't be cached for replay. |
| Max response size | Responses larger than 1 MB are not cached. |
Error responses
409 — Concurrent duplicate
If a request with the same idempotency key is already being processed, the API returns:
{
"errors": [
{
"message": "A request with this idempotency key is currently being processed",
"extensions": {
"code": "IDEMPOTENCY_CONFLICT"
}
}
]
}The response includes a Retry-After header. Wait the indicated time and retry — the cached response will then be available.
When to use idempotency keys
| Scenario | Use idempotency key? |
|---|---|
| Retrying after a network timeout | ✅ Yes |
| Retrying after a 5xx server error | ✅ Yes |
| Retrying after a rate limit (429) | ❌ No — the original request wasn't processed, so no duplicate risk. |
| Automated/webhook-triggered mutations | ✅ Yes — derive the key from the triggering event ID. |
| Batch imports | ✅ Yes — use a per-record key to allow safe resume after partial failure. |
Generating idempotency keys
Good keys are:
- Unique per intended operation — a UUID generated at the first attempt, reused on retries.
- Deterministic for the same intent — if retrying, send the same key; don't generate a new one.
Examples:
uuid()— generated once when the user clicks "Create", reused on retries.${webhookEventId}-create-item— for webhook-driven automations.${importBatchId}-row-${rowIndex}— for batch imports.
WarningDo not generate a new key on every retry attempt. The key must remain the same across retries for deduplication to work. Store the key alongside the request so retries use the same value.
Updated about 2 hours ago
