Saltar al contenido principal
POST /meeting-notes Envía la salida de un tomador de notas — transcripción cruda, resumen, recapitulación enriquecida con IA, items de acción — contra una reunión existente. Diseñado para webhooks de Fathom, Granola, Otter, Zoom AI Companion, o cualquier flujo de toma de notas interno (Make / Zapier / personalizado). La nota se adjunta a un calendar_event que ya existe en Nexor. Sin notas huérfanas en v1 — si ninguna reunión se resuelve, obtienes un 404.

Resolución de reunión

El endpoint intenta lo siguiente en orden, deteniéndose en la primera coincidencia:
  1. calendar_event_id — directo.
  2. external_calendar_provider + external_calendar_event_id — coincide reuniones creadas vía POST /meetings con esas claves de dedup.
  3. meeting_url — coincidencia exacta con la URL de reunión del calendar_event.
  4. lead_email + meeting_date — reunión del lead dentro de +-60 minutos de meeting_date.
  5. lead_email solo — la reunión pasada más reciente del lead. Sin límite de ventana de tiempo.
Si ninguna resuelve una reunión -> 404. Crea la reunión primero vía POST /meetings o pasa un identificador válido.

Idempotencia

Si proporcionas external_meeting_id junto con un provider, repeticiones del mismo (provider, external_meeting_id) bajo tu cliente actualizan la fila existente en lugar de crear duplicados. Seguro para reintentos de webhook. La actividad note_added en la línea de tiempo solo se dispara en la primera inserción, no en repeticiones.

Proveedores reservados

Los siguientes valores se rechazan para proteger los pipelines de sincronización internos: fireflies, diio, gemini, retell. Escoge cualquier otro string alfanumérico en minúsculas (ej. fathom, granola, otter, manual, zoom_ai). Regex: ^[a-z0-9_-]{1,64}$.

Cuerpo de la Solicitud

Todos los campos son opcionales a menos que se indique. Como mínimo debes proporcionar:
  • una forma de resolver una reunión (calendar_event_id, external_calendar_event_id+external_calendar_provider, meeting_url, o lead_email), y
  • un campo de contenido no vacío (notes, transcript_text, summary, manual_ai_summary, o action_items).
CampoTipoDescripción
providerstringOrigen de la nota. Por defecto "manual". Nombres reservados son rechazados.
external_meeting_idstringID estable del tomador de notas (ej. Recording ID de Fathom). Habilita repetición idempotente. ≤ 255 caracteres.
calendar_event_idstring (uuid)Enlace directo — resolución nivel 1.
external_calendar_providerstringPar con external_calendar_event_id — nivel 2.
external_calendar_event_idstringID del evento del proveedor desde POST /meetings.
meeting_urlstringURL de Meet / Zoom / Fathom — nivel 3.
lead_emailstringCoincide con el lead (alcance de cliente); también impulsa niveles 4 y 5.
meeting_datestring (ISO 8601)Usado con lead_email para coincidencia difusa de +-60 min.
meeting_titlestring
duration_secondsinteger
organizer_emailstringEmail del anfitrión.
notesstringTexto libre crudo. Alias de transcript_text — si ambos se proporcionan, transcript_text gana. ≤ 1 MB.
transcript_textstringTranscripcion completa. ≤ 1 MB.
summarystringResumen nativo del tomador de notas (recapitulación de Fathom / Granola / Otter).
manual_ai_summarystringResumen personalizado enriquecido con IA (ej. paso posterior con ChatGPT en Make). Se almacena separado de summary.
action_itemsarray["Send pricing", ...] o [{ text, assignee }, ...]. ≤ 512 KB.
questionsarray["What's the monthly cost?", ...]. ≤ 512 KB.
keywordsarray["pricing", "enterprise", ...]. ≤ 512 KB.
sentencesarrayEnunciados a nivel de hablante (formato compatible con Fireflies). ≤ 512 KB.
statusstringcompleted (por defecto), pending o failed.

Cuerpo de la Solicitud — texto libre mínimo

Ideal para escenarios de Make / Zapier que construyen un blob markdown y lo adjuntan a la reunión más reciente del lead:
{
  "lead_email": "tony.stark@gmail.com",
  "notes": "Revisamos propuesta. Cliente preguntó por plazos de implementación. Budget Q2 aprobado.",
  "manual_ai_summary": "Alta intención. Enterprise. Siguiente paso: propuesta formal antes del viernes."
}

Cuerpo de la Solicitud — Webhook de Fathom vía Make

Usando la salida del trigger “Watch New Recordings” de Fathom mapeada a campos de la API:
{
  "provider": "fathom",
  "external_meeting_id": "133148102",
  "meeting_url": "https://fathom.video/call/133148102",
  "meeting_title": "Discovery — Stark Industries",
  "meeting_date": "2026-04-15T17:18:02Z",
  "organizer_email": "pepper@starkindustries.com",
  "lead_email": "tony.stark@gmail.com",
  "summary": "## Deal Information\n### Prospect\n[...Fathom markdown summary...]",
  "manual_ai_summary": "ChatGPT-enriched recap: strong buying intent, Q2 budget confirmed.",
  "action_items": ["Send pricing by Friday", "Intro CTO for technical deep-dive"]
}
Resolviendo lead_email en Make: El flag is_external de Fathom no es confiable (el anfitrión a veces se marca como externo). Filtra Calendar Invitees[] por dominio en su lugar:
Array filter:
  Input:      Calendar Invitees[]
  Condition:  email_domain  ≠  {{Recorded By.email_domain}}

Then:
  lead_email = {{first(filtered).Email}}

Respuesta — 201 Created (o 200 en repetición upsert)

{
  "success": true,
  "upserted": false,
  "meeting_note": {
    "id": "0f9230e0-a5e3-4245-8995-afc61007c992",
    "client_id": "2c0911d1-25f9-47c2-8795-fe9407b8d67e",
    "calendar_event_id": "5a76ac77-523d-4100-843c-1105212de877",
    "lead_id": "0433aeee-44af-4148-9ca0-9e2ac41501a7",
    "provider": "manual",
    "external_meeting_id": null,
    "meeting_title": null,
    "meeting_date": "2025-12-29T17:00:00+00:00",
    "duration_seconds": null,
    "organizer_email": null,
    "summary": null,
    "manual_ai_summary": "Alta intención. Siguiente paso: propuesta formal antes del viernes.",
    "transcript_text": "Revisamos propuesta. Budget Q2 aprobado. Interés Enterprise.",
    "action_items": null,
    "questions": null,
    "keywords": null,
    "status": "completed",
    "created_at": "2026-04-15T20:52:35.426356+00:00",
    "updated_at": "2026-04-15T20:52:35.426356+00:00"
  }
}
upserted es true cuando una fila previa con el mismo (provider, external_meeting_id) fue actualizada en lugar de insertar una nueva fila.

Línea de Tiempo

En la primera inserción, una actividad note_added se escribe en la línea de tiempo del lead con un enlace a la fila meeting_transcripts creada. Las repeticiones no emiten actividades duplicadas.

Códigos de Error

CódigoSignificado
400Campo faltante o inválido; proveedor reservado; payload excede límites de tamaño; sin campos de contenido; nada para resolver la reunión
401X-API-Key faltante o inválida
404Ningún calendar_event resuelto vía ninguna de las 5 estrategias
409(provider, external_meeting_id) ya vinculado a un calendar_event diferente
500Error inesperado del servidor
Última modificación el 18 de junio de 2026