Conexiones y partners
Una conexión es la relación formal entre tu establecimiento y un partner tecnológico: quién es, con qué propósito trata datos, a qué recursos puede llegar y bajo qué contrato. Esta página cubre la API con que se administra ese grafo — cuentas de partner, solicitudes de conexión, scopes, contratos DPA y orígenes de redirección — además del endpoint de diagnóstico para depurar rechazos 403.
Las rutas aceptan sesión de la Consola o una API key de organización en la
cabecera x-api-key. Las lecturas exigen integrations.read; las escrituras,
integrations.write. Todo esto también se administra desde la Consola, en
Integraciones.
El modelo: conexión, scopes y DPA
Tres piezas gobiernan el acceso de un partner:
- La conexión (
organization_partner_connection) une un colegio con una cuenta de partner. Registra el propósito (purposeSummary), la base legal, quién la autorizó y su estado (activeorevoked; cualquier estado distinto deactivecierra el paso al partner). Hay a lo más una conexión por par colegio–partner. - Los scopes (
connection_scopes) abren grupos de rutas de la API de partner por espacio de recursos (resourceNamespace, por ejemplosubjectsoconsents) y tipo (readowrite). Sin el scope correspondiente, el grupo de rutas queda cerrado aunque la credencial tenga el permiso. - El contrato DPA (Art. 15 bis) es una compuerta dura: sin un DPA vigente — estado
activey dentro de su rango de vigencia — toda llamada del partner es rechazada conPARTNER_DPA_NOT_ACTIVE. Las conexiones de tipoexternal_registryno llevan DPA; para ellas la compuerta exige la declaración jurada firmada del registrador.
Cada llamada del partner atraviesa, en orden, cuatro compuertas: credencial válida y no vencida → conexión activa con ese colegio → cuenta del partner activa → DPA vigente (o declaración jurada, según el tipo). Recién entonces se evalúan scopes y permisos de la ruta. Puedes reproducir esa evaluación con el diagnóstico de acceso.
Las credenciales de API del partner y los endpoints de webhook asociados a una conexión se documentan aparte.
Listar partners
Devuelve el estado completo del grafo para tu organización en una sola respuesta:
- Nombre
partnerConnections- Tipo
- array
- Descripción
Las conexiones existentes, cada una con su cuenta de partner (
partner), susscopesy el resumen del último DPA (dpa, constatus, vigencia y si tiene documento adjunto).
- Nombre
partnerConnectionRequests- Tipo
- array
- Descripción
Las solicitudes de conexión pendientes o decididas que involucran a tu organización.
- Nombre
orphanPartnerAccounts- Tipo
- array
- Descripción
Cuentas de partner creadas por tu organización que aún no tienen conexión, listadas para que puedas limpiarlas.
Solicitud
curl https://app.edugoverna.com/api/integrations/partners \
-H "x-api-key: {api_key}"
Respuesta
{
"partnerConnections": [
{
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"partnerAccountId": "16fd2706-8baf-433b-82eb-8c7fada847da",
"connectionType": "api",
"status": "active",
"purposeSummary": "Sincronización de matrícula y consentimientos",
"legalBasis": "contrato_encargo",
"partner": {
"id": "16fd2706-8baf-433b-82eb-8c7fada847da",
"name": "Plataforma Escolar SpA",
"slug": "plataforma-escolar"
},
"scopes": [
{ "resourceNamespace": "subjects", "scopeType": "read" },
{ "resourceNamespace": "consents", "scopeType": "write" }
],
"dpa": {
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"versionNumber": 2,
"status": "active",
"effectiveFrom": "2026-08-12T00:00:00.000Z",
"effectiveTo": null,
"hasDocument": true
}
}
],
"partnerConnectionRequests": [],
"orphanPartnerAccounts": []
}
Detalle de una conexión
Devuelve una conexión con todo lo que cuelga de ella: la cuenta de partner,
sus scopes (con id, para poder quitarlos), el resumen del último DPA,
los redirectOrigins aprobados y las credentials del partner en su forma
segura (con prefix, nunca la llave). Una conexión de otra organización
responde 404 con ORGANIZATION_PARTNER_CONNECTION_NOT_FOUND.
Solicitud
curl https://app.edugoverna.com/api/integrations/partners/d290f1ee-6c54-4b01-90e6-d701748f0851 \
-H "x-api-key: {api_key}"
Respuesta
{
"partnerConnection": {
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"status": "active",
"partner": { "name": "Plataforma Escolar SpA" },
"scopes": [
{
"id": "0b8e4c2a-5d1f-4a6b-8c3e-7f9d2a1b6c4e",
"resourceNamespace": "subjects",
"scopeType": "read"
}
],
"dpa": { "status": "active", "hasDocument": true },
"redirectOrigins": [
{
"id": "b1946ac9-2d5a-4a3c-8f2e-0d9c7e6f5a4b",
"origin": "https://app.plataformaescolar.cl",
"allowSubpaths": true
}
],
"credentials": [
{
"id": "9e2a41d7-6c3b-4f0e-8a17-b5d4c2e8f901",
"label": "Producción",
"prefix": "9e2a41d7-6c3",
"status": "active"
}
]
}
}
Crear una cuenta de partner
Registra una cuenta de partner nueva (por ejemplo, un proveedor que aún no existe en la plataforma). La cuenta queda visible en tu listado como huérfana hasta que la conectes.
Atributos obligatorios
- Nombre
name- Tipo
- string
- Descripción
Nombre del partner (2–160 caracteres).
Atributos opcionales
- Nombre
slug- Tipo
- string
- Descripción
Identificador legible, único en la plataforma (2–160 caracteres).
- Nombre
partnerType- Tipo
- string
- Descripción
Tipo de partner. Por defecto
software_vendor.
- Nombre
websiteUrl- Tipo
- string
- Descripción
Sitio web del partner.
- Nombre
contactEmail- Tipo
- string
- Descripción
Correo de contacto general.
- Nombre
contactPhone- Tipo
- string
- Descripción
Teléfono de contacto.
- Nombre
privacyContactEmail- Tipo
- string
- Descripción
Correo del contacto de privacidad del partner.
- Nombre
status- Tipo
- string
- Descripción
Estado inicial. Por defecto
active.
- Nombre
metadata- Tipo
- object
- Descripción
Metadatos libres.
Para eliminar una cuenta creada por tu organización que no tiene
conexión, usa
DELETE /api/integrations/partner-accounts/:partnerAccountId; si la
cuenta ya tiene conexiones, solicitudes o credenciales, responde 409
con PARTNER_ACCOUNT_IN_USE.
Solicitud
curl https://app.edugoverna.com/api/integrations/partners \
-H "x-api-key: {api_key}" \
-H "Content-Type: application/json" \
-d '{
"name": "Plataforma Escolar SpA",
"contactEmail": "soporte@plataformaescolar.cl",
"privacyContactEmail": "privacidad@plataformaescolar.cl"
}'
Respuesta (201)
{
"id": "16fd2706-8baf-433b-82eb-8c7fada847da",
"name": "Plataforma Escolar SpA",
"slug": "plataforma-escolar-spa",
"partnerType": "software_vendor",
"status": "active"
// ... resto de la cuenta
}
Solicitudes de conexión
Una solicitud de conexión es la invitación formal entre las partes: el
colegio invita a un partner (school_invites_partner) o el partner pide
acceso a un colegio (partner_requests_school). Las pendientes se listan
con GET /api/integrations/connection-requests y la contraparte las
decide con
POST /api/integrations/connection-requests/:id/decide enviando
{ "decision": "accepted" } o { "decision": "rejected" }. Al aceptarse,
la plataforma crea la conexión con los scopes solicitados; si la solicitud
no traía scopes, aplica un conjunto por defecto (subjects read,
consents read y write, rights_requests read).
Atributos opcionales
- Nombre
direction- Tipo
- string
- Descripción
school_invites_partner(por defecto) opartner_requests_school.
- Nombre
targetPartnerAccountId- Tipo
- string
- Descripción
UUID de la cuenta de partner invitada.
- Nombre
targetOrganizationId- Tipo
- string
- Descripción
UUID de la organización objetivo, cuando quien solicita es el partner.
- Nombre
targetEmail- Tipo
- string
- Descripción
Correo del invitado cuando aún no tiene cuenta en la plataforma; la invitación le llega por correo.
- Nombre
requestedScopes- Tipo
- array
- Descripción
Hasta 50 scopes solicitados, cada uno con
resourceNamespace(2–80 caracteres),scopeTypeyconditionsopcionales.
- Nombre
message- Tipo
- string
- Descripción
Mensaje para la contraparte (hasta 2000 caracteres).
- Nombre
expiresAt- Tipo
- string (fecha)
- Descripción
Vencimiento de la invitación.
Solicitud
curl https://app.edugoverna.com/api/integrations/connection-requests \
-H "x-api-key: {api_key}" \
-H "Content-Type: application/json" \
-d '{
"direction": "school_invites_partner",
"targetPartnerAccountId": "16fd2706-8baf-433b-82eb-8c7fada847da",
"requestedScopes": [
{ "resourceNamespace": "subjects", "scopeType": "read" },
{ "resourceNamespace": "consents", "scopeType": "write" }
],
"message": "Integración de consentimientos 2026"
}'
Decidir (POST …/:id/decide)
{
"decision": "accepted"
}
Crear o reactivar una conexión
Crea la conexión directamente (sin pasar por una solicitud), o actualiza y
reactiva la existente: hay a lo más una conexión por par colegio–partner,
así que un segundo POST con el mismo partnerAccountId actualiza esa
fila y limpia una revocación previa.
Atributos obligatorios
- Nombre
partnerAccountId- Tipo
- string
- Descripción
UUID de la cuenta de partner.
Atributos opcionales
- Nombre
connectionType- Tipo
- string
- Descripción
Tipo de conexión. Por defecto
api.
- Nombre
status- Tipo
- string
- Descripción
Estado inicial. Por defecto
active.
- Nombre
purposeSummary- Tipo
- string
- Descripción
Propósito del tratamiento encargado (hasta 1000 caracteres).
- Nombre
legalBasis- Tipo
- string
- Descripción
Base legal registrada para la relación.
- Nombre
controllerEntityId- Tipo
- string
- Descripción
Entidad responsable bajo la cual se registra la conexión; si se omite, se usa la entidad principal de la organización.
- Nombre
authorizedByUserId- Tipo
- string
- Descripción
Usuario que autorizó la conexión.
- Nombre
approvedAt- Tipo
- string (fecha)
- Descripción
Fecha de aprobación. Por defecto, el momento de la llamada.
- Nombre
returnOrDeletionRequired- Tipo
- boolean
- Descripción
Si al término de la relación se exige devolución o supresión de los datos. Por defecto
true.
Solicitud
curl https://app.edugoverna.com/api/integrations/connections \
-H "x-api-key: {api_key}" \
-H "Content-Type: application/json" \
-d '{
"partnerAccountId": "16fd2706-8baf-433b-82eb-8c7fada847da",
"purposeSummary": "Sincronización de matrícula y consentimientos",
"legalBasis": "contrato_encargo"
}'
Respuesta (201)
{
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"partnerAccountId": "16fd2706-8baf-433b-82eb-8c7fada847da",
"connectionType": "api",
"status": "active",
"returnOrDeletionRequired": true
// ... resto de la conexión
}
Scopes de una conexión
Agrega un scope a la conexión. Cada scope abre un grupo de rutas de la API de partner; quitarlo lo cierra en la llamada siguiente, sin caché de por medio.
Atributos
- Nombre
resourceNamespace- Tipo
- string
- Descripción
Espacio de recursos que abre el scope (2–80 caracteres), por ejemplo
subjectsoconsents.
- Nombre
scopeType- Tipo
- string
- Descripción
readowrite. Por defectoread.
- Nombre
conditions- Tipo
- object
- Descripción
Condiciones adicionales del scope, opcionales.
Para quitar un scope:
DELETE /api/integrations/connections/:id/scopes/:connectionScopeId.
El id de cada scope viene en el
detalle de la conexión; un id de otra
conexión u otra organización responde 404 con
CONNECTION_SCOPE_NOT_FOUND. La respuesta de la eliminación es
{ "ok": true }.
Solicitud
curl https://app.edugoverna.com/api/integrations/connections/d290f1ee-6c54-4b01-90e6-d701748f0851/scopes \
-H "x-api-key: {api_key}" \
-H "Content-Type: application/json" \
-d '{ "resourceNamespace": "consents", "scopeType": "write" }'
Respuesta (201)
{
"id": "0b8e4c2a-5d1f-4a6b-8c3e-7f9d2a1b6c4e",
"organizationPartnerConnectionId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"resourceNamespace": "consents",
"scopeType": "write",
"conditions": null
}
Revocar una conexión
Marca la conexión como revoked y registra cuándo y quién la revocó. La
revocación arrastra todo lo que cuelga de la relación: las comparticiones
de padrón otorgadas por esta conexión se retiran y sus solicitudes de
consentimiento pendientes quedan invalidadas (ver
Campañas compartidas). Desde ese momento, toda
llamada del partner a tu organización es rechazada con
PARTNER_CONNECTION_NOT_ACTIVE.
Un nuevo POST /api/integrations/connections con el mismo partner
reactiva la relación.
Solicitud
curl -X POST https://app.edugoverna.com/api/integrations/connections/d290f1ee-6c54-4b01-90e6-d701748f0851/revoke \
-H "x-api-key: {api_key}"
Respuesta
{
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"status": "revoked",
"revokedAt": "2026-08-25T14:03:22.511Z"
// ... resto de la conexión
}
Registrar un contrato DPA
Registra una nueva versión del contrato de encargo (Art. 15 bis) del partner. El endpoint acepta dos formatos:
Multipart — adjunta el documento firmado en el campo file
(máximo 15 MB; DPA_DOCUMENT_TOO_LARGE si lo excede) y, opcionalmente, un
campo status. El documento se almacena como evidencia y la nueva versión
del contrato lo referencia.
JSON — registra la versión con o sin documento externo:
- Nombre
status- Tipo
- string
- Descripción
draftoactive. Por defectoactive. Solo un contratoactivedentro de su vigencia abre la compuerta de la API de partner.
- Nombre
versionNumber- Tipo
- integer
- Descripción
Número de versión; si se omite, continúa la numeración existente.
- Nombre
executedAt- Tipo
- string (fecha)
- Descripción
Fecha de firma. Por defecto, el momento de la llamada.
- Nombre
effectiveFrom- Tipo
- string (fecha)
- Descripción
Inicio de vigencia. Por defecto, el momento de la llamada.
- Nombre
effectiveTo- Tipo
- string (fecha)
- Descripción
Fin de vigencia; debe ser posterior a
effectiveFrom.
- Nombre
documentUrl- Tipo
- string
- Descripción
Referencia externa al documento (URL), como alternativa al adjunto.
- Nombre
returnOrDeletionClause- Tipo
- string
- Descripción
Texto de la cláusula de devolución o supresión (hasta 2000 caracteres).
- Nombre
artifactId / artifact- Tipo
- string / object
- Descripción
Referencia a un artefacto de evidencia ya almacenado, o uno inline. Excluyentes entre sí.
Una versión nueva que no re-adjunta documento arrastra la referencia al documento de la versión anterior, de modo que el DPA vigente siga apuntando al último documento cargado.
El documento del último contrato registrado se descarga con
GET /api/integrations/connections/:id/dpa-document — la respuesta es el
archivo mismo, con su content-type original y la cabecera
x-artifact-checksum. Si la conexión no tiene documento cargado, responde
404 con DPA_DOCUMENT_NOT_FOUND.
Solicitud
curl https://app.edugoverna.com/api/integrations/connections/d290f1ee-6c54-4b01-90e6-d701748f0851/dpa-contracts \
-H "x-api-key: {api_key}" \
-F "file=@dpa-firmado.pdf" \
-F "status=active"
Respuesta (201)
{
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"versionNumber": 2,
"status": "active",
"executedAt": "2026-08-25T14:03:22.511Z",
"effectiveFrom": "2026-08-25T14:03:22.511Z",
"effectiveTo": null
// ... resto del contrato
}
Orígenes de redirección
Cuando el partner lanza flujos que terminan redirigiendo al titular de vuelta a su propia aplicación (por ejemplo, al cerrar un portal de consentimiento de una campaña), el destino debe estar en esta lista de orígenes aprobados por el colegio. Un origen fuera de la lista es rechazado.
Atributos
- Nombre
origin- Tipo
- string
- Descripción
El origen a aprobar, por ejemplo
https://app.plataformaescolar.cl. Se normaliza antes de guardarse; un valor que no es un origen válido responde conREDIRECT_ORIGIN_INVALID.
- Nombre
allowSubpaths- Tipo
- boolean
- Descripción
Si se permiten rutas bajo el origen. Por defecto
true.
La operación es idempotente: volver a agregar un origen existente devuelve
la fila que ya estaba. Los orígenes se listan con
GET /api/integrations/connections/:id/redirect-origins y se quitan con
DELETE /api/integrations/connections/:id/redirect-origins/:redirectOriginId.
Solicitud
curl https://app.edugoverna.com/api/integrations/connections/d290f1ee-6c54-4b01-90e6-d701748f0851/redirect-origins \
-H "x-api-key: {api_key}" \
-H "Content-Type: application/json" \
-d '{ "origin": "https://app.plataformaescolar.cl" }'
Respuesta (201)
{
"id": "b1946ac9-2d5a-4a3c-8f2e-0d9c7e6f5a4b",
"organizationPartnerConnectionId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"origin": "https://app.plataformaescolar.cl",
"allowSubpaths": true
}
Diagnóstico de acceso
Resuelve una llave de partner contra tu organización pasando por las
mismas cuatro compuertas que una llamada real de la API de partner. Es la
herramienta para depurar un 403: en lugar de adivinar cuál compuerta
rechazó, la respuesta te lo dice. Aunque el método es POST, la ruta es
de diagnóstico y exige integrations.read.
Atributos
- Nombre
providedKey- Tipo
- string
- Descripción
La llave del partner en texto plano (mínimo 10 caracteres).
Si todas las compuertas pasan, la respuesta es el contexto de acceso
completo: credencial, cuenta, conexión, scopes, permissions y el
resumen del dpaContract vigente. Si alguna falla, el error identifica la
compuerta:
PARTNER_CREDENTIAL_INVALID(401) — la llave no existe o está revocada.PARTNER_CREDENTIAL_EXPIRED(401) — la credencial venció.PARTNER_CONNECTION_NOT_ACTIVE(403) — no hay conexión activa entre el partner y tu organización.PARTNER_WORKSPACE_NOT_ACTIVE(403) — la cuenta del partner está suspendida o pendiente de activación.PARTNER_DPA_NOT_ACTIVE(403) — no hay DPA vigente (o falta la declaración jurada, en conexiones de registro externo).
El formato general de los errores está en Errores.
Solicitud
curl https://app.edugoverna.com/api/integrations/authorize \
-H "x-api-key: {api_key}" \
-H "Content-Type: application/json" \
-d '{ "providedKey": "9e2a41d7-6c3b-4f0e-8a17-b5d4c2e8f901.f47ac10b58cc4372a5670e02b2c3d479" }'
Respuesta
{
"partnerCredentialId": "0b8e4c2a-5d1f-4a6b-8c3e-7f9d2a1b6c4e",
"partnerAccountId": "16fd2706-8baf-433b-82eb-8c7fada847da",
"organizationPartnerConnectionId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"scopes": [
{
"resourceNamespace": "subjects",
"scopeType": "read",
"conditions": null
}
],
"permissions": ["partner.consents.write", "partner.subjects.read"],
"dpaContract": {
"id": "a3bb189e-8bf9-3888-9912-ace4e6543002",
"versionNumber": 2,
"status": "active",
"executedAt": "2026-08-12T00:00:00.000Z",
"effectiveFrom": "2026-08-12T00:00:00.000Z",
"effectiveTo": null
}
}