Consentimientos

Una solicitud de consentimiento le pregunta a quien tiene la autoridad — el propio titular o su apoderado, según la banda etaria — si acepta una actividad de tratamiento concreta. Edugoverna arma el aviso desde la versión publicada de la actividad, despacha la entrega por email o WhatsApp, captura la decisión con verificación de identidad y conserva la evidencia. En esta página revisamos los endpoints para crear solicitudes una a una, consultarlas de forma incremental y lanzar campañas sobre tu propia audiencia.

El modelo de solicitud

Una solicitud (consentRequest) referencia a un titular objetivo (por su referenceCode del padrón) y a una versión de actividad de tratamiento. De ella cuelgan las entregas (deliveries, una por canal y destinatario) y, cuando alguien decide, la decisión (latestDecision) con su evidencia.

Ciclo de vida (status)

Mientras la solicitud sigue abierta, su status es pending; el avance del envío (queued, sent, delivered, opened, failed) se lee en cada entrega (deliveries[].status), no en la solicitud. Los estados terminales de la solicitud son:

  • granted — el consentimiento fue otorgado.
  • denied — fue denegado.
  • revoked — fue otorgado y luego revocado.
  • expired — venció sin decisión.
  • invalidated — la solicitud fue anulada (por ejemplo, porque se publicó una nueva versión de la actividad que invalida los consentimientos previos, o porque una campaña posterior la reemplazó). El campo invalidationReason explica el motivo.

Idempotencia

Los endpoints de escritura aceptan idempotencyKey (entre 8 y 120 caracteres, único por credencial). Reintentar una llamada con la misma llave devuelve la solicitud original con idempotentReplay: true y sin tokens de entrega nuevos, al estilo de los reintentos seguros de pago.


POST/v1/organizations/:organizationId/consents/requests

Crear una solicitud de consentimiento

Crea una solicitud para un titular del padrón y encola de inmediato sus entregas. Responde 201 con el paquete completo de la solicitud y emite el webhook consent.requested.

Permiso requerido: partner.consents.write · Alcance de conexión: consents:write.

La actividad de tratamiento se referencia de una de dos formas: por processingActivityVersionId (UUID exacto de la versión) o por processingActivityCode (más processingActivityVersionNumber opcional; si se omite, se usa la versión vigente). Omitir ambas responde 422; si ambas vienen y no resuelven a la misma versión, 422 PROCESSING_ACTIVITY_REFERENCE_MISMATCH.

Las URLs de redirección deben estar registradas en la lista de destinos permitidos de tu conexión; una URL no registrada rechaza la llamada antes de escribir nada.

Atributos requeridos

  • Nombre
    targetSubjectReferenceCode
    Tipo
    string
    Descripción

    Código de referencia del titular objetivo (típicamente el estudiante). Si no existe, 404 TARGET_SUBJECT_NOT_FOUND.

Atributos opcionales

  • Nombre
    processingActivityVersionId
    Tipo
    string
    Descripción

    UUID de la versión de la actividad. Requerido si no viene processingActivityCode.

  • Nombre
    processingActivityCode
    Tipo
    string
    Descripción

    Código de la actividad. Requerido si no viene processingActivityVersionId.

  • Nombre
    processingActivityVersionNumber
    Tipo
    integer
    Descripción

    Número de versión a usar junto con processingActivityCode. Por defecto, la versión vigente.

  • Nombre
    successRedirectUrl
    Tipo
    string
    Descripción

    URL a la que se envía al firmante tras otorgar. Máximo 2048 caracteres.

  • Nombre
    declineRedirectUrl
    Tipo
    string
    Descripción

    URL a la que se envía al firmante tras denegar.

  • Nombre
    redirectMode
    Tipo
    string
    Descripción

    auto (redirección inmediata) o bridge (pantalla intermedia de Edugoverna antes de redirigir).

  • Nombre
    partnerExternalId
    Tipo
    string
    Descripción

    Identificador tuyo para correlacionar la solicitud (1–160 caracteres). Filtrable en el listado.

  • Nombre
    idempotencyKey
    Tipo
    string
    Descripción

    Llave de idempotencia (8–120 caracteres).

Request

