---
title: "Errores"
description: "El sobre de error de la API de Edugoverna, el catálogo de códigos de la Partner API y cómo reintentar de forma segura."
url: "https://docs.edugoverna.com/errores"
---
# Errores

Todo error de la API llega con el mismo sobre JSON: un `code` estable pensado para tu código, un `message` en español pensado para personas y, cuando aporta, un `details` con contexto adicional. Programa siempre contra el `code` — los mensajes pueden cambiar de redacción; los códigos no. {{ className: 'lead' }}

<Note>
  ¿Un rechazo que no esperabas? Antes de escribir a soporte, revisa el `code`:
  en la Partner API casi todos los 401/403 corresponden a una de las [cuatro
  puertas de acceso](/autenticacion) y se resuelven desde la consola del
  colegio, no desde tu código.
</Note>

## El sobre de error

<Row>
  <Col>

    <Properties>
      <Property name="error.code" type="string">
        Código estable en mayúsculas, por ejemplo `PARTNER_DPA_NOT_ACTIVE`.
        Es el contrato: úsalo para ramificar tu manejo de errores.
      </Property>
      <Property name="error.message" type="string">
        Descripción legible, en español (es-CL) para los códigos del catálogo.
        Apta para mostrar en pantalla, pero no para parsear.
      </Property>
      <Property name="error.details" type="object | array">
        Contexto opcional. En un `VALIDATION_ERROR` trae la lista de problemas
        del payload (campo por campo, formato de issues de Zod); en un
        `PARTNER_RATE_LIMITED` trae `limit`, `windowSeconds` y
        `retryAfterSeconds`.
      </Property>
    </Properties>

  </Col>
  <Col sticky>

    ```json {{ title: 'Ejemplo: 403' }}
    {
      "error": {
        "code": "PARTNER_DPA_NOT_ACTIVE",
        "message": "El contrato de tratamiento de datos (DPA) no está vigente.",
        "details": {
          "organizationPartnerConnectionId": "…",
          "partnerAccountId": "…"
        }
      }
    }
    ```

    ```json {{ title: 'Ejemplo: 422 de validación' }}
    {
      "error": {
        "code": "VALIDATION_ERROR",
        "message": "Los datos enviados no son válidos. Revisa el formulario.",
        "details": [
          {
            "origin": "string",
            "code": "too_small",
            "minimum": 2,
            "inclusive": true,
            "path": ["targetSubjectReferenceCode"],
            "message": "Too small: expected string to have >=2 characters"
          }
        ]
      }
    }
    ```

  </Col>
</Row>

## Códigos de autenticación y autorización de la Partner API

Estos son los códigos que produce la cadena de acceso de las rutas `/partner/v1/...`, en el orden en que se evalúan. Cada denegación queda además registrada en la auditoría del colegio.

