# Idempotency

Retries improve reliability, but they introduce a new challenge - **what happens if the original request actually succeeded, but the response was never received?**

Without idempotency, retrying a request could accidentally execute the same operation multiple times.

For example:

- Charging a customer twice
- Creating duplicate invoices
- Sending the same email multiple times
- Creating multiple GitHub issues
- Provisioning duplicate cloud resources

To prevent this, Swytchcode supports **automatic idempotency-key injection** for supported integrations. It's opt-in per integration - see [Configuring Idempotency](#configuring-idempotency) below - but once enabled, key generation and reuse across retries is handled for you.

---

## Why Idempotency Matters

Imagine an AI agent creating a payment.

```text
Create Payment
        │
        ▼
 Provider receives request
        │
        ▼
Network connection lost
        │
        ▼
Client never receives response
```

At this point, your application doesn't know whether:

- the provider never received the request, or
- the provider successfully completed the request but the response was lost.

If the client retries blindly, the payment could be processed twice.

---

## The Problem Without Idempotency

```text
Attempt 1

↓

Payment Created

↓

Network Failure

↓

Retry

↓

Second Payment Created ❌
```

Even though the retry was caused by a network failure, the provider receives two independent requests.

---

## How Swytchcode Solves This

For supported providers with idempotency enabled (`execution_policy.idempotency.mode: "dynamic"` in `manifest.json`), Swytchcode automatically attaches an **idempotency key** to mutating API requests.

```text
Create Payment
        │
        ▼
Idempotency-Key:
b7fd8a91...
        │
        ▼
Provider API
```

If the request is retried, the **same idempotency key** is sent again.

The provider recognizes that it has already processed a request with that key and returns the original result instead of executing the operation again.

---

## Retry Flow with Idempotency

```text
Request

↓

Attach Idempotency Key

↓

Provider

↓

Network Failure

↓

Retry

↓

Same Idempotency Key

↓

Provider Returns Previous Result

↓

No Duplicate Operation
```

This makes retries safe even when the client cannot determine whether the previous request succeeded.

---

## When Is Idempotency Used?

Idempotency is most valuable for **mutating operations**.

Examples include:

- Creating payments
- Charging cards
- Creating invoices
- Creating subscriptions
- Sending emails
- Creating repositories
- Creating cloud infrastructure

Read-only operations such as `GET` requests generally do not require idempotency.

---

## Idempotency Modes

Idempotency is **off by default** (`mode: "none"`) - Swytchcode does not attach an idempotency key to any request unless you turn it on for that integration's `execution_policy`. Once enabled (`mode: "dynamic"`), the `scope` setting controls how the key is generated:

### Call Scope

A unique idempotency key is generated for every API call.

```text
Call

↓

Generate Unique Key

↓

Execute Once
```

This is the default `scope` once idempotency is enabled - each individual `exec` call gets its own key, so a retry of that same call reuses it, but a second, unrelated call gets a new one.

---

### Workflow Scope

For multi-step workflows, the idempotency key can remain stable across the workflow execution.

```text
Workflow

↓

Step 1

↓

Step 2

↓

Retry

↓

Continue Using Same Key
```

This prevents partially completed workflows from executing duplicate operations if one step needs to be retried.

---

## Configuring Idempotency

Idempotency is configured in the `execution_policy` section of `manifest.json`.

```json
{
  "execution_policy": {
    "idempotency": {
      "mode": "dynamic",
      "header_name": "Idempotency-Key",
      "scope": "workflow"
    }
  }
}
```

Every field is optional.

If omitted, Swytchcode uses the default configuration.

---

## Default Configuration

| Field | Default |
|--------|---------|
| `mode` | `"none"` |
| `header_name` | `"Idempotency-Key"` |
| `scope` | `"call"` |

---

## How It Works with Retries

Retries and idempotency work together.

```text
Execute Request
        │
        ▼
Attach Idempotency Key
        │
        ▼
Send Request
        │
        ▼
Temporary Failure
        │
        ▼
Retry
        │
        ▼
Reuse Same Idempotency Key
        │
        ▼
Provider Returns Original Result
```

Retries improve reliability.

Idempotency guarantees that those retries remain safe.

---

## Best Practices

- Enable idempotency for mutating APIs.
- Use workflow scope for multi-step workflows.
- Never generate a new idempotency key during a retry.
- Combine idempotency with retries for production workloads.
- Test retry scenarios in sandbox environments before deploying to production.

---

## Related guides

- [Retries](https://docs.swytchcode.com/guides/retries/) - Learn which failures Swytchcode retries automatically, and retry conditions and budgets.
- [Execution Pipeline](https://docs.swytchcode.com/guides/execution-pipeline/) - See the complete runtime flow, from validation to API execution.
- [Policy Rules](https://docs.swytchcode.com/policies/policy-rules/) - Design safe retry and idempotency behavior with runtime guard policies.
