> ## 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.

# Errores

> Todos los errores tienen una misma forma y un código estable que dice qué falló: decide por él.

Una llamada que falla responde un estado HTTP de 400 o más y un cuerpo de tipo `application/problem+json`, la forma
estándar de [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457):

```json theme={null}
{
  "type": "urn:rfc:problem:core.forbidden",
  "status": 403,
  "title": "Forbidden",
  "code": "core.forbidden",
  "params": { "permission": "core.exports.run" },
  "requestId": "5d0c2b7e-8f3a-4c61-9e2d-1b7a4f6c3e90"
}
```

| Campo | Qué contiene |
| - | - |
| `code` | Qué falló, como `<módulo>.<error>`. Nunca cambia para el mismo problema: **decide por él.** |
| `params` | Los valores que lo explican, como el permiso que le falta a la llave. Cada código tiene los suyos. |
| `title` | Un resumen fijo del código, en inglés, igual en cada respuesta, para que lo leas mientras programas. Nunca lo muestres a tus usuarios, y nunca decidas por él. |
| `status` | El estado HTTP, el mismo de la respuesta. Varios códigos comparten un estado. |
| `type` | `urn:rfc:problem:` y el código. |
| `requestId` | El id de esta llamada. Inclúyelo cuando nos reportes un problema. |
| `errors` | Solo con `422 core.validation_failed`: cada campo que la petición tiene mal (abajo). |

## Decide por el código

