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

# Claves de idempotencia

> Envía una Idempotency-Key en cada escritura para que reintentar nunca reserve dos veces.

Un error de red justo después de enviar `POST /v1/appointments` te deja sin saber si la cita existe. Con una clave de idempotencia basta con enviar otra vez la misma petición: Brelio devuelve el primer resultado en lugar de reservar dos veces.

## La regla

Cada escritura (`POST` y `PATCH`) necesita la cabecera `Idempotency-Key`. Las lecturas (`GET`) no.

```bash theme={null}
curl -X POST https://api.brelio.app/v1/appointments \
  -H "Authorization: Bearer $BRELIO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0f7e3c52-3b1a-4d55-9a7e-6f2b1c8d9e10" \
  -d '{"patientId":"…","professionalId":"…","serviceId":"…","start":"2026-11-16T08:00:00Z"}'
```

* **Formato:** de 8 a 255 caracteres ASCII imprimibles, sin espacios. Un UUID v4 es lo más sencillo.
* **Una clave por cambio.** Genérala antes del primer intento y mantenla en todos los reintentos de ese mismo cambio.
* **Alcance:** por credencial y operación. Dos credenciales nunca chocan.
* **Duración:** Brelio recuerda una clave durante 24 horas.

## Qué pasa

| Envías | Brelio responde |
| - | - |
| Una clave nueva | Ejecuta la operación y guarda el resultado. |
| La misma clave y el mismo cuerpo otra vez | El resultado guardado, con el mismo estado (por ejemplo `201`), sin ejecutar nada. |
| La misma clave con otro cuerpo | `409 OPERATION_IDEMPOTENCY_CONFLICT`. No se ejecuta nada. |
| La misma clave mientras la primera petición sigue en curso | `409 OPERATION_IDEMPOTENCY_IN_PROGRESS`. Espera un momento y reintenta. |
| Ninguna clave en una escritura | `400 IDEMPOTENCY_KEY_REQUIRED`. |

```json 409 OPERATION_IDEMPOTENCY_CONFLICT theme={null}
{
  "type": "https://api.brelio.app/problems/operation-idempotency-conflict",
  "title": "Request refused",
  "status": 409,
  "code": "OPERATION_IDEMPOTENCY_CONFLICT",
  "detail": "The idempotency key was already used with a different request for appointments.create",
  "request_id": "17eb0fd0-c750-4dfa-bf6a-654f32dbb877",
  "params": { "operationId": "appointments.create" }
}
```

## Los secretos se muestran una vez

Algunas escrituras devuelven un secreto una sola vez (el `secret` de firma de un webhook). Repetir esa petición devuelve el mismo registro **sin** el secreto y con la cabecera `Brelio-Secret-Already-Shown: true`. Guarda el secreto de la primera respuesta.

## Reintenta con seguridad

```javascript Node.js theme={null}
async function createWithRetry(path, body) {
  const key = crypto.randomUUID() // una vez, antes del primer intento
  for (let attempt = 0; attempt < 4; attempt++) {
    try {
      const response = await fetch(`https://api.brelio.app/v1${path}`, {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${process.env.BRELIO_API_KEY}`,
          'Content-Type': 'application/json',
          'Idempotency-Key': key,
        },
        body: JSON.stringify(body),
      })
      if (response.status < 500 && response.status !== 429) return response
    } catch {
      // error de red: reintenta con la misma clave
    }
    await new Promise((resolve) => setTimeout(resolve, 2 ** attempt * 1000))
  }
  throw new Error('Brelio did not answer')
}
```


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