POST
/v1/.../consents/requests
curl https://app.edugoverna.com/api/partner/v1/organizations/org_2f7a/consents/requests \
  -H "Authorization: Bearer {keyId}.{secret}" \
  -H "Content-Type: application/json" \
  -d '{
    "targetSubjectReferenceCode": "EST-2026-0142",
    "processingActivityCode": "plataforma-lectura",
    "successRedirectUrl": "https://app.milectura.cl/bienvenida",
    "redirectMode": "auto",
    "partnerExternalId": "lic-88231",
    "idempotencyKey": "lic-88231-consent-v1"
  }'

Response

{
  "id": "c4a1b2d3-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "organizationId": "org_2f7a",
  "processingActivityVersionId": "3f2e1d0c-9b8a-4765-b432-1a0f9e8d7c6b",
  "targetSubjectId": "9c1f6d1e-1c9d-4f6a-9a44-1f2ab5c0d9e1",
  "requestedForAgeBand": "under_14",
  "decisionActorType": "guardian",
  "status": "pending",
  "requestedAt": "2026-08-25T12:30:00.000Z",
  "expiresAt": null,
  "successRedirectUrl": "https://app.milectura.cl/bienvenida",
  "declineRedirectUrl": null,
  "redirectMode": "auto",
  "partnerExternalId": "lic-88231",
  "idempotencyKey": "lic-88231-consent-v1",
  "deliveries": [
    {
      "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
      "channel": "email",
      "status": "queued",
      "destinationMasked": "c***a.pino@familia.cl",
      "recipientSummary": null
    }
  ],
  "latestDecision": null,
  "deliveryAccessLinks": [
    {
      "consentDeliveryId": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
      "recipientSubjectId": "5d2a8c3b-77e1-4b0e-9f1d-3c4e5f6a7b8c",
      "channel": "email",
      "token": "cdt_..."
    }
  ],
  "idempotentReplay": false
  // ...
}

GET/v1/organizations/:organizationId/consents/requests

Listar solicitudes de consentimiento

Devuelve una página de solicitudes de la organización, ordenadas de la más reciente a la más antigua. A diferencia del detalle, el listado devuelve las filas base de cada solicitud (sin entregas ni decisión); usa el detalle para el paquete completo.

Permiso requerido: partner.consents.read · Alcance de conexión: consents:read.

Para sincronización incremental, el parámetro since acota a las solicitudes cuyo requestedAt sea posterior al instante dado; combínalo con cursor para recorrer páginas. El cursor está firmado contra la organización y el juego de filtros con que se emitió: reutilizarlo con filtros distintos responde 422 INVALID_CURSOR. Las solicitudes cuyo titular fue suprimido en origen se omiten de la respuesta.

Parámetros de consulta opcionales

  • Nombre
    status
    Tipo
    string
    Descripción

    Filtra por estado (por ejemplo granted, pending).

  • Nombre
    processingActivityCode
    Tipo
    string
    Descripción

    Filtra por actividad de tratamiento (todas sus versiones).

  • Nombre
    partnerExternalId
    Tipo
    string
    Descripción

    Filtra por tu identificador externo.

  • Nombre
    since
    Tipo
    timestamp
    Descripción

    Sólo solicitudes creadas después de este instante (ISO 8601).

  • Nombre
    limit
    Tipo
    integer
    Descripción

    Tamaño de página, entre 1 y 200. Por defecto 50.

  • Nombre
    cursor
    Tipo
    string
    Descripción

    Cursor de la página anterior (nextCursor). Ver Paginación.

Request

GET
/v1/.../consents/requests
curl -G https://app.edugoverna.com/api/partner/v1/organizations/org_2f7a/consents/requests \
  -H "Authorization: Bearer {keyId}.{secret}" \
  -d status=granted \
  -d since=2026-08-01T00:00:00Z \
  -d limit=50

Response

{
  "consentRequests": [
    {
      "id": "c4a1b2d3-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "organizationId": "org_2f7a",
      "processingActivityVersionId": "3f2e1d0c-9b8a-4765-b432-1a0f9e8d7c6b",
      "targetSubjectId": "9c1f6d1e-1c9d-4f6a-9a44-1f2ab5c0d9e1",
      "requestedForAgeBand": "under_14",
      "decisionActorType": "guardian",
      "status": "granted",
      "requestedAt": "2026-08-20T15:02:11.000Z",
      "expiresAt": null,
      "invalidatedAt": null,
      "invalidationReason": null,
      "partnerExternalId": "lic-88231",
      "redirectMode": "auto"
      // ...
    }
  ],
  "nextCursor": "eyJ2IjoxLCJzY29wZSI6InBhcnRuZXItY29uc2VudC1yZXF1ZXN0cyJ9"
}

