Cómo integrar la API de OpenAI con un CRM de forma segura

Integrar la API de OpenAI con un CRM puede ayudar a resumir mensajes, identificar la intención declarada por un contacto y proponer el siguiente paso para revisión. No debería convertir al modelo en la autoridad que decide quién merece una oferta, un empleo, un crédito, una vivienda, una póliza o una atención sanitaria. La salida es una recomendación probabilística y debe pasar por validaciones de código y, cuando afecte a personas, por supervisión humana proporcional al riesgo.

Esta guía usa la Responses API y Structured Outputs con Pydantic. Así se evita pedir «JSON libre» y ejecutar json.loads confiando en que el texto siempre tendrá la forma esperada. El SDK valida la respuesta contra un esquema conocido y entrega un objeto tipado, pero la aplicación aún debe manejar refusals, interrupciones, campos ausentes y errores del proveedor.

Casos de uso razonables y límites

  • Resumen: condensar un correo o una nota para que una persona lo revise.
  • Enrutamiento: proponer si el mensaje corresponde a ventas, soporte, información o baja.
  • Extracción: localizar datos que el propio contacto declaró, marcando lo que necesita confirmación.
  • Borrador: preparar una respuesta que un agente pueda editar y aprobar.
  • Control de calidad: comprobar si una nota contiene los elementos internos exigidos, sin inventar los que faltan.

No uses el modelo como única base para puntuar el valor de una persona, aplicar precios individualizados sensibles, descartar candidatos, priorizar pacientes, aprobar crédito o tomar otras decisiones de alto impacto. Tampoco infieras atributos sensibles —salud, religión, origen, orientación, ideología o situación económica— a partir del lenguaje. Incluso en ventas ordinarias, una clasificación automática puede estar equivocada o amplificar sesgos; muéstrala como sugerencia, conserva trazabilidad y permite corregirla.

Arquitectura segura

El CRM envía un webhook firmado a un endpoint propio. Ese endpoint verifica la firma, registra un identificador técnico y coloca el trabajo en una cola. Un worker recupera únicamente los campos permitidos, elimina datos innecesarios, llama a OpenAI, valida la estructura y guarda una propuesta separada. Una persona la revisa antes de escribir campos que disparen automatizaciones o comunicaciones.

  1. Verificar firma, marca temporal y origen del webhook.
  2. Rechazar eventos repetidos mediante el identificador del CRM.
  3. Aplicar una lista permitida de campos; no enviar el registro completo.
  4. Redactar secretos, números de pago, credenciales y notas especialmente sensibles.
  5. Obtener una salida estructurada y comprobar si requiere revisión.
  6. Guardar la propuesta con modelo, versión del flujo y fecha.
  7. Solicitar aprobación humana antes de modificar estado, propietario o comunicación.

La clave de OpenAI se guarda en el servidor o gestor de secretos. Nunca se coloca en una extensión del CRM ejecutada en el navegador, en una aplicación móvil, en el repositorio ni en una fórmula visible. Utiliza proyectos y credenciales separados por entorno, permisos mínimos y rotación documentada.

Ejemplo actual con responses.parse y Pydantic

El siguiente programa es autocontenido: clasifica un mensaje de ejemplo y muestra un objeto validado. Instala versiones actuales de openai y pydantic, configura OPENAI_API_KEY en el entorno y ejecuta el archivo en el backend. En producción, sustituye lead_text por el texto minimizado que proceda de un evento autenticado.

from enum import Enum

from openai import OpenAI
from pydantic import BaseModel, Field


class Intent(str, Enum):
    demo = "demo"
    soporte = "soporte"
    informacion = "informacion"
    baja = "baja"
    otro = "otro"


class LeadTriage(BaseModel):
    intent: Intent
    summary: str = Field(
        description="Resumen breve basado únicamente en el mensaje"
    )
    requested_follow_up: bool = Field(
        description="El contacto pide explícitamente una respuesta o llamada"
    )
    fields_to_verify: list[str] = Field(
        description="Datos mencionados que un agente debe confirmar"
    )
    requires_human_review: bool = Field(
        description="Siempre true si hay ambigüedad, riesgo o acción externa"
    )


