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

# Límites de uso

> Cuántas llamadas puede hacer una llave y una organización, qué pasa al pasarse, y cómo repetir una escritura sin riesgo.

Cada llave de API, cada conexión de IA y cada organización tiene un presupuesto de llamadas por minuto, según el tipo
de llamada:

| Llamadas por minuto | Por llave de API | Por conexión de IA | Por organización |
| - | - | - | - |
| **Lectura:** un `GET` | 1200 | 300, lecturas y escrituras juntas | 2400 |
| **Escritura:** cualquier otro método | 600 | compartidas con las lecturas | 1200 |
| **Masiva:** una operación que cambia muchos registros en una llamada | 60 | 60 | 120 |

* **Una llamada gasta del presupuesto de su llave, y luego del de su organización.** El presupuesto de la organización
  lo comparten todas sus llaves y [conexiones de IA](https://developers.readyforcommerce.com/es/connect-an-ai.md), así que un programa muy activo puede frenar a
  los demás: da a cada programa su propia llave y reparte sus llamadas.
* **Las personas en la aplicación no gastan nada de él.** El trabajo de una persona en la aplicación nunca toma de
  estos presupuestos, así que un programa que los agota nunca deja fuera a tu equipo.
* **Los presupuestos se recargan de forma continua,** no al empezar cada minuto, y guardan solo unos segundos de
  llamadas a la vez: un ritmo parejo rinde más que las ráfagas.

## Saber cuánto queda

[Obtener la credencial que llama](https://developers.readyforcommerce.com/es/api-reference/core-get-credential.md) responde los `limits` de tu llave y sus
llamadas `remaining` de cada tipo, lo menor entre lo que aún tienen su propio presupuesto y el de su organización. No
cuenta para ningún límite ni ocupa lugar entre las llamadas en curso, así que puedes llamarla cuando lo necesites.

## Al pasarse de un límite

Una llamada que pasa un presupuesto responde `429` con el código `core.rate_limited` y una cabecera `Retry-After`, los
segundos enteros que hay que esperar. No hizo nada: espera ese tiempo y vuelve a enviarla, nunca en un bucle sin pausa.

```bash curl theme={null}
# --retry sigue Retry-After ante un 429 o un 503
curl --retry 3 "https://app.readyforcommerce.com/api/v1/orgs/$RFC_ORG_ID/core/org" \
  --header "Authorization: Bearer $RFC_API_KEY"
```

```python Python theme={null}
import os
import time

import requests

url = f"https://app.readyforcommerce.com/api/v1/orgs/{os.environ['RFC_ORG_ID']}/core/org"
headers = {"Authorization": f"Bearer {os.environ['RFC_API_KEY']}"}
for _ in range(3):
    response = requests.get(url, headers=headers)
    if response.status_code not in (429, 503):
        break
    time.sleep(int(response.headers["Retry-After"]))
print(response.json())
```

```php PHP theme={null}
<?php
$url = 'https://app.readyforcommerce.com/api/v1/orgs/' . getenv('RFC_ORG_ID') . '/core/org';
for ($attempt = 0; $attempt < 3; $attempt++) {
    $wait = 0;
    $curl = curl_init($url);
    curl_setopt_array($curl, [
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('RFC_API_KEY')],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HEADERFUNCTION => function ($curl, $line) use (&$wait) {
            if (stripos($line, 'Retry-After:') === 0) {
                $wait = (int) trim(substr($line, 12));
            }
            return strlen($line);
        },
    ]);
    $body = curl_exec($curl);
    $status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
    if ($status !== 429 && $status !== 503) {
        break;
    }
    sleep($wait);
}
echo $body;
```

```javascript JavaScript theme={null}
const url = `https://app.readyforcommerce.com/api/v1/orgs/${process.env.RFC_ORG_ID}/core/org`;
let response;
for (let attempt = 0; attempt < 3; attempt++) {
  response = await fetch(url, { headers: { Authorization: `Bearer ${process.env.RFC_API_KEY}` } });
  if (response.status !== 429 && response.status !== 503) break;
  const seconds = Number(response.headers.get('Retry-After'));
  await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}
console.log(await response.json());
```

## Llamadas en curso

Mantén como máximo 5 llamadas de las llaves y conexiones de IA de tu organización en curso a la
vez. Una llamada más allá de ellas puede responder `429 core.rate_limited` antes de hacer nada, con su propio
`Retry-After`. Para leer más rápido, pide [páginas](https://developers.readyforcommerce.com/es/pagination.md) más grandes en lugar de más llamadas a la vez.

## Trabajos sin terminar

El trabajo largo, como una importación o una exportación, corre como un trabajo: su llamada responde `202 Accepted`
con un `jobId`, que [Obtener un trabajo](https://developers.readyforcommerce.com/es/api-reference/core-get-job.md) sigue hasta que termina. Una organización
tiene como máximo 50 trabajos sin terminar, quien sea que los haya iniciado: en espera, en pausa o corriendo.
Un inicio de una llave o de una IA más allá de ellos responde `429` con el código `core.job_limit_reached` y un
`Retry-After` de 60 segundos, y no inicia nada. El inicio de una persona en la aplicación
nunca se rechaza.

El archivo de un trabajo, como el de una exportación, se lee mediante un enlace de
[Obtener el enlace de un archivo del trabajo](https://developers.readyforcommerce.com/es/api-reference/core-get-job-file.md), que funciona durante
5 minutos: pide uno nuevo cuando venza.

## Repite una escritura sin riesgo

Una escritura cuya respuesta nunca llegó, porque la conexión se cortó o tardó demasiado, puede haber ocurrido o no.
Envíala con una cabecera `Idempotency-Key`, un valor tuyo de como máximo 255 caracteres, como un
UUID hecho para esa sola escritura, y envía el mismo valor en cada reintento:

```bash curl theme={null}
IDEMPOTENCY_KEY=$(uuidgen) # una por escritura; la misma en cada reintento

curl --request POST \
  "https://app.readyforcommerce.com/api/v1/orgs/$RFC_ORG_ID/core/jobs/$JOB_ID/cancel" \
  --header "Authorization: Bearer $RFC_API_KEY" \
  --header "Idempotency-Key: $IDEMPOTENCY_KEY"
```

```python Python theme={null}
import os
import uuid

import requests

idempotency_key = str(uuid.uuid4())  # una por escritura; la misma en cada reintento
response = requests.post(
    f"https://app.readyforcommerce.com/api/v1/orgs/{os.environ['RFC_ORG_ID']}/core/jobs/{os.environ['JOB_ID']}/cancel",
    headers={
        "Authorization": f"Bearer {os.environ['RFC_API_KEY']}",
        "Idempotency-Key": idempotency_key,
    },
)
print(response.json())
```

```php PHP theme={null}
<?php
$idempotencyKey = bin2hex(random_bytes(16)); // una por escritura; la misma en cada reintento
$curl = curl_init(
    'https://app.readyforcommerce.com/api/v1/orgs/' . getenv('RFC_ORG_ID') . '/core/jobs/' . getenv('JOB_ID') . '/cancel'
);
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('RFC_API_KEY'),
        'Idempotency-Key: ' . $idempotencyKey,
    ],
    CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($curl);
```

```javascript JavaScript theme={null}
const idempotencyKey = crypto.randomUUID(); // una por escritura; la misma en cada reintento
const response = await fetch(
  `https://app.readyforcommerce.com/api/v1/orgs/${process.env.RFC_ORG_ID}/core/jobs/${process.env.JOB_ID}/cancel`,
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.RFC_API_KEY}`,
      'Idempotency-Key': idempotencyKey,
    },
  },
);
console.log(await response.json());
```

* **La primera llamada hace la escritura;** un reintento con el mismo valor y la misma petición responde la respuesta
  de la primera, sin hacerla otra vez, durante 24 horas.
* **Mientras la primera llamada sigue corriendo,** un reintento responde `409 core.idempotency_in_progress`: espera y
  reintenta.
* **El mismo valor con otra petición,** otro cuerpo u otra ruta, responde `422 core.idempotency_mismatch`.
* **Cada valor es de tu credencial:** la llamada de otra llave de API con el mismo valor es una llamada aparte.
* **Un valor vacío o demasiado largo** responde `400 core.bad_request`.
* Una llamada que falló no guarda nada, así que su reintento vuelve a correr.

Estas escrituras respetan un `Idempotency-Key`; en cualquier otra no cambia nada:
[Cancelar un trabajo](https://developers.readyforcommerce.com/es/api-reference/core-cancel-job.md), [Restaurar una versión](https://developers.readyforcommerce.com/es/api-reference/core-restore-version.md),
[Iniciar una importación](https://developers.readyforcommerce.com/es/api-reference/core-start-import.md),
[Inspeccionar un archivo de importación](https://developers.readyforcommerce.com/es/api-reference/core-inspect-import.md),
[Revisar una importación](https://developers.readyforcommerce.com/es/api-reference/core-check-import.md),
[Traer un archivo desde una URL](https://developers.readyforcommerce.com/es/api-reference/core-fetch-import-file.md),
[Generar los resultados de una importación](https://developers.readyforcommerce.com/es/api-reference/core-start-import-results.md),
[Iniciar una exportación](https://developers.readyforcommerce.com/es/api-reference/core-start-export.md),
[Crear una plantilla de exportación](https://developers.readyforcommerce.com/es/api-reference/core-create-export-template.md),
[Crear una vista guardada](https://developers.readyforcommerce.com/es/api-reference/core-create-view.md),
[Conectar una tienda](https://developers.readyforcommerce.com/es/api-reference/integrations-connect-store.md),
[Crear un producto](https://developers.readyforcommerce.com/es/api-reference/catalog-create-product.md) y
[Duplicar un producto](https://developers.readyforcommerce.com/es/api-reference/catalog-duplicate-product.md).


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