<Properties>
  <Property name="ORGANIZATION_ID_REQUIRED" type="422">
    La ruta requiere el parámetro `:organizationId` y no venía en la URL. Es lo
    primero que se verifica.
  </Property>
  <Property name="PARTNER_BEARER_REQUIRED" type="401">
    Falta el encabezado `Authorization: Bearer`, está malformado, o enviaste
    `x-api-key` a una ruta de partner. Las rutas de partner solo aceptan la
    credencial Bearer.
  </Property>
  <Property name="PARTNER_CREDENTIAL_INVALID" type="401">
    La credencial no existe, no coincide con ningún hash registrado o fue
    revocada.
  </Property>
  <Property name="PARTNER_CREDENTIAL_EXPIRED" type="401">
    La credencial tenía fecha de expiración y ya pasó. Emite una nueva desde la
    consola.
  </Property>
  <Property name="PARTNER_CONNECTION_NOT_ACTIVE" type="403">
    No existe una conexión activa entre tu cuenta de partner y la organización
    de la URL: el colegio no la ha creado, la pausó o la terminó.
  </Property>
  <Property name="PARTNER_WORKSPACE_NOT_ACTIVE" type="403">
    Tu cuenta de partner está suspendida o pendiente de activación en
    Edugoverna, lo que deshabilita el acceso por API a todos tus colegios
    conectados.
  </Property>
  <Property name="PARTNER_DPA_NOT_ACTIVE" type="403">
    La conexión no tiene un contrato de encargo de datos (DPA) ejecutado y
    vigente — o, en conexiones de registro externo, falta la declaración jurada
    del registrador.
  </Property>
  <Property name="PARTNER_RATE_LIMITED" type="429">
    La credencial agotó su ventana de tasa. Se evalúa antes que el permiso y el
    alcance. La respuesta incluye `Retry-After` y `details.retryAfterSeconds`.
    Ver [Límites](/limites).
  </Property>
  <Property name="PARTNER_PERMISSION_REQUIRED" type="403">
    La credencial no lleva el permiso `partner.*` que la ruta exige. Los
    permisos se fijan al emitir la credencial.
  </Property>
  <Property name="PARTNER_SCOPE_REQUIRED" type="403">
    La conexión con ese colegio no otorga el alcance de la ruta (por ejemplo
    `consents:write`). El colegio puede otorgarlo desde la consola.
  </Property>
  <Property name="PARTNER_WORKSPACE_REQUIRED" type="403">
    La ruta opera sobre el espacio de trabajo propio del partner (por ejemplo
    campañas compartidas) y la organización de la URL no es tu workspace.
  </Property>
</Properties>

## Códigos de dominio frecuentes

Superada la cadena de acceso, los errores restantes describen el recurso o el payload:

