---
title: Idempotencia
description: La cabecera Idempotency-Key hace que reintentar el envío de una generación sea seguro — la misma solicitud devuelve el mismo request_id sin un segundo trabajo ni un segundo cargo.
icon: Repeat
---

Envíe una cabecera `Idempotency-Key` cuando envíe una generación. Si se corta la conexión y reintenta con la misma clave y el mismo cuerpo, Clipia devuelve **la misma respuesta** con el mismo `request_id`: no se crea un segundo trabajo ni se cobran los créditos dos veces. El registro se conserva durante 24 horas.

## Cabecera

<TypeTable
  type={{
    'Idempotency-Key': {
      type: 'string',
      description: 'Clave para una solicitud lógica, de hasta 255 caracteres. Se recomienda un UUID v4. Válida durante 24 horas dentro de una misma clave de API.',
    },
  }}
/>

## Uso

<Tabs items={['cURL', 'TypeScript', 'Python']}>
<Tab value="cURL">

```bash
curl -X POST https://api.clipia.ai/v1/models/nano-banana-2 \
  -H "Authorization: Bearer $CLIPIA_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 8f3a1c7e-2b41-4d2a-9c0e-1200304cf45b" \
  -d '{ "input": { "prompt": "a sunset over mountains, cinematic" } }'
```

</Tab>
<Tab value="TypeScript">

```ts
import { createClient } from 'clipia-ai';

const clipia = createClient({ apiKey: process.env.CLIPIA_KEY! });

// El SDK añade por sí mismo una Idempotency-Key en cada submit.
// Para que sus propios reintentos lleguen al mismo trabajo, pase su clave:
await clipia.queue.submit('nano-banana-2', {
  input: { prompt: 'a sunset over mountains, cinematic' },
  idempotencyKey: '8f3a1c7e-2b41-4d2a-9c0e-1200304cf45b',
});
```

</Tab>
<Tab value="Python">

```python
import os
from clipia import Clipia

client = Clipia(api_key=os.environ["CLIPIA_KEY"])

# El SDK añade una Idempotency-Key en cada submit; pase la suya si lo necesita.
client.submit(
    "nano-banana-2",
    {"prompt": "a sunset over mountains, cinematic"},
    idempotency_key="8f3a1c7e-2b41-4d2a-9c0e-1200304cf45b",
)
```

</Tab>
</Tabs>

Cree una clave nueva para cada solicitud **lógica**, no para cada intento de red. Cuando el SDK genera la clave, cada llamada a `submit` recibe la suya; un reintento en su código que hace una llamada nueva recibe una clave nueva.

## Comportamiento al reintentar

| Situación | Resultado |
|-----------|-----------|
| Misma clave, mismo modelo, mismo cuerpo | La misma respuesta completa (incluidos los `warnings`, si los hubo) y el mismo `request_id`. Sin trabajo nuevo ni cargo nuevo |
| Misma clave, modelo o cuerpo distinto | `409 idempotency_key_reuse` |
| Reintento mientras la primera solicitud aún se procesa | `409 request_in_progress`: reintente en unos segundos |
| La primera solicitud terminó con un error | La clave se libera y el reintento se procesa desde cero |
| Han pasado más de 24 horas | La clave cuenta como nueva y crea un trabajo nuevo |

Las claves no se cruzan entre claves de API: la misma `Idempotency-Key` en dos claves de API son dos solicitudes independientes.

## Sin la cabecera

Sin la cabecera, las solicitudes idénticas de una misma clave de API que llegan en un intervalo de 20 segundos también se fusionan en un solo trabajo. Esto protege frente a un doble clic accidental o un reintento de red rápido. Si quiere a propósito dos generaciones idénticas seguidas, envíe valores de `Idempotency-Key` distintos.

<Callout type="warn" title="Solo el envío de generaciones">
La idempotencia se aplica a `POST /v1/models/{model}`. Las solicitudes `GET` se pueden reintentar sin ella con total seguridad. No incluya un correo electrónico ni otros datos personales en la clave: use un UUID v4 aleatorio.
</Callout>