GET/v1/organizations/:organizationId/consents/requests/:consentRequestId

Obtener una solicitud de consentimiento

Devuelve el paquete completo de una solicitud: sus entregas con resumen del destinatario, la última decisión con su desglose por permiso (cuando la actividad usa consentimiento granular) y su evidencia, y el último evento del historial.

Permiso requerido: partner.consents.read · Alcance de conexión: consents:read.

Si la solicitud no existe — o si su titular fue suprimido en la organización de origen — la respuesta es 404 CONSENT_REQUEST_NOT_FOUND en ambos casos, deliberadamente indistinguibles. El resumen de un apoderado suprimido vuelve en null aunque la solicitud siga visible.

Campos destacados del paquete:

  • Nombre
    targetSubjectSummary
    Tipo
    object
    Descripción

    Resumen de visualización del titular objetivo.

  • Nombre
    deliveries
    Tipo
    array
    Descripción

    Entregas con canal, estado, destino enmascarado y recipientSummary.

  • Nombre
    latestDecision
    Tipo
    object
    Descripción

    Última decisión: decision, options (desglose por permiso, null si el consentimiento es en bloque), optionsSummary, evidence y missingEvidenceTypes.

  • Nombre
    latestEvent
    Tipo
    object
    Descripción

    Último evento del ciclo de vida, con su payload.

Request

GET
/v1/.../consents/requests/c4a1b2d3...
curl https://app.edugoverna.com/api/partner/v1/organizations/org_2f7a/consents/requests/c4a1b2d3-e5f6-4a7b-8c9d-0e1f2a3b4c5d \
  -H "Authorization: Bearer {keyId}.{secret}"

Response

{
  "id": "c4a1b2d3-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
  "status": "granted",
  "requestedForAgeBand": "under_14",
  "decisionActorType": "guardian",
  "targetSubjectSummary": {
    "displayName": "Martina Rojas Pino",
    "subjectType": "student"
  },
  "deliveries": [
    {
      "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
      "channel": "email",
      "status": "delivered",
      "destinationMasked": "c***a.pino@familia.cl",
      "deliveredAt": "2026-08-20T15:04:40.000Z",
      "recipientSummary": { "displayName": "Carolina Pino Soto" }
    }
  ],
  "latestDecision": {
    "decision": "granted",
    "decidedAt": "2026-08-20T16:12:03.000Z",
    "options": null,
    "optionsSummary": null,
    "decisionMakerSummary": { "displayName": "Carolina Pino Soto" },
    "evidence": [
      {
        "id": "ev_01",
        "artifactId": "art_7c2d",
        "evidenceType": "signed_manifest",
        "checksum": "sha256:…",
        "capturedAt": "2026-08-20T16:12:03.000Z"
      }
    ],
    "missingEvidenceTypes": []
  },
  "latestEvent": {
    "eventType": "granted",
    "payload": { }
  }
  // ...
}

POST/v1/organizations/:organizationId/consents/campaigns

Crear una campaña con audiencia en línea

Crea y publica en una sola llamada una campaña de consentimiento sobre una lista de estudiantes que viaja en el propio cuerpo (audiencia "en línea"), creando una solicitud por estudiante. De pasada puede hacer upsert del estudiante, del apoderado y del vínculo de cada entrada, con los mismos esquemas del padrón.

Permiso requerido: partner.consents.write · Alcance de conexión: consents:write.

La audiencia en línea acepta hasta 100 estudiantes por llamada — la creación es síncrona y alguien espera la respuesta. Para lotes mayores, pagina: cada página es idempotente por su idempotencyKey, así que reenviar una página no duplica nada. Para campañas sobre padrones compartidos por un colegio, usa Campañas compartidas.

El procesamiento es por estudiante y tolerante a fallos: un error en una entrada no detiene el resto. Cada resultado vuelve con status created, idempotent_replay o error (con error.code y error.message); las entradas con error quedan también visibles en el embudo de la campaña. Por cada solicitud creada se encolan las entregas y se emite el webhook consent.requested.

