Con los webhooks, Read puede enviar notas de reuniones y datos de informes a un endpoint personalizado para que otras herramientas o servicios reciban automáticamente las actualizaciones de las reuniones. Cuando un informe está disponible, Read envía una solicitud de webhook que contiene los datos de la reunión al endpoint configurado.
Hay dos tipos de webhooks:
- Webhooks de usuario envían los informes de reuniones de un solo usuario (la persona que creó el webhook). Cualquier usuario puede configurarlos para sus propias reuniones.
- Webhooks del espacio de trabajo envían los informes de reuniones de cada usuario del espacio de trabajo a un único endpoint. Los administradores y propietarios del espacio de trabajo crean y administran estos webhooks.
Si es necesario, un usuario también puede activar manualmente un webhook desde el informe de una reunión individual.
Requisitos previos
- Los webhooks solo están disponibles en los planes Pro, Enterprise y Enterprise+.
- Los usuarios deben verificar su dirección de correo electrónico antes de crear webhooks.
- Hay un máximo de 20 webhooks por usuario y un máximo independiente de 20 webhooks del espacio de trabajo; cuando se alcanza un límite, es necesario eliminar los webhooks antiguos para crear otros nuevos.
- Solo los administradores y propietarios del espacio de trabajo pueden crear o editar webhooks del espacio de trabajo.
Webhooks de usuario frente a webhooks del espacio de trabajo
| Webhooks de usuario | Webhooks del espacio de trabajo | |
|---|---|---|
| Quién puede crear o editar | Cualquier usuario | Solo los administradores y propietarios del espacio de trabajo |
| Dónde configurarlos | Integraciones → pestaña Tus integraciones → Webhooks | Integraciones → pestaña Espacio de trabajo → Webhooks |
| Informes enviados | Solo los informes del usuario que lo creó | Informes de todos los miembros del espacio de trabajo |
trigger opciones
|
meeting_end |
meeting_start, meeting_end
|
| Envío manual desde un informe | Disponible para el usuario que lo creó | Disponible para todos los miembros del espacio de trabajo |
| Esquema de la carga útil | Esquema estándar | El mismo esquema estándar |
| Límite | 20 por usuario | 20 por espacio de trabajo (límite independiente) |
Ambos tipos de webhook comparten el mismo esquema de carga útil y el mismo proceso de verificación de firma. Las principales diferencias son quién puede configurarlos y los informes de quién envían.
Los webhooks solo se activan para los informes a los que un miembro tenía acceso directo en el momento en que se creó el informe. No se activan para los informes que un miembro solo puede ver mediante Acceso a informes del equipo o Acceso global a informes (acceso indirecto).
Webhooks automatizados frente a webhooks manuales
Los webhooks automatizados se activan cuando el informe de la reunión se genera correctamente después de que finaliza una reunión. Debes tener al menos acceso de «Viewer» al informe en el momento de la reunión; por lo tanto, no funcionará si obtuviste acceso después de la reunión. Por lo general, solo se activa una vez por informe. Si tu endpoint devuelve un código de estado HTTP que no sea 2xx, Read vuelve a intentar la solicitud con una espera exponencial (consulta ¿Los webhooks vuelven a intentarlo automáticamente cuando se produce un error? más abajo). Si los envíos siguen fallando, el webhook cambia al estado «Stopped» (consulta ¿Por qué mi webhook aparece como «stopped»? más abajo).
Los webhooks manuales los activa un usuario desde la página de un informe. También funcionan si obtuviste acceso al informe después de la reunión, pero necesitas al menos acceso de «Editor». Siempre que tengas al menos un webhook configurado, abre el informe, haz clic en Enviar a... y selecciona Webhooks. En la ventana emergente Enviar al webhook, elige el webhook al que quieres enviar el informe y haz clic en Enviar al webhook. Cuando se haya enviado correctamente, verás un mensaje de confirmación.
Pasos para configurar webhooks
1. Ve a la página Integraciones
¿Estás configurando un webhook del espacio de trabajo? Los administradores y propietarios del espacio de trabajo administran estos webhooks en la pestaña Espacio de trabajo de la página Integraciones. Los pasos restantes (nombre, URL, clave de firma, prueba y activación) son idénticos.
2. En la sección Webhooks, haz clic en «Crear webhook»
Si estás creando un webhook del espacio de trabajo, también se te pedirá que reconozcas y confirmes que comprendes los riesgos antes de continuar.
3. Introduce un nombre y una URL para el webhook
No uses caracteres Unicode ni emojis UTF-8 en el nombre y asegúrate de proporcionar una URL HTTPS. La aplicación de esta URL debe estar configurada para recibir una carga útil JSON con nuestro esquema estándar.
Si estás creando un webhook del espacio de trabajo, también tendrás la opción de activarlo cuando comience una reunión y deberás seleccionar al menos una de las opciones de activación.
4. (Opcional) Copia tu clave de firma
Como práctica recomendada de seguridad, generamos una clave de firma única para cada webhook que crees. Más adelante puedes usar esta clave de firma para verificar que las llamadas recibidas por tu endpoint personalizado proceden realmente de Read AI (más información a continuación).
5. (Opcional) Prueba tu webhook
Te recomendamos hacer una prueba en este momento para detectar los problemas lo antes posible. Haz clic en el menú de tres puntos situado junto a tu webhook y selecciona Enviar llamada de prueba para activar una solicitud con datos ficticios. Para probarlo con datos reales de una reunión, abre un informe antiguo y activa el webhook manualmente.
Si encuentras algún problema, asegúrate de que tu endpoint esté activo y configurado correctamente para devolver un código de estado HTTP 2xx cuando reciba una carga útil JSON con nuestro esquema estándar.
6. Celebra una reunión y observa el flujo de datos
Ten en cuenta que el estado seguirá apareciendo como «Pending» hasta que envíes tu primera carga útil real correspondiente a una reunión. Siempre que la URL proporcionada responda correctamente al webhook cuando se active, el estado cambiará a «Active».
Verificación de solicitudes de webhook
Para ayudar a garantizar que las solicitudes de webhook que recibes realmente las envía Read AI, cada envío de webhook incluye una firma criptográfica. Puedes utilizar la clave de firma proporcionada en la configuración del webhook para verificar que la solicitud se originó en Read AI y no se modificó durante el tránsito. Ten en cuenta que esta función solo está disponible para los webhooks nuevos creados después del 17 de marzo de 2026.
Cómo funciona
Cuando Read AI envía un webhook, calculamos una firma usando la clave de firma de tu webhook y el cuerpo sin procesar de la solicitud. La firma resultante se incluye en el encabezado de la solicitud X-Read-Signature.
En tu servidor, puedes calcular independientemente la misma firma utilizando la clave de firma. Si el valor calculado coincide con la firma incluida en la solicitud del webhook, la carga útil es auténtica.
Pasos para verificar un webhook
-
Obtén la clave de firma de tu webhook
En la configuración del webhook de Read AI, verás una clave de firma asociada a tu endpoint de webhook. Guarda esta clave de forma segura y úsala únicamente en tu servidor al verificar las solicitudes de webhook. -
Lee el cuerpo sin procesar de la solicitud
Captura la carga útil exacta y sin procesar enviada a tu endpoint. No la modifiques, reformatees ni analices antes de verificarla, ya que la firma se calcula utilizando el cuerpo original sin procesar. -
Extrae el encabezado de firma
Lee el valor del encabezadoX-Read-Signaturede la solicitud entrante. Este encabezado contiene la firma HMAC generada por Read AI. -
Calcula tu propia firma
Usando la clave de firma de tu webhook, calcula un hash HMAC SHA‑256 del cuerpo sin procesar de la solicitud. -
Compara las firmas
Compara la firma que calculaste con el valor del encabezadoX-Read-Signature. Si coinciden, Read AI envió la solicitud y la carga útil no ha sido manipulada.
Nota: Los webhooks también contienen una propiedad request_id única en el cuerpo, que puede utilizarse para detectar e ignorar cargas útiles duplicadas y evitar ataques de repetición.
Código de ejemplo de verificación
Python
import base64
import hmac
import hashlib
import os
# Replace with the body of the request
body = b'{...}'
# Replace with the value of the X-Read-Signature header received on each request
header_sig = "d2f733f07d3862f707e761be1b72c6533133977307abf272dabb66addfbec9a1"
# ⚠️ IMPORTANT: Store the signing key in a secure location (for example a secrets manager or an environment variable), never in code.
signing_key = os.environ["READ_WEBHOOK_SIGNING_KEY"]
key_bytes = base64.b64decode(signing_key)
digest = hmac.new(key_bytes, body, hashlib.sha256).hexdigest()
if hmac.compare_digest(digest, header_sig.lower()):
print("✅ Signature verified. This request came from Read AI!")
else:
print("❌ Signature verification failed!")
JavaScript
const crypto = require('crypto');
// Replace with the body of the request
const body = '{...}';
// Replace with the value of the X-Read-Signature header received on each request
const headerSig = "d2f733f07d3862f707e761be1b72c6533133977307abf272dabb66addfbec9a1";
// ⚠️ IMPORTANT: Store the signing key in a secure location (for example a secrets manager or an environment variable), never in code.
const signingKey = process.env.READ_WEBHOOK_SIGNING_KEY;
const keyBytes = Buffer.from(signingKey, 'base64');
const digest = crypto.createHmac('sha256', keyBytes)
.update(body, 'utf8')
.digest('hex');
const expected = Buffer.from(digest);
const received = Buffer.from(headerSig.toLowerCase());
// timingSafeEqual throws if the lengths differ, so check the length first
if (expected.length === received.length && crypto.timingSafeEqual(expected, received)) {
console.log("✅ Signature verified. This request came from Read AI!");
} else {
console.log("❌ Signature verification failed!");
}Go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
"os"
"strings"
)
func main() {
// Replace with the body of the request
body := []byte("{...}")
// Replace with the value of the X-Read-Signature header received on each request
headerSig := "d2f733f07d3862f707e761be1b72c6533133977307abf272dabb66addfbec9a1"
// ⚠️ IMPORTANT: Store the signing key in a secure location (for example a secrets manager or an environment variable), never in code.
signingKey := os.Getenv("READ_WEBHOOK_SIGNING_KEY")
keyBytes, err := base64.StdEncoding.DecodeString(signingKey)
if err != nil {
panic(err)
}
h := hmac.New(sha256.New, keyBytes)
h.Write(body)
digest := hex.EncodeToString(h.Sum(nil))
if hmac.Equal([]byte(digest), []byte(strings.ToLower(headerSig))) {
fmt.Println("✅ Signature verified. This request came from Read AI!")
} else {
fmt.Println("❌ Signature verification failed!")
}
}
Ruby
require 'openssl'
require 'base64'
# Replace with the body of the request
body = '{...}'
# Replace with the value of the X-Read-Signature header received on each request
header_sig = "d2f733f07d3862f707e761be1b72c6533133977307abf272dabb66addfbec9a1"
# ⚠️ IMPORTANT: Store the signing key in a secure location (for example a secrets manager or an environment variable), never in code.
signing_key = ENV.fetch("READ_WEBHOOK_SIGNING_KEY")
key_bytes = Base64.decode64(signing_key)
digest = OpenSSL::HMAC.hexdigest('SHA256', key_bytes, body)
if OpenSSL.secure_compare(digest, header_sig.downcase)
puts "✅ Signature verified. This request came from Read AI!"
else
puts "❌ Signature verification failed!"
end
Prácticas recomendadas
- Verifica siempre las firmas de los webhooks antes de procesar la carga útil.
- Rechaza las solicitudes que no incluyan firmas
X-Read-Signatureo cuyas firmas no sean válidas. - Guarda la clave de firma de forma segura y nunca la expongas en código del lado del cliente.
- Utiliza una función de comparación segura frente a ataques de temporización al comparar firmas.
Esquema
Propiedades JSON
Cada vez que se activa un webhook, Read envía una solicitud HTTP POST con una carga útil JSON sin procesar en el cuerpo, que contiene las siguientes propiedades de nivel superior:
-
session_id: Identificador único de la sesión de la reunión -
trigger: El evento que activó el webhook —meeting_endomeeting_start(solo webhooks del espacio de trabajo). Ten en cuenta que activar manualmente un webhook desde un informe siempre envíameeting_end. -
title: El título de la reunión -
start_time: La hora de inicio de la reunión en formato UTC -
end_time: La hora de finalización de la reunión en formato UTC -
participants: Una matriz de participantes de la reunión -
owner: El propietario de la reunión -
summary: El resumen general de la reunión -
action_items: Una matriz de elementos de acción tratados durante la reunión -
key_questions: Una matriz de preguntas clave planteadas durante la reunión -
topics: Una matriz de temas tratados en la reunión -
report_url: Una URL al informe de la reunión en la interfaz web de Read -
chapter_summaries: Resúmenes más detallados de la reunión, divididos en capítulos secuenciales junto con sus temas asociados. -
transcript: La transcripción completa de la reunión, incluidos los nombres de los oradores y las marcas de tiempo en tiempo Unix (milisegundos). -
platform_meeting_id: El ID único de esta reunión en, por ejemplo, Teams, Zoom o Meet -
platform: La plataforma desde la que se grabó la reunión (ten en cuenta que las grabaciones de la aplicación de escritorio o móvil de Read AI siempre indicarán esa aplicación como la plataforma) -
request_id: ID único generado para cada solicitud, que puede utilizarse para ignorar cargas útiles duplicadas y evitar ataques de repetición.
Cargas útiles de «inicio de reunión»
Los webhooks del espacio de trabajo también pueden activarse al inicio de una reunión. Como todavía no existe ningún informe, una carga útil meeting_start contiene únicamente el siguiente subconjunto del esquema estándar:
session_id-
trigger("meeting_start") titlestart_timeownerplatformplatform_meeting_idrequest_id
Los demás campos (como end_time, summary, action_items, topics, chapter_summaries, transcript y report_url) no están presentes al inicio de la reunión. Los envíos de meeting_start se firman con el mismo encabezado X-Read-Signature, por lo que debes verificarlos exactamente como verificarías una carga útil de meeting_end.
Ejemplo de carga útil
Este es un ejemplo de carga útil, que debería ser muy similar a la carga útil enviada en una solicitud de prueba de webhook.
{
"session_id": "SESSIONID",
"trigger": "meeting_end",
"title": "Meeting Title",
"start_time": "2026-01-01T00:00:00Z",
"end_time": "2026-01-01T01:00:00Z",
"participants": [
{
"name": "Participant One",
"first_name": "Participant",
"last_name": "One",
"email": "participant_one@company.com"
},
{
"name": "Participant Two",
"first_name": "Participant",
"last_name": "Two",
"email": null
}
],
"owner": {
"name": "Participant One",
"first_name": "Participant",
"last_name": "One",
"email": "participant_one@company.com"
},
"summary": "Meeting summary goes here...",
"action_items": [
{
"text": "Action item one"
},
{
"text": "Action item two"
}
],
"key_questions": [
{
"text": "Key question one?"
},
{
"text": "Key question two?"
}
],
"topics": [
{
"text": "Topic one"
},
{
"text": "Topic two"
}
],
"report_url": "https://app.read.ai/analytics/meetings/SESSIONID",
"chapter_summaries": [
{
"title": "Chapter one",
"description": "First chapter description",
"topics": [
{
"text": "Topic one"
}
]
},
{
"title": "Chapter two",
"description": "Second chapter description",
"topics": [
{
"text": "Topic two"
}
]
}
],
"transcript": {
"speaker_blocks": [
{
"start_time": "1719514000000",
"end_time": "1719514001000",
"speaker": {
"name": "Speaker 1"
},
"words": "Good morning everyone!"
},
{
"start_time": "1719514002000",
"end_time": "1719514003000",
"speaker": {
"name": "Speaker 2"
},
"words": "Hi!"
}
],
"speakers": [
{
"name": "Speaker 1"
},
{
"name": "Speaker 2"
}
]
},
"platform_meeting_id": "abc-defg-hij",
"platform": "meet",
"request_id": "01KKVQZ19X57NMNFTS8YXJNZE4"
}
Preguntas frecuentes
¿Por qué no recibo webhooks para algunas de mis reuniones?
Los webhooks solo se activan automáticamente cuando se crea un informe por primera vez y únicamente para los informes a los que tenías acceso directo en ese momento. No se activan cuando los informes se comparten contigo más tarde o si obtuviste acceso únicamente mediante Acceso a informes del equipo o Acceso global a informes (que se consideran acceso indirecto).
¿Pueden los webhooks enviar informes generados a partir de cargas de archivos?
No, los webhooks (tanto automáticos como manuales) están diseñados para los informes de reuniones estándar; los informes generados a partir de cargas de archivos no los activan.
¿Puedo obtener acceso a todos los informes de mi equipo o espacio de trabajo mediante webhooks?
Sí. Los webhooks del espacio de trabajo envían los informes de reuniones de cada miembro del espacio de trabajo a un único endpoint. Solo los administradores y propietarios del espacio de trabajo pueden crearlos y editarlos desde la pestaña Espacio de trabajo de la página Integraciones.
¿Los webhooks vuelven a intentarlo automáticamente cuando se produce un error?
Sí. Si tu endpoint devuelve cualquier código de estado fuera del intervalo 2xx, Read vuelve a intentar la solicitud hasta 5 veces con una espera exponencial, para un total de 6 intentos.
¿Por qué mi webhook no incluye una firma?
Las firmas se añadieron a los webhooks de Read en marzo de 2026, por lo que los webhooks generados antes de esa fecha no las incluirán. Para obtener firmas y verificar estos webhooks antiguos, tendrás que eliminarlos y volver a crearlos.
¿Por qué mi webhook aparece como «stopped»?
Si Read intenta enviar datos a un webhook y no lo consigue, después de 25 fallos consecutivos Read desactiva automáticamente el webhook y lo marca como «stopped».
Los webhooks solo están disponibles en los planes de pago, por lo que, si tu suscripción finaliza por cualquier motivo, tus webhooks también dejarán de funcionar.
Si esto ocurre, es posible que tengas que eliminar y volver a crear el webhook para activarlo de nuevo.