La página de cada operación en la [referencia de la API](https://developers.readyforcommerce.com/es/api-reference/introduction.md) lista los códigos que puede
responder, como la de [Iniciar una exportación](https://developers.readyforcommerce.com/es/api-reference/core-start-export.md). Lee `code`, y `params` cuando el
código los tiene:

```bash curl theme={null}
curl --silent "https://app.readyforcommerce.com/api/v1/orgs/$RFC_ORG_ID/core/org" \
  --header "Authorization: Bearer $RFC_API_KEY" | jq '{code, params, requestId}'
```

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

import requests

response = requests.get(
    f"https://app.readyforcommerce.com/api/v1/orgs/{os.environ['RFC_ORG_ID']}/core/org",
    headers={"Authorization": f"Bearer {os.environ['RFC_API_KEY']}"},
)
if not response.ok:
    problem = response.json()
    if problem["code"] == "core.forbidden":
        print("A la llave le falta", problem["params"]["permission"])
    else:
        print(problem["code"], problem["requestId"])
```

```php PHP theme={null}
<?php
$curl = curl_init('https://app.readyforcommerce.com/api/v1/orgs/' . getenv('RFC_ORG_ID') . '/core/org');
curl_setopt_array($curl, [
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('RFC_API_KEY')],
    CURLOPT_RETURNTRANSFER => true,
]);
$body = json_decode(curl_exec($curl), true);
if (curl_getinfo($curl, CURLINFO_RESPONSE_CODE) >= 400) {
    if ($body['code'] === 'core.forbidden') {
        echo 'A la llave le falta ' . $body['params']['permission'];
    } else {
        echo $body['code'] . ' ' . $body['requestId'];
    }
}
```

```javascript JavaScript theme={null}
const response = await fetch(
  `https://app.readyforcommerce.com/api/v1/orgs/${process.env.RFC_ORG_ID}/core/org`,
  { headers: { Authorization: `Bearer ${process.env.RFC_API_KEY}` } },
);
if (!response.ok) {
  const problem = await response.json();
  if (problem.code === 'core.forbidden')
    console.log('A la llave le falta', problem.params.permission);
  else console.log(problem.code, problem.requestId);
}
```

## Una petición con campos mal

`422 core.validation_failed` lista en `errors` cada parte de la petición que rechazó:

```json theme={null}
{
  "type": "urn:rfc:problem:core.validation_failed",
  "status": 422,
  "title": "Validation failed",
  "code": "core.validation_failed",
  "requestId": "a3e1f9c2-4b7d-4e08-8a6f-2c5d9b1e7f34",
  "errors": [
    {
      "location": "body",
      "pointer": "#/name",
      "code": "invalid_type",
      "params": { "expected": "string" }
    }
  ]
}
```

* `location` es la parte de la petición: `body`, `querystring`, `params` (la ruta) o `headers`.
* `pointer` es un [JSON Pointer](https://www.rfc-editor.org/rfc/rfc6901) al campo, `#` para la parte entera.
* `code` dice qué tiene mal, y `params` sus límites, como `minimum` o `maximum`. El valor que enviaste nunca vuelve.

## Los códigos comunes

Estos códigos vienen de lo que recorre cada llamada, o de un tipo de llamada que comparten muchas operaciones; la
página de cada operación lista los que puede responder:

| Estado | Código | Qué pasó | Qué hacer |
| - | - | - | - |
| `400` | `core.bad_request` | No se pudo leer la petición: un cuerpo que no es JSON, o un `Idempotency-Key` incorrecto. | Corrige la petición. |
| `401` | `core.invalid_credential` | La llave es desconocida, está anulada o vencida, o es de otra organización. | Envía una llave vigente de esta organización ([Autenticación](https://developers.readyforcommerce.com/es/authentication.md)). |
| `403` | `core.forbidden` | A la llave le falta el permiso de `params.permission`. | Usa una llave que lo tenga: los permisos de una llave existente nunca crecen. |
| `403` | `core.module_not_enabled` | Tu organización no activó el módulo al que pertenece la operación; las conexiones de tienda necesitan `catalog` o `pricing`. | Alguien que puede activar módulos lo activa en la aplicación. |
| `403` | `core.module_read_only` | El módulo de `params.module` está en solo lectura: tu organización superó su cupo gratis sin tarjeta. Las lecturas, las exportaciones y las eliminaciones siguen pasando. | Alguien que gestiona la facturación agrega una tarjeta en la aplicación, o eliminar registros devuelve el uso a su cupo gratis. |
| `403` | `core.human_only` | Solo una persona hace esto, en la aplicación; `params.reason` dice de qué grupo de acciones. | Hazlo en la aplicación. |
| `404` | `core.not_found`, o el del módulo, como `core.job_not_found` | La ruta no existe, o tu organización no tiene ese registro. | Revisa la ruta y el id. |
| `409` | `core.org_deletion_scheduled` | La eliminación de la organización está programada, así que se rechaza cada llamada. | Deja de llamar. La persona dueña puede restaurar la organización en la aplicación hasta que se elimine. |
| `409` | `core.version_conflict` | Un cambio enviado con un `expectedVersion` que el registro ya dejó atrás: alguien lo guardó después de que lo leíste, y no se escribió nada de tu cambio. | Vuelve a leer el registro, aplica tu cambio a lo que tiene ahora y envíalo con su nueva `version`. |
| `422` | `core.validation_failed` | Un campo está mal; `errors` dice cuál. | Corrige los campos como los describe la página de la operación. |
| `429` | `core.rate_limited` | Demasiadas llamadas ([Límites de uso](https://developers.readyforcommerce.com/es/rate-limits.md)). | Espera los segundos que dice `Retry-After` y vuelve a llamar. |
| `429` | `core.job_limit_reached` | Demasiados trabajos sin terminar ([Límites de uso](https://developers.readyforcommerce.com/es/rate-limits.md#trabajos-sin-terminar)). | Espera los segundos que dice `Retry-After`, o a que termine un trabajo. |
| `500` | `core.internal` | Algo falló de nuestro lado. | Reintenta más tarde; si sigue, dinos el `requestId`. |
| `503` | `core.unavailable`, `core.surface_disabled` | La API no está disponible por un momento, o está en pausa para todos. | Espera los segundos que dice `Retry-After` y vuelve a llamar. |

> [!TIP]
>
> Un `4xx` que no sea `429` responde lo mismo hasta que cambies la petición o la llave: no lo
> repitas sin cambios. Un `429` o un `503` dice cuánto esperar en `Retry-After`: espera ese tiempo,
> nunca en un bucle sin pausa. Para repetir una escritura sin hacerla dos veces, envía un
> [`Idempotency-Key`](https://developers.readyforcommerce.com/es/rate-limits#repite-una-escritura-sin-riesgo).


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