Usar URLs de redirección exige una conexión de partner (403 PARTNER_CONNECTION_REQUIRED en su ausencia) y que todas las URLs del lote estén en la lista de destinos permitidos — se validan completas antes de escribir nada.

Atributos requeridos

  • Nombre
    students
    Tipo
    array
    Descripción

    Entre 1 y 100 entradas. Cada una acepta: referenceCode (requerido), partnerExternalId, successRedirectUrl, declineRedirectUrl, idempotencyKey propio, student (upsert de estudiante), guardian (upsert de apoderado, con referenceCode requerido) y guardianship (upsert del vínculo entre ambos).

Además debe venir processingActivityVersionId o processingActivityCode, igual que en la creación individual.

Atributos opcionales

  • Nombre
    name
    Tipo
    string
    Descripción

    Nombre de la campaña (2–160). Por defecto, un nombre generado con la fecha.

  • Nombre
    description
    Tipo
    string
    Descripción

    Descripción (máx. 2000).

  • Nombre
    channels
    Tipo
    array
    Descripción

    Canales de despacho: ["email"], ["whatsapp"] o ambos. Si se omite, cada solicitud usa el canal del contacto primario del destinatario.

  • Nombre
    endsAt
    Tipo
    timestamp
    Descripción

    Cierre de la campaña (ISO 8601, debe ser futuro). Se copia como expiración de cada solicitud.

  • Nombre
    reminderDayOffsets
    Tipo
    array
    Descripción

    Hasta 3 recordatorios, en días desde el envío (1–30, estrictamente crecientes). Por ejemplo [3, 7].

  • Nombre
    redirectMode
    Tipo
    string
    Descripción

    auto o bridge, para toda la campaña.

  • Nombre
    defaultSuccessRedirectUrl
    Tipo
    string
    Descripción

    URL de éxito por defecto; cada estudiante puede traer la suya.

  • Nombre
    defaultDeclineRedirectUrl
    Tipo
    string
    Descripción

    URL de rechazo por defecto.

  • Nombre
    idempotencyKey
    Tipo
    string
    Descripción

    Llave de idempotencia de la campaña (8–120). Reintentar con la misma llave reutiliza la campaña ya creada y deduplica por estudiante ({llave}:{referenceCode} cuando el estudiante no trae la suya).

Request

POST
/v1/.../consents/campaigns
curl https://app.edugoverna.com/api/partner/v1/organizations/org_2f7a/consents/campaigns \
  -H "Authorization: Bearer {keyId}.{secret}" \
  -H "Content-Type: application/json" \
  -d '{
    "processingActivityCode": "plataforma-lectura",
    "name": "Alta plataforma de lectura 2026",
    "channels": ["email"],
    "reminderDayOffsets": [3, 7],
    "idempotencyKey": "alta-lectura-2026-p1",
    "students": [
      {
        "referenceCode": "EST-2026-0142",
        "partnerExternalId": "lic-88231",
        "student": { "legalGivenNames": "Martina", "legalFamilyNames": "Rojas Pino" },
        "guardian": {
          "referenceCode": "APO-889",
          "legalGivenNames": "Carolina",
          "legalFamilyNames": "Pino Soto",
          "contact": { "contactType": "email", "value": "carolina.pino@familia.cl" }
        },
        "guardianship": { "relationshipType": "madre" }
      }
    ]
  }'

Response

{
  "campaignId": "a9b8c7d6-e5f4-4321-a0b1-c2d3e4f5a6b7",
  "processingActivityVersionId": "3f2e1d0c-9b8a-4765-b432-1a0f9e8d7c6b",
  "results": [
    {
      "referenceCode": "EST-2026-0142",
      "partnerExternalId": "lic-88231",
      "consentRequestId": "c4a1b2d3-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "portalAccessLinks": [
        {
          "consentDeliveryId": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
          "channel": "email",
          "token": "cdt_..."
        }
      ],
      "status": "created"
    },
    {
      "referenceCode": "EST-2026-0198",
      "partnerExternalId": null,
      "consentRequestId": null,
      "portalAccessLinks": [],
      "status": "error",
      "error": {
        "code": "PARTNER_SUBJECT_NOT_FOUND",
        "message": "student subject not found for reference code EST-2026-0198."
      }
    }
  ]
}

¿Te sirvió esta página?