> For the complete documentation index, see [llms.txt](https://developers.gallantreecapital.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.gallantreecapital.com/guides/idempotency.md).

# Idempotency

Every write endpoint (`POST`, `PUT`, `DELETE`) supports the `Idempotency-Key` header. This lets you retry safely — a network hiccup, a client timeout, a container restart — without accidentally creating the same resource twice.

## The rule

* **On the first request** with a given key, the API processes the request normally and stores the response — status code, headers, and body — against the key.
* **On any subsequent request** with the same key, the API returns the stored response verbatim. It does not re-execute the write.
* **The response is stored for 24 hours** from the first request. After that, the key is forgotten and a new request with the same key is treated as a first request.

## What counts as "the same key"

* **Same header value** (`Idempotency-Key: <value>`).
* **Same route** (`POST /api/v1/loans`).
* **Same authenticated app** (idempotency records are scoped to an app — two apps can safely use the same key value in isolation).

A key that matches on all three replays the stored response. A key that matches only some of them is treated as a new request.

## What about a different body?

If you re-send the same `Idempotency-Key` with a **different request body**, the API returns `409 Conflict`:

```json
{ "message": "Idempotency key conflict: the same key was used with a different request body." }
```

This is a safety measure — it prevents a client bug from silently overwriting a stored response. Fix the client or use a fresh key.

## Choosing a key

* **Format:** a valid UUID (any version — UUID v4 is the safe default). The API rejects non-UUID values with `400 Idempotency-Key must be a valid UUID`.
* **Scope:** one key per **logical operation**, not one per attempt. If your client generates a fresh key on every retry, you defeat the purpose — the API cannot recognise the retries and each attempt runs afresh.
* **Persistence:** store the key alongside the operation it identifies. When your client retries, look up the key you already generated and re-use it.

## What idempotency does not do

* It does **not** re-attempt failed writes. If the first request returned `500`, replays return `500`. Use a **new** key if you want the operation to actually run again.
* It does **not** cover `GET` reads. Reads are naturally idempotent; the header is ignored on `GET` routes.
* It does **not** cross environments. A key on sandbox and a key on production are entirely separate spaces.

## Runnable example

```bash
KEY=$(uuidgen)   # or any URL-safe unique string

# First attempt — actually creates the loan
curl -sS -X POST https://developers.gallantreecapital.com/api/v1/loans \
  -H "x-api-key: $GALLANTREE_API_KEY" \
  -H "Idempotency-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"reference":"MY-001","capitalProgramId":"...","principal":{"amount":100000,"currency":"AUD"}}'

# Retry after a client-side timeout — returns the original response, no duplicate
curl -sS -X POST https://developers.gallantreecapital.com/api/v1/loans \
  -H "x-api-key: $GALLANTREE_API_KEY" \
  -H "Idempotency-Key: $KEY" \
  -H "Content-Type: application/json" \
  -d '{"reference":"MY-001","capitalProgramId":"...","principal":{"amount":100000,"currency":"AUD"}}'
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://developers.gallantreecapital.com/guides/idempotency.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