client = OpenAI(timeout=20.0, max_retries=2)

lead_text = (
    "Somos una clínica de 20 personas. Queremos una demostración la próxima "
    "semana, pero antes necesitamos saber cómo se tratan los datos. "
    "Pueden responder por correo."
)

response = client.responses.parse(
    model="gpt-5.6-terra",
    input=[
        {
            "role": "developer",
            "content": (
                "Clasifica el mensaje para ayudar a una persona del equipo. "
                "No inventes identidad, presupuesto, urgencia ni autoridad de compra. "
                "No infieras atributos sensibles. Si falta información o existe una "
                "solicitud sobre privacidad, marca revisión humana. La salida nunca "
                "autoriza una decisión ni una comunicación automática."
            ),
        },
        {"role": "user", "content": lead_text},
    ],
    text_format=LeadTriage,
    max_output_tokens=500,
    store=False,
)

result = response.output_parsed
if result is None:
    raise RuntimeError("No se recibió una salida estructurada utilizable")

print(result.model_dump_json(indent=2))

responses.parse solicita una salida conforme al esquema y el SDK la convierte al modelo Pydantic. Esto reduce errores de sintaxis y evita un parser manual de texto, pero no demuestra que el contenido sea verdadero. Por ejemplo, un resumen puede ser formalmente válido y aun así interpretar mal la intención. Compara siempre los campos importantes con el mensaje original y mide errores en un conjunto representativo de tu CRM.

La aplicación debe revisar también el estado completo de la respuesta. Una negativa del modelo, un máximo de salida alcanzado, un error de red o un cambio de esquema no deben convertirse silenciosamente en valores por defecto. Si output_parsed no está disponible, mueve el caso a una cola de revisión y conserva un mensaje técnico mínimo. No reemplaces el fallo por intent="otro", porque eso ocultaría problemas operativos.

Por qué Structured Outputs es preferible a JSON libre

Pedir «devuelve solo JSON» no garantiza claves, tipos ni valores permitidos. El modelo puede envolver el objeto en Markdown, omitir campos o emitir una cadena donde el código espera un booleano. Con Structured Outputs, el esquema es parte de la solicitud y el resultado se valida. También facilita versionar la integración y detectar cuándo un consumidor sigue esperando una forma antigua.

  • Usa enumeraciones para categorías cerradas y nombres de campo inequívocos.
  • Describe cada campo con su significado, no solo con un ejemplo.
  • Mantén el esquema pequeño; no extraigas información que el proceso no utiliza.
  • Versiona el esquema y prueba compatibilidad antes de añadir o renombrar campos.
  • Valida reglas del negocio después del parseo, mediante código determinista.

Un esquema no protege contra una instrucción maliciosa dentro del mensaje. El contenido del CRM es entrada no confiable: puede incluir texto que intente cambiar reglas, solicitar secretos o activar herramientas. Mantén las instrucciones de sistema separadas, no concedas al modelo credenciales del CRM y valida cada acción en una capa de autorización propia.

Modelo y límites de consumo

El ejemplo usa gpt-5.6-terra como opción equilibrada. Para grandes volúmenes puede evaluarse otra variante de la familia, y para casos complejos una variante de mayor capacidad, siempre con pruebas. Los alias, prestaciones y disponibilidad evolucionan; evita codificar una promesa comercial en la interfaz. La selección debe basarse en exactitud medida, latencia, límites y coste total del flujo.

max_output_tokens=500 acota la salida, pero el presupuesto también requiere limitar el texto de entrada, el número de eventos por cuenta y la concurrencia. Configura límites de gasto y alertas del proyecto. Observa tokens agregados, errores, latencia y tasa de revisión humana. No registres el texto completo para calcular una métrica que puede obtenerse sin contenido.

Privacidad y retención

