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

# Reliability and retries

> Use Floral's rate-limit, idempotency, concurrency, request-ID, and audit guarantees safely.

Floral publishes the reliability profile of every operation in the API reference. Use that profile to decide whether a request is safe to retry and which headers it requires.

## Rate limits

Limits apply per principal and workspace in clock-aligned, fixed one-minute windows.

| Operation profile                   | Requests per minute |
| ----------------------------------- | ------------------: |
| Reads                               |                 120 |
| Creates                             |                  60 |
| Partial updates                     |                  60 |
| Archive, restore, and other actions |                  60 |
| Generation operations               |                  10 |

Responses evaluated against an operation's limit include `X-RateLimit-Limit` and `X-RateLimit-Remaining`. A limited request returns `429 RATE_LIMITED` and a `Retry-After` header measured in seconds. Wait for that interval, then retry with exponential backoff and jitter.

These limits protect service reliability. They are not fixed customer quotas and can become more specific while preserving the operation's public contract.

## Idempotent writes

Create, archive, restore, generation, and approval operations require an `Idempotency-Key` header. Choose an opaque value that is unique to one logical operation, such as a UUID.

Floral retains a completed result for 24 hours. An exact retry by the same token, workspace, and operation replays the original status, response body, `ETag`, `Location`, and `X-Request-ID`. Within that operation, reusing the key with a different canonical target, parsed body, or `If-Match` value returns `409 IDEMPOTENCY_CONFLICT`. Keys are scoped per operation, but you should still choose a new key for every new logical request.

```bash theme={null}
export IDEMPOTENCY_KEY="01J5C2R6X4T7A9N3K8M1Q0V2WP"
```

If a connection closes before you receive the response, retry the identical request with the same key. Generate a new key only for a new logical operation.

## Optimistic concurrency

Mutable detail responses include a strong `ETag`. Partial updates and state-changing actions require the latest value in `If-Match`.

```http theme={null}
ETag: "v1.ZXhhbXBsZS12ZXJzaW9u"
```

```http theme={null}
If-Match: "v1.ZXhhbXBsZS12ZXJzaW9u"
```

Treat the value as opaque and preserve its quotes. After a successful write, save the new `ETag` from the response. When Floral returns `412 VERSION_CONFLICT`, reload the resource, reconcile your intended change with the current state, and retry with the new value. Do not retry a `412` automatically without reconciling.

## Request IDs and audit expectations

Send a unique `X-Request-ID` of at most 128 characters for each logical request. Floral returns the effective ID in the response and in every error envelope. Idempotent replays return the original ID so you can correlate all attempts.

Record the following in your integration logs without storing tokens or sensitive body fields:

* the operation identifier, workspace slug, and resource ID;
* the idempotency key or resource version used;
* the response status, error code, and `X-Request-ID`;
* the time and outcome of each retry.

Floral records the authenticated actor for writes. Use a token belonging to the person responsible for the change, and retain the request ID when investigating an audit event.

## Retry decision table

| Result                                      | What to do                                                   |
| ------------------------------------------- | ------------------------------------------------------------ |
| Network interruption on an idempotent write | Retry the identical request with the same `Idempotency-Key`. |
| `429 RATE_LIMITED`                          | Wait for `Retry-After`, then retry with backoff and jitter.  |
| Transient `5xx` on a read                   | Retry with capped exponential backoff and jitter.            |
| Transient `5xx` on an idempotent write      | Retry the identical request with the same key.               |
| `412 VERSION_CONFLICT`                      | Reload, reconcile, and send the current `ETag`.              |
| Other `4xx` response                        | Correct the request or access before retrying.               |
