Actualizado a agosto de 2025: si hoy publicas en Teams con el conector O365 (Incoming Webhook), la ruta soportada y de largo plazo es Workflows (Power Automate) en Microsoft Teams. A continuación verás qué cambia (URL, payload, seguridad), cómo migrar paso a paso y cómo diseñar tu configuración para que tu plugin no dependa de IDs frágiles ni de formatos transitorios.
Contexto y cronograma de retiro
Microsoft anunció la retirada de los Office 365 Connectors en Teams en dos oleadas durante 2024. El bloqueo de creación de nuevos conectores comenzó el 15‑ago‑2024 y el cese global anunciado para el 01‑oct‑2024 se amplió posteriormente. En 2025 Microsoft confirmó dos puntos clave: (1) los conectores basados en webhook debían actualizar su URL al nuevo formato antes del 31‑ene‑2025 para seguir funcionando; (2) el servicio de O365 Connectors en Teams se retirará al final de 2025. La recomendación oficial es migrar a Power Automate (Workflows) dentro de Teams, que aporta más control, seguridad y extensibilidad.
Hito | Fecha | Implicación |
---|---|---|
Bloqueo de creación de nuevos O365 Connectors | 15‑ago‑2024 | No crear nuevos webhooks de conector clásico. |
Actualización obligatoria de URL en conectores webhook (O365) | 31‑ene‑2025 | Actualizar la URL de los conectores existentes al nuevo formato para evitar interrupciones temporales. |
Fin de vida del servicio O365 Connectors (Teams) | Fin de 2025 | Migrar definitivamente a Workflows (Power Automate) u otra alternativa (bot, Graph, etc.). |
Traducción práctica: si tu plugin aún publica en Teams usando el conector O365, planifica la migración ahora. No dependas de nuevos parches sobre O365 Connectors; invierte directamente en Workflows.
Conectores de Microsoft Teams: O365 vs Workflows (Power Automate)
Resumen de la pregunta
¿Cómo migrar un plugin que hoy publica mensajes en Teams vía O365 (Incoming Webhook) hacia los Workflow connectors (Power Automate)?
Respuesta rápida
- Rumbo de plataforma: O365 Connectors salen de soporte; Workflows es la ruta soportada.
- URL: en Workflows cada flujo genera una URL completa y única. No existe una “base por tenant” que puedas reconstruir con un ID corto.
- Payload: probablemente necesites ajustar el JSON. El trigger de Workflows define el contrato de entrada; dentro del flujo usarás acciones de Teams para publicar el mensaje o la tarjeta.
- API para recuperar la URL: no hay una API pública y estable que, dado un ID corto, devuelva la URL completa del webhook de Workflows. Trátala como secreto y almacénala íntegra.
Comparativa esencial
Aspecto | O365 (Incoming Webhook) | Workflows (Power Automate) |
---|---|---|
Generación de URL | Se obtenía al crear el conector en el canal. Patrón estable por dominio “office.com/webhook…”. | Se genera al crear/guardar el flujo con trigger de webhook en Workflows. Incluye firma (sig ) y parámetros. |
Derivación por ID/tenant | Se podía reutilizar cierta lógica por grupo/canal; muchos sistemas guardaban fragmentos. | No derivable. Debes almacenar la URL completa. Cambia por entorno y lleva token firmado. |
Formato de payload | MessageCard (Office 365 Connector Card) en JSON. | Contrato definido por tu trigger. Normalmente JSON propio + acción de Teams para publicar mensaje o Adaptive Card. Soporte directo a messageCard anunciado como “en desarrollo” en 2025. |
Publicación en canales privados | Soportado desde el conector clásico. | Funcionalidad específica “en desarrollo” durante 2025 (según actualizaciones oficiales). Verifica en tu tenant. |
Seguridad | URL compartida con token. Difícil aplicar control de identidades. | Trigger con opciones: Cualquiera / Usuarios del tenant / Usuarios específicos. Posibilidad de exigir autenticación (y firmar payloads). |
Observabilidad | Limitada; logs en canal. | Historial de ejecuciones del flujo, métricas, errores, reintentos. |
Estructura de la URL y modelo de configuración
¿Cómo cambia la estructura del URL del webhook?
En O365, los webhooks de canal usaban dominios del tipo *.webhook.office.com
y contenían identificadores del grupo y del conector. Muchos equipos terminaban “reconstruyendo” la URL con fragmentos conocidos.
En Workflows, el trigger (por ejemplo, When a Teams webhook request is received) genera una URL extensa, con parámetros de versión y una firma criptográfica (sig
). Es típica la presencia de un host regional bajo logic.azure.com
y una ruta con /workflows/<flowId>/triggers/<triggerName>/paths/invoke?...&sig=<token>
. No es determinista ni derivable a partir de un ID corto.
¿Se puede construir el URL a partir de un identificador o base por tenant?
No. El dominio varía por región/entorno, la ruta incluye el flowId y los parámetros contienen la firma sig
. Por diseño, debes guardar el URL completo generado por el flujo.
¿Existe API pública para obtener el URL completo?
No hay una API pública documentada y estable que, a partir de un identificador corto, devuelva la URL completa del webhook de Workflows en Teams. A nivel operativo, la URL se copia desde la UI al crear/editar el flujo. Trátala como un secreto que puede rotarse.
Modelo de configuración recomendado
Define un repositorio de destinos desacoplado del código:
{
"destinations": [
{
"alias": "teams-prod-alerts",
"type": "teams-workflow-webhook",
"url": "https://<region>.logic.azure.com/workflows/<flowId>/triggers/teamswebhook/paths/invoke?...&sig=<token>",
"payloadContract": { "type": "myCompany.alert.v2", "schemaVersion": "2.1.0" },
"security": { "hmac": { "alg": "HMAC-SHA256", "sharedKeyRef": "kv:teams-prod-alerts" } },
"owner": "SRE",
"environment": "prod",
"rotation": { "lastRotated": "2025-06-10", "notes": "URL rotated after incident #1234" }
}
]
}
Ventajas: el usuario final sólo selecciona el alias
; tu plugin enruta al webhook correcto. El día que rotes la URL, no recompilas ni redeployas el plugin.
Payload y compatibilidad
¿Hay que cambiar el payload?
Es muy probable. En O365 enviabas MessageCard
. En Workflows defines tu propio esquema de entrada y, dentro del flujo, usas la acción de Teams para publicar mensaje o tarjeta.
Estrategia A: mantener el viejo JSON y transformar en el flujo
- Trigger: When a Teams webhook request is received.
- Acción: Parse JSON con un esquema que refleje tu
MessageCard
previo (al menossummary
,sections
,potentialAction
). - Acción: Compose para mapear al formato de una Adaptive Card 1.4 (o al texto simple si buscas simplicidad).
- Acción: Post card in chat or channel con el JSON de la Adaptive Card.
Estrategia B: contrato nuevo, limpio y versionado
Define un payload mínimo, claro y orientado a tu caso:
{
"type": "myCompany.alert",
"schemaVersion": "2.1.0",
"messageId": "a4c8b0a9-73e7-4d8c-b56a-0ea3a5bbf91e",
"occurredAt": "2025-08-17T11:23:45Z",
"severity": "high",
"source": "payments/api",
"title": "Fallo en conciliación",
"text": "Se detectaron 125 transacciones en estado pendiente > 15 min.",
"links": [
{ "title": "Abrir dashboard", "url": "https://dashboard-interno/..." }
]
}
En el flujo conviertes este JSON a una tarjeta (Adaptive Card) o a un mensaje con formato Markdown. Mantén el contrato versionado para introducir cambios sin romper integraciones.
Ejemplo de mapeo MessageCard → Adaptive Card
// Antes (fragmento)
{
"@type": "MessageCard",
"summary": "Build OK",
"themeColor": "0076D7",
"sections": [
{ "activityTitle": "API", "facts": [ {"name": "Duración", "value": "3m"} ] }
],
"potentialAction": [
{ "@type": "OpenUri", "name": "Ver pipeline", "targets": [ { "os": "default", "uri": "https://ci/..." } ] }
]
}
// Después (fragmento)
{
"\$schema": "[http://adaptivecards.io/schemas/adaptive-card.json](http://adaptivecards.io/schemas/adaptive-card.json)",
"type": "AdaptiveCard",
"version": "1.4",
"body": \[
{ "type": "TextBlock", "size": "Medium", "weight": "Bolder", "text": "Build OK" },
{ "type": "FactSet", "facts": \[ { "title": "Servicio", "value": "API" }, { "title": "Duración", "value": "3m" } ] }
],
"actions": \[
{ "type": "Action.OpenUrl", "title": "Ver pipeline", "url": "https\://ci/..." }
]
}
Nota 2025: Microsoft comunicó que trabaja en soporte para publicar messageCard
directamente desde Workflows (evitando la conversión), así como publicación a canales privados. Verifica disponibilidad en tu inquilino antes de asumirlo en producción.
Buenas prácticas de contrato
- Encabezado:
type
,schemaVersion
,messageId
(idempotencia),occurredAt
(ISO‑8601),source
,severity
. - Validación: usa Parse JSON y devuelve
4xx
con detalle si falta un campo. - Compatibilidad: añade un campo
compat
para banderas temporales (p.ej.,acceptsMessageCard
).
Estrategias de integración
- Endpoints separados: mantener endpoint legado para O365 y otro para Workflows. Sencillo en transición; desactivar el legado antes de fin de 2025.
- Gestión de configuración (recomendada): repositorio
alias → URL completa
+ metadatos (versión de payload, seguridad, propietario, entorno). El plugin enruta por alias. - Híbrido: soporta temporalmente parámetros heredados (p.ej.,
groupId
) y, en paralelo, alias con URL de Workflow. Úsalo solo como puente.
Guía paso a paso de migración
- Crear el flujo en la app Workflows de Teams:
- Elige el trigger When a Teams webhook request is received (o “Post to a channel/chat when a webhook request is received” desde plantilla).
- Selecciona el tipo de autenticación: Cualquiera, Usuarios del tenant o Usuarios específicos. Si eliges autenticado, planifica cómo firmará tu plugin (token u HMAC). Para el trigger HTTP genérico, revisa opciones de OAuth en tu región.
- Definir el esquema del payload (usa “Generate from sample” para acelerar).
- Publicar a Teams:
- Acción: Post card in chat or channel (Adaptive Card) o Post message in a chat or channel.
- Si migras desde MessageCard, añade un paso de transformación.
- Copiar el URL completo del webhook y guardarlo en tu secreto de configuración (Key Vault/Secret Manager).
- Actualizar el plugin:
- Soporta alias y busca el URL en el repositorio seguro.
- Configura timeouts, retries con backoff y traza un
correlationId
por envío.
- Probar end‑to‑end con datos reales. Automatiza pruebas de contrato (validación de esquema).
- Monitorear métricas (éxito, latencia, errores) y retirar la ruta O365 antes del fin de 2025.
Seguridad y cumplimiento
- Protección de URL: guarda la URL como secreto (cifrado en reposo). Considera un formato de referencia (
kv:alias
) en tu config. - Autenticación del trigger:
- Workflows (Teams webhook): restringe a usuarios del tenant o a usuarios específicos cuando sea posible.
- Trigger HTTP genérico: opciones de OAuth/identidades de servicio (despliegue progresivo por regiones). Confirma disponibilidad.
- Firma del payload: añade cabecera
X-Signature
con HMAC‑SHA256 del cuerpo. Verifícala en el flujo (expresión, Azure Function o Power Fx). - Permisos mínimos en la acción de Teams y propietario del flujo (evita cuentas personales; usa service accounts gestionadas).
- Auditoría: registra quién crea/lee/rota cada URL; emite
correlationId
en los logs del plugin y del flujo. - Rate limiting: controla ráfagas; define tamaño máximo del payload; comprime si es necesario.
Patrones de implementación
Enrutamiento por alias en el plugin
// Pseudocódigo
const url = secrets.getByAlias("teams-prod-alerts"); // Recupera URL completa
const body = buildPayload(event); // Tu JSON versionado
const headers = {
"Content-Type": "application/json",
"X-Correlation-Id": correlationId(),
"X-Signature": hmacSha256Hex(sharedKey("teams-prod-alerts"), JSON.stringify(body))
};
http.post(url, body, { headers, timeoutMs: 5000 });
Validación de firma en el flujo
En el trigger, extrae headers['X-Signature']
. Con una expresión calcula el HMAC del triggerBody()
(o invoca un paso auxiliar) y compara. Devuelve 401
/403
si no coincide. Mantén la clave en un vault.
Respuestas con detalle
// Estructura recomendada de respuesta del flujo
{
"correlationId": "8f7c1b2d-...-c4d5",
"accepted": true,
"warnings": [],
"next": "queued"
}
Errores frecuentes y cómo depurarlos
- 404 / 401 al llamar al webhook: URL caducada/rotada o trigger con autenticación de usuario y el plugin no envía token. Revisa el tipo de autenticación.
- 415 Unsupported Media Type: faltó
Content-Type: application/json
. - 400 de validación: el Parse JSON rechaza campos. Valida contra el esquema y usa
schemaVersion
para bifurcar. - Duplicados: reintentos sin idempotencia. Incluye
messageId
y deduplica en el flujo. - URL truncada: columnas cortas (p.ej.,
VARCHAR(255)
). Usa tipos largos; verifica longitud (>1000). - Publicación en canal privado: comprueba si tu tenant ya tiene soporte en Workflows o usa alternativas (bot/Graph) mientras tanto.
Preguntas y respuestas específicas
¿Cómo cambia la estructura del URL del webhook?
De una URL “reconstruible” por patrón en O365 a una URL firmada y única por flujo en Workflows. La nueva incluye host regional, identificador del flujo/trigger y query con sig
. No la infieras; guárdala completa.
¿Se puede construir el URL a partir de un identificador alfanumérico o base por tenant?
No. La seguridad y el direccionamiento dependen de la firma y de la región/entorno. No hay “base por tenant” que puedas combinar con un ID corto.
¿Hay que cambiar el payload?
Normalmente sí. Tu flujo define el contrato. Si quieres preservar compatibilidad, parsea el MessageCard
y transforma a Adaptive Card antes de publicar. Si puedes, adopta un contrato nuevo y versionado.
¿Existe API para obtener el URL completo?
No hay una API pública, estable y soportada que devuelva el URL de los webhooks de Workflows para Teams a partir de un identificador corto. Trata el URL como un secreto operativo: se copia desde la UI y se rota bajo control.
Plan de migración recomendado
- Crear un workflow en Power Automate (Workflows en Teams) con disparador de webhook y definir el esquema JSON esperado.
- Configurar la acción de Teams (mensaje o tarjeta).
- Copiar el URL completo del webhook del flujo y registrarlo en tu sistema (alias + secretos + versión de payload).
- Actualizar el plugin para enrutar por alias. Mantener temporalmente ruta O365 si aún la necesitas, pero con fecha de caducidad antes de fin de 2025.
- Implementar reintentos, timeouts, validación de esquema y idempotencia.
- Probar extremo a extremo con muestras reales; automatizar pruebas de contrato.
- Desplegar, monitorear y retirar definitivamente la ruta O365.
Modelo de operación y rotación
- Rotación segura: crea una segunda URL (nuevo flujo o regeneración) y alterna alias → URL. Haz un health check (prueba de publicación) antes del cutover.
- Trazabilidad: registra en el flujo la URL lógica (
alias
) y elcorrelationId
para auditoría. - Backoff y circuit‑breaker: si recibes muchos
429
/5xx
, corta temporalmente y alerta; evita bucles de reintento.
Plantillas de tablas útiles
Checklist de migración
Ítem | Estado | Notas |
---|---|---|
Inventario de webhooks O365 | — | Equipo/Canal/Propietario |
Diseño de contrato JSON | — | Versionado y validación |
Creación de flujos Workflows | — | Trigger y autenticación |
Acción de publicación en Teams | — | Mensaje o Adaptive Card |
Repositorio alias → URL | — | Secret manager |
Firma HMAC / OAuth | — | Clave y validación |
Pruebas de contrato | — | Esquemas y datos reales |
Monitoreo y alertas | — | Métricas y logs |
Plan de rotación de URL | — | Ensayo + cutover |
Retiro de ruta O365 | — | Antes de fin de 2025 |
FAQ de decisiones arquitectónicas
- ¿Uso el trigger “Teams webhook” o el “HTTP request” genérico? Para reemplazar O365 Connectors en Teams, el de Teams suele ser suficiente y más simple. El HTTP genérico aporta flexibilidad extra (por ejemplo, OAuth), a costa de licenciamiento y configuración.
- ¿Puedo seguir usando
MessageCard
? En general, migra a Adaptive Cards. Hay comunicaciones de soporte futuro amessageCard
en Workflows, pero confírmalo en tu tenant. - ¿Cómo administro la propiedad del flujo? Usa cuentas de servicio administradas y políticas de traspaso. Evita cuentas personales para evitar bloqueos.
- ¿Qué pasa con canales privados? Verifica disponibilidad en tu entorno. Mientras tanto, considera un bot o Graph si necesitas enviar a privados hoy.
TL;DR actualizado
- O365 Connectors en Teams: bloqueados para creación desde 15‑ago‑2024; fin de vida al cierre de 2025. Si sigues con O365, migra.
- URL en Workflows: única por flujo, firmada y no derivable. No hay API pública para reconstruirla; guárdala completa.
- Payload: define tu contrato o transforma el antiguo en el propio flujo.
- Estrategia: repositorio
alias → URL
+ contrato versionado + pruebas de esquema + firma/seguridad.
Bonus: ejemplo de política de validación en el flujo
// Pseudolenguaje (expresión)
expectedHmac = hmacSha256(
base64ToBinary(variables('sharedKeyBase64')),
string(triggerBody())
)
if (toLower(headers('X-Signature')) != toLower(expectedHmac)) {
return 401
}
Con esto, tu plugin puede migrar de forma ordenada y segura, sin romper a los usuarios, y quedando alineado con el modelo soportado por Microsoft: Workflows en Teams.