<Properties>
  <Property name="VALIDATION_ERROR" type="422">
    El cuerpo o la query no pasan la validación de esquema. `details` enumera
    los problemas campo por campo.
  </Property>
  <Property name="INVALID_CURSOR" type="422">
    El cursor de paginación no es válido, o se reutilizó con otros filtros u
    otra organización. Ver [Paginación](/paginacion).
  </Property>
  <Property name="PARTNER_SUBJECT_NOT_FOUND" type="404">
    Ningún titular del colegio tiene el `referenceCode` indicado.
  </Property>
  <Property name="PARTNER_SUBJECT_TYPE_CONFLICT" type="409">
    El `referenceCode` existe, pero pertenece a un titular de otro tipo (por
    ejemplo, esperabas un estudiante y es un apoderado). `details` indica el
    tipo esperado y el real.
  </Property>
  <Property name="SUBJECT_NOT_FOUND" type="404">
    El titular no existe o no es visible para tu conexión.
  </Property>
  <Property name="CONSENT_REQUEST_NOT_FOUND" type="404">
    La solicitud de consentimiento no existe en esa organización.
  </Property>
  <Property name="CONSENT_REQUEST_NOT_OPEN" type="409">
    La solicitud ya no está pendiente (decidida, revocada, invalidada o
    vencida): no se puede reemitir su enlace.
  </Property>
  <Property name="CONSENT_DELIVERY_NOT_FOUND" type="404">
    La entrega no pertenece a esa solicitud.
  </Property>
  <Property name="INTEGRATIONS_MODULE_REQUIRED" type="409">
    La organización no tiene el módulo `integrations`: no se pueden crear ni
    activar endpoints de webhook. Ver [Webhooks](/webhooks#registrar-un-endpoint).
  </Property>
  <Property name="PROCESSING_ACTIVITY_NOT_FOUND" type="404">
    La actividad de tratamiento (o la versión indicada) no existe.
  </Property>
  <Property name="NOT_FOUND" type="404">
    La ruta solicitada no existe: es el 404 genérico del router. Revisa el
    método y la URL.
  </Property>
  <Property name="INTERNAL_SERVER_ERROR" type="500">
    Error inesperado del servidor. Reintenta con retroceso exponencial; si
    persiste, contacta a soporte con la hora y la ruta.
  </Property>
</Properties>

Cada grupo de endpoints documenta además sus códigos específicos — por ejemplo `CONSENT_CAMPAIGN_CLOSED` o `RIGHTS_REQUEST_NOT_FOUND` — en su página de la [referencia](/api-organizacion/introduccion).

## Códigos del motor de riesgo

Los produce el [registro de riesgos](/api-organizacion/riesgos) y los escenarios de las [evaluaciones de impacto](/api-organizacion/actividades-tratamiento#evaluaciones-de-impacto-eipd). Son rechazos de vocabulario y de regla metodológica, no de esquema: el payload puede ser sintácticamente válido y aun así no describir algo que la ley acepte.

<Properties>
  <Property name="RISK_ENTRY_SUBJECT_INVALID" type="422">
    Algún valor de `affectedSubjectTypes` no es un tipo de titular conocido
    (`student`, `guardian`, `staff`, `other`). `details.unknown` los enumera.
  </Property>
  <Property name="RISK_ENTRY_DATA_CATEGORY_INVALID" type="422">
    El `dataCategoryGroup` de la entrada no está en el catálogo de categorías
    del registro de riesgos.
  </Property>
  <Property name="NNA_IMPACT_JUSTIFICATION_REQUIRED" type="422">
    Una fila **redactada a mano** (`origin: "manual"`, el valor por defecto)
    califica el impacto bajo Significativo (3) afectando a estudiantes con
    datos sensibles, y no trae `impactRationale`. El interés superior del NNA
    (Art. 16 quáter) exige fundamentar por escrito una calificación así. Con
    `origin: "template"` o `"suggested"` no se rechaza: la fila se guarda y la
    respuesta trae `warnings: ["nna_impact_floor"]`.

    Rige en los dos lados del motor, y cada uno determina la sensibilidad donde
    corresponde: un **escenario de EIPD** la hereda de la actividad evaluada
    (`involvesSensitiveData`), mientras que una **entrada del registro de
    riesgos** la declara ella misma con su `dataCategoryGroup` — `health_pie`,
    `socioeconomic`, `behavioral_convivencia` o `biometric_image`—, porque
    describe un proceso y no una actividad de la que heredar.
  </Property>
</Properties>

## Códigos del modelo de prevención

Los produce el [modelo de prevención](/api-organizacion/mpi), un módulo add-on: sin contratarlo, sus rutas responden `403 MODULE_NOT_LICENSED` antes que cualquiera de estos.

<Properties>
  <Property name="MPI_REQUIREMENT_NOT_ATTESTABLE" type="422">
    La clave del requisito corresponde a uno **derivado** de los registros
    (`responsable`, `delegado`, `caracterizacion`, `riesgos`, `protocolos`), que
    se computa en lectura y no se puede declarar a mano.
  </Property>
  <Property name="MPI_EVIDENCE_FILE_REQUIRED" type="422">
    El `multipart/form-data` llegó sin `file`, o el archivo venía vacío.
  </Property>
  <Property name="MPI_EVIDENCE_TOO_LARGE" type="400">
    El documento de respaldo supera los 15 MB.
  </Property>
  <Property name="MPI_EVIDENCE_NOT_FOUND" type="404">
    La declaración no tiene evidencia adjunta, o el artefacto referido no
    pertenece a la organización.
  </Property>
  <Property name="MPI_DOSSIER_NOT_FOUND" type="404">
    No existe una versión sellada del expediente con ese id en la organización.
  </Property>
  <Property name="MPI_DOSSIER_DOCUMENT_MISSING" type="404">
    La versión sellada existe pero no tiene documento generado.
  </Property>
</Properties>

## Cómo reintentar

- **`429`**: espera lo que indique el encabezado `Retry-After` (o
  `details.retryAfterSeconds`) antes de reintentar. No acortes la espera: la
  ventana no se reinicia antes.
- **`5xx`**: reintenta con retroceso exponencial y jitter (por ejemplo 1 s,
  2 s, 4 s…), con un tope de intentos. Las operaciones de escritura que
  aceptan `idempotencyKey` — como la creación de solicitudes y campañas de
  consentimiento — pueden reintentarse con la misma clave sin riesgo de
  duplicar.
- **`4xx` (salvo 429)**: no reintentes sin cambiar algo. Un 401/403 se
  resuelve en la consola del colegio; un 422 se resuelve corrigiendo el
  payload.