store=False impide el almacenamiento predeterminado del objeto de respuesta como estado de aplicación en la ruta compatible de Responses. No significa Zero Data Retention. La documentación de OpenAI indica que los registros de supervisión de abuso pueden incluir prompts, respuestas y metadatos y conservarse por defecto hasta 30 días, salvo exigencias legales o necesidades de protección del servicio o terceros. ZDR requiere un acuerdo y elegibilidad separados, y algunas funciones no son compatibles.

OpenAI indica que los datos de la API no se usan para entrenar modelos por defecto salvo adhesión voluntaria. Esto no elimina las obligaciones del responsable del CRM. Define una base legal, informa a los contactos, limita el acceso y documenta OpenAI y el CRM como proveedores cuando corresponda. La cola, los logs, las copias de seguridad y las herramientas de soporte también pueden conservar datos y deben tener plazos de borrado.

  • Envía el contenido del mensaje, no toda la ficha ni notas históricas si no son necesarias.
  • Sustituye identificadores directos por referencias internas cuando el texto pueda procesarse sin ellos.
  • No uses el correo como safety_identifier; genera un HMAC o hash con secreto.
  • Evita conservar prompts y respuestas en sistemas de observabilidad.
  • Atiende solicitudes de acceso o borrado en todos los almacenes bajo control de la organización.

Idempotencia, reintentos y escritura en el CRM

Los webhooks suelen entregarse al menos una vez, por lo que el mismo evento puede repetirse. Antes de llamar al modelo, reserva de manera atómica el identificador del evento y la versión del proceso. Si ya existe un resultado completo, reutilízalo; si está en curso, no inicies otro trabajo. Esto evita consumo duplicado y, sobre todo, evita dos cambios o dos mensajes.

Respeta Retry-After y usa espera exponencial con variación aleatoria para fallos transitorios. El SDK ya incorpora reintentos limitados para ciertos errores, así que no multipliques las capas. No reintentes automáticamente errores de autenticación, solicitudes inválidas o límites de gasto. Para una escritura externa, separa «generar propuesta» de «aplicar cambio» y exige una clave de idempotencia interna en la segunda etapa.

Revisión humana que aporta control real

Una pantalla de aprobación no basta si la persona no ve el original, no puede modificar el resultado o recibe cientos de casos por minuto. Presenta el mensaje fuente junto a la propuesta, destaca campos no confirmados y permite corregir, rechazar o escalar. Registra la decisión humana sin almacenar más datos de los necesarios. Usa las correcciones agregadas para una evaluación, no para afirmar que el modelo aprende automáticamente de ellas.

  • Mide precisión por intención y por idioma, no solo un promedio global.
  • Incluye mensajes ambiguos, muy cortos, hostiles, multilingües y con instrucciones maliciosas.
  • Evalúa falsos positivos en categorías que activan comunicaciones.
  • Detén el despliegue si aumenta la tasa de corrección o de casos sin parsear.
  • Repite las evaluaciones al cambiar modelo, prompt, esquema o campos del CRM.

Checklist de producción

  1. El webhook se autentica y los eventos duplicados no repiten acciones.
  2. La integración aplica una lista permitida de datos y no envía el registro completo.
  3. La clave está en el backend y separada por entorno.
  4. La salida usa Structured Outputs y Pydantic; no depende de json.loads sobre texto libre.
  5. Refusals, interrupciones y output_parsed=None van a revisión.
  6. Las decisiones sensibles están excluidas y las demás propuestas tienen control humano adecuado.
  7. Entrada, salida, frecuencia, concurrencia y gasto tienen límites.
  8. Los logs no copian contenido, credenciales o datos personales.
  9. La política de privacidad explica proveedores y plazos reales.
  10. Existe una evaluación versionada y un mecanismo para revertir el cambio.

Fuentes oficiales

Revisión editorial: 3 de agosto de 2026. Se emplearon herramientas de IA como apoyo para estructurar y comprobar el borrador; una persona revisó el contenido, el ejemplo y las fuentes oficiales. chatgpt-gratis.chat es independiente y no es una aplicación oficial de OpenAI ni ChatGPT. El servicio del sitio utiliza actualmente la API de OpenAI, pero el proveedor, los modelos y los límites pueden cambiar.