# Idempotency keys

Increase's APIs include an optional creation parameter called the `Idempotency-Key`. This string parameter should be a unique value you pre-allocate in your system _before_ invoking the creation method. For example, you could use your application's Invoice ID for an [ACH Transfer](/documentation/api/ach-transfers) or your application's User ID for an [Entity](/documentation/api/entities).

We recommend setting the value for all POST requests. The value should be transmitted as the HTTP header `Idempotency-Key`. Idempotency keys can be up to 200 characters long.

You cannot re-use an `Idempotency-Key` across two objects—passing `Idempotency-Key` guarantees that at most one object is created per key. If Increase receives a second request with the same arguments and `Idempotency-Key`, we will return the object created during the first request and set an HTTP response header `Idempotent-Replayed` to the value `true`.

Attempting to create a second, different, object with an already used `Idempotency-Key` will result in an HTTP 409 Conflict error with the `type` field set to `idempotency_key_already_used_error` and the `resource_id` set to the ID of the Object that is associated with that key.

Idempotency keys are only used for `POST` requests. `PATCH`, `GET`, and `DELETE` endpoints are inherently idempotent.

You can retrieve objects by their `Idempotency-Key`, too. Each list endpoint has an optional filter parameter `idempotency_key`. Passing an `idempotency_key` there will return an empty list, if that key is unused, or a list containing exactly one matching result.

## Recovering from errors

You can use the `Idempotency-Key` header to automatically and safely retry ephemeral errors. As long as the `Idempotency-Key` is set to the same value and the request is valid, we will eventually return a successful object to you. We recommend building support for automatic retries, especially for important endpoints like transfer creation.

We do not recommend building automatic solutions using reads of the list endpoint: instead retry your requests with the same parameters and the same `Idempotency-Key` and rely on idempotency to eventually deliver you a successful response.

## Examples

On the first successful request, Increase creates the Account Transfer.

```curl
curl -X POST https://api.increase.com/account_transfers
  -H "Idempotency-Key: test_001"
  -d $'{
      "account_id": "account_1",
      "destination_account_id": "account_2",
      "description": "My great transfer!"
  }'

200 OK
{
  "id": "account_transfer_abc123",
  "idempotency_key": "test_001"
  // ...
}
```

On the second request with the same `idempotency_key`, Increase returns the same object and sets a header indicating this response was replayed.

```curl
curl -X POST https://api.increase.com/account_transfers
  -H "Idempotency-Key: test_001"
  -d $'{
      "account_id": "account_1",
      "destination_account_id": "account_2",
      "description": "My great transfer!"
  }'

200 OK with header `Idempotent-Replayed: true`
{
  "id": "account_transfer_abc123", # The same ID!
  "idempotency_key": "test_001"
  // ...
}
```

If an idempotency key is re-used for different request arguments, the POST will fail.

```curl
curl -X POST https://api.increase.com/account_transfers
  -H "Idempotency-Key: test_001"
  -d $'{
      "account_id": "account_1",
      "destination_account_id": "account_2",
      "description": "A different description"
  }'

409 Conflict
{
  "status": 409,
  "type": "idempotency_key_already_used_error",
  "title": "The idempotency key submitted has already been used. Fetch the created object or use a different idempotency key.",
  "detail": null,
  "resource_id": "account_transfer_abc123"
}
```

You can also access the object with the list endpoint.

```curl
GET https://api.increase.com/account_transfers?idempotency_key=test_001

200 OK
{
  "data": [
    {
      "id": "account_transfer_abc123",
      "idempotency_key": "test_001"
      // ...
    }
  ]
}
```

## Deprecation notice

Prior to 2024, this functionality was only available on a subset of requests and was called `unique_identifier`. [Learn more about the older implementation.](/documentation/unique_identifiers)
