> ## Documentation Index
> Fetch the complete documentation index at: https://docs.etherfuse.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Idempotency

> Which create requests are safe to retry, and what we return when you retry them.

A network timeout leaves you unsure whether a create request landed. Each create request below has a rule for what happens when you send it again, so you can retry without creating a duplicate.

We do not read an `Idempotency-Key` header. Sending one has no effect.

## Orders: keyed on quoteId

[`POST /organization/{organizationId}/order`](/v2/api-reference/orders/create-order) creates at most one order per quote. The order's `id` is the `quoteId`.

| Request | Response |
| - | - |
| First request for a `quoteId` | `201` with the new order. |
| Same `quoteId` again, after the order exists | `200` with the existing order, unchanged. We ignore a different `memo`. |
| Same `quoteId` again, after the quote expired | `200` with the existing order. We check for the order before we check the quote. |
| Two requests for the same `quoteId` at the same moment | One gets `201`. The other gets `409` `conflict`. |
| A `quoteId` that has no order and has expired | `400` `quote-expired`. |

So a timed-out request is safe to retry with the same `quoteId`:

1. Keep the `quoteId` from the quote response.
2. Retry `POST /organization/{organizationId}/order` with the same organization id and `quoteId`.
3. Treat `201` and `200` as success.
4. On `409` `conflict`, read the order with [`GET /organization/{organizationId}/order/{id}`](/v2/api-reference/orders/get-order), using the `quoteId` as the id.

```js theme={null}
async function createOrder(organizationId, quoteId) {
  const base = `https://api.sand.etherfuse.com/organization/${organizationId}`;
  const res = await fetch(`${base}/order`, {
    method: "POST",
    headers: { Authorization: apiKey, "Content-Type": "application/json" },
    body: JSON.stringify({ quoteId }),
  });

  if (res.status === 201 || res.status === 200) return res.json();

  const problem = await res.json();
  if (problem.type === "https://docs.etherfuse.com/ramp/v2/errors/conflict") {
    return fetch(`${base}/order/${quoteId}`, {
      headers: { Authorization: apiKey },
    }).then((r) => r.json());
  }
  throw new Error(`Create failed: ${problem.type}`);
}
```

## Quotes

[`POST /organization/{organizationId}/quote`](/v2/api-reference/quotes/create-quote) creates a new quote with a new `quoteId` on every call. Retrying is safe: a quote does nothing until you create an order from it, and it expires after 2 minutes.

## Payment accounts

[`POST /organization/{organizationId}/payment_account`](/v2/api-reference/payment-accounts/register-payment-account) returns the account that organization already holds, with `200`, when you register the same account again. We do not change the stored account, except that we retry a `rejected` direction with the `registrationInfo` you send, and it goes back to `pending`. If another organization holds the account, you get `409` `payment-account-unavailable`.

## Webhook subscriptions

[`POST /webhook_subscription`](/v2/api-reference/webhook-subscriptions/create-webhook-subscription) allows one subscription per URL and event. A second request for the same URL and event returns `409` `conflict`. We return the signing `secret` only on the first `201`, so a retry that gets `409` does not see it. If you lost the secret, delete the subscription and create it again.

## Customer organizations: keyed on the id you send

[`POST /organization`](/v2/api-reference/organizations/create-organization) accepts an `id` you generate. If the `id` is already in use, the request returns `409` `conflict`.

1. Generate the UUID **once** and store it before the first attempt.
2. Send the same UUID on every retry.
3. Treat `409` `conflict` as "already created" and read it with [`GET /organization/{organizationId}`](/v2/api-reference/organizations/get-organization).

<Tip>
  Generate UUIDs with a standard v4 generator (`crypto.randomUUID()` in Node, a `uuid` library elsewhere).
</Tip>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.