Primeros 15 minutos con la API
Del alta de la aplicación a tu primer ticket: identificar al usuario, abrir una incidencia, pedir sugerencias de IA, enviar errores y tratar los fallos.
Actualizado el . 6 min de lectura
Incluido en los planes Profesional y Avanzado. Ver precios
Esta guía te lleva de cero a una integración que funciona: das de alta la aplicación, le concedes permisos, identificas a un usuario, abres un ticket en su nombre, pides sugerencias de IA y aprendes a tratar los errores sin que tu interfaz se rompa.
Necesitas la clave de API de una aplicación externa. Los ejemplos usan tickets de soporte, así que el plan de tu organización tiene que incluir el aplicativo Tickets de soporte con la capacidad «Tickets propios», además de Integraciones.
Esta es la conversación completa entre tu servidor y UTILIA OS; los pasos de abajo la construyen una petición cada vez:
Tu primera integración, de principio a fin
Participan: Tu servidor, UTILIA OS.
De Tu servidor a UTILIA OS:
POST /external/v1/users/identify
Da de alta a tu usuario con el externalId que tú eliges.De Tu servidor a UTILIA OS:
POST /external/v1/tickets
Abre un ticket en su nombre.De UTILIA OS a Tu servidor:
201 con el ticket creado (respuesta)
De Tu servidor a UTILIA OS:
POST /external/v1/tickets/ai-suggest
Pide sugerencias de IA para lo que escribe tu usuario.De UTILIA OS a Tu servidor:
jobId (respuesta)
El trabajo queda en cola.De Tu servidor a UTILIA OS:
GET /external/v1/tickets/ai-suggest/{jobId}/stream
Espera el resultado en tiempo real.De UTILIA OS a Tu servidor:
completed, con título, descripción, categoría y prioridad (respuesta)
Nota en UTILIA OS:
Tu equipo contesta el ticket desde Tickets de soporte.De UTILIA OS a Tu servidor:
Aviso TICKET_REPLIED
Llega a la dirección de avisos de tu aplicación.
Crea la aplicación y guarda su clave
Cada integración necesita su propia aplicación externa. Créala desde Ajustes › Integraciones › Aplicaciones externas, necesitas entrar con tu cuenta con Crear app y elige «Tickets y soporte» como uso. Al terminar verás la clave de API, del tipo
utl_xxxxxxxxxxxxxxxx, que enviarás en cada petición:HTTPX-Api-Key: utl_xxxxxxxxxxxxxxxxLa clave es secreta: úsala desde tu servidor, nunca en el navegador ni en el repositorio. El alta paso a paso está en Panel de aplicaciones externas.
Concede los permisos
La aplicación nace sin permisos. En su ficha, Ajustes › Permisos, aplica el conjunto «Tickets y soporte», que concede:
crm:users:readycrm:users:write, para listar y dar de alta usuarios.support:tickets:readysupport:tickets:write, para leer y abrir tickets.
Si vas a seguir los pasos de IA y de errores, añade a mano «IA en tickets de soporte» (
support:tickets:ai) y «Reportar errores al backend» (analytics:errors:write).Identifica al usuario final
Antes de crear tickets, pedir IA o emitir facturas para un usuario, llama a
POST /users/identify. Es el paso que vincula tu usuario con UTILIA OS mediante unexternalIdque tú eliges.Casi todos los endpoints que reciben
userIden la dirección o como campo suelto del cuerpo dan por hecho que el usuario ya existe; si no, responden404conerrorCode: USER_NOT_FOUND. Las excepciones son los que aceptan un objetouser: { externalId, email, name }en el cuerpo, comoPOST /ticketsyPOST /invoices: crean el usuario si no existe y lo actualizan si ya existe.curl -X POST 'https://os.utilia.ai/api/external/v1/users/identify' \ -H 'Content-Type: application/json' \ -H 'X-Api-Key: utl_xxx' \ -d '{ "externalId": "user_42", "email": "ada@example.com", "name": "Ada Lovelace" }'Llama a
identifycuando el usuario inicia sesión en tu aplicación y otra vez si cambian su correo o su nombre. Detalle en Usuarios externos.Con el SDK de JavaScript o de Python, identifica al usuario de forma explícita con
sdk.users.identify(...)antes de operar sobre él: el SDK no lo hace por ti. Ver la configuración del SDK de JavaScript o del SDK de Python.Abre un ticket
Tienes dos formas equivalentes de crear el ticket. Elige la que mejor encaje con tu flujo:
Opción A: deja que el propio endpoint cree el usuario. No necesita
identifyprevio: UTILIA OS busca al usuario por la pareja aplicación másexternalIdy lo crea si no existe.const res = await fetch('https://os.utilia.ai/api/external/v1/tickets', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'utl_xxx', }, body: JSON.stringify({ user: { externalId: 'user_42', email: 'ada@example.com', name: 'Ada Lovelace', }, title: 'No puedo subir archivos al panel', description: 'Recibo un timeout al intentar adjuntar el PDF de la factura.', category: 'BUG', priority: 'ALTA', context: { url: 'https://mi-app.com/facturas/123' }, }), }); const ticket = await res.json();Opción B: si ya llamaste a
/users/identify, envía solouser.externalId. Los datos que omitas no se sobrescriben.Todos los campos del ticket están en Endpoints básicos de tickets.
Pide sugerencias de IA
La IA analiza el texto, el audio o las imágenes que escribe tu usuario y propone
title,description,categoryyprioritypara el ticket. A diferencia dePOST /tickets,POST /tickets/ai-suggestno crea el usuario: eluserIddel cuerpo tiene que existir ya, o la respuesta es404conUSER_NOT_FOUND.// 1. Solicitar sugerencias (devuelve un jobId) const enqueue = await fetch( 'https://os.utilia.ai/api/external/v1/tickets/ai-suggest', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Api-Key': 'utl_xxx', }, body: JSON.stringify({ userId: 'user_42', // debe estar previamente identificado text: 'No puedo subir archivos. Sale un timeout cuando adjunto el PDF.', existingFields: { title: '', description: '' }, source: 'SDK_EXTERNAL', }), }, ); const { jobId } = await enqueue.json(); // 2. Recibir el resultado en tiempo real (o consultando el estado). // EventSource no puede enviar cabeceras, así que la clave viaja como // parámetro `apiKey` (solo se acepta en peticiones GET de eventos). const eventSource = new EventSource( `https://os.utilia.ai/api/external/v1/tickets/ai-suggest/${jobId}/stream?apiKey=utl_xxx`, ); eventSource.onmessage = (msg) => { const data = JSON.parse(msg.data); if (data.event === 'completed') { console.log('Sugerencias:', data.result.suggestions); eventSource.close(); } };Opciones de audio e imágenes en Endpoints de sugerencias con IA.
Envía los errores de tu aplicación
UTILIA OS tiene dos endpoints distintos para errores, y confundirlos es de lo más habitual al integrar.
Endpoint Para qué sirve Quién lo llama Campos POST /errors/reportErrores de la lógica de negocio de tu aplicación que quieres registrar con contexto (módulo, archivo, línea, función, usuario, contexto) Tu servidor messageymodule(obligatorios), y ademásseverity,stack,file,line,function,endpoint,method,userId,requestId,contextPOST /tickets/client-errorsErrores del navegador que envían el SDK o el widget, en lotes de hasta 10 Tu interfaz web, o el SDK por su cuenta errors[]conmessage,stack,code,severity,endpoint,method,requestId,component,url,userAgentRegla práctica: si lo llamas tú desde tu servidor para registrar un error con contexto,
POST /errors/report; si son errores del navegador en lote,POST /tickets/client-errors. Detalle en Endpoints de errores de tu aplicación y Endpoint de errores del cliente.Trata los errores en tu interfaz
Cuando algo falla, UTILIA OS responde siempre con la misma forma:
JSON{ "statusCode": 404, "message": "Usuario externo no encontrado. Usa /users/identify primero.", "error": "NOT_FOUND", "errorCode": "USER_NOT_FOUND", "timestamp": "2026-05-07T10:31:12.000Z", "requestId": "550e8400-e29b-41d4-a716-446655440000" }No pases el cuerpo del error a tu interfaz
error.response.dataes un objeto, no un texto. Si lo pintas contoast.error(error.response.data)o lo metes como hijo en JSX, React lanza «Objects are not valid as a React child» y la pantalla se rompe. Muestramessage, decide conerrorCodey guardarequestIdpara soporte.La receta completa está en Errores, identificador de petición y reintentos.
Recibe avisos en tu servidor
Para enterarte de lo que pasa sin preguntar (una respuesta en un ticket con
TICKET_REPLIED, su resolución conTICKET_RESOLVED, un usuario nuevo conUSER_CREATED), configura la dirección de avisos en la pestaña Avisos a tu servidor de la ficha y comprueba la firma de cada entrega. Es opcional, pero ahorra muchas consultas.Catálogo de eventos y firma en Avisos a tu servidor: visión general.
Errores típicos en la primera integración
| Síntoma | Causa más probable | Qué hacer |
|---|---|---|
403 INSUFFICIENT_SCOPE | La aplicación no tiene el permiso de esa operación | Concédelo en Ajustes › Permisos de la ficha de la aplicación |
404 USER_NOT_FOUND al llamar a ai-suggest u otros endpoints de tickets e IA con userId suelto | El usuario no se identificó antes | Llama a POST /users/identify y repite. Con el SDK, sdk.users.identify(...) |
404 EXTERNAL_USER_NOT_FOUND en invoices/stats, invoices/:id, invoices/:id/pay, payment-methods u otros endpoints de facturación | Lo mismo: los endpoints de facturación usan este código | Trátalo igual que USER_NOT_FOUND |
Faltan module, file o line en los errores registrados | Enviaste a /tickets/client-errors un error de servidor: esos campos se descartan | Usa /errors/report para los errores de tu servidor |
| React: «Objects are not valid as a React child» tras un fallo de la API | Pintaste el objeto de error completo | Muestra message |
403 APP_DISABLED en cualquier endpoint | Alguien desactivó la aplicación | Reactívala desde su ficha (ver Panel de aplicaciones externas) |
429 RATE_LIMIT_EXCEEDED | Superaste el límite por hora | Respeta Retry-After y reintenta con espera exponencial; ver Límites de uso y CORS |
Siguiente paso
- Repasa Dónde va cada parámetro: es la causa número uno de errores
400y404en las primeras integraciones. - Si vas a emitir facturas, sigue la guía de facturación y cobro.
- Antes de pasar a producción, vigila tu integración desde Métricas de la API.
Ponlo en práctica
Lo encontrarás en Aplicaciones externas. Para abrirlo, entra con tu cuenta de UTILIA OS.