La instalación y el canje del código
Qué recibe tu dirección de instalación, cómo canjear el código por las credenciales de cada empresa, cómo guardarlas y cómo se vuelve a conectar.
Actualizado el . 8 min de lectura
Cuando una empresa instala tu aplicación, UTILIA OS crea una instalación y manda a la persona a tu dirección de instalación con un código de un solo uso. Tu servidor canjea ese código y recibe, una sola vez, la clave de API y la clave de firma de esa instalación. Hasta que no lo canjea, la instalación no funciona: para la empresa está Conectando y, si pasan 30 minutos, Falta conectar.
La conversación completa
Instalar y canjear el código
Participan: Empresa que instala, UTILIA OS, Tu servidor.
De Empresa que instala a UTILIA OS:
Instalar y seguir en acme.example
Acepta los permisos y elige la persona responsable.Nota en UTILIA OS:
Crea la instalación y un código válido 30 minutos.De Empresa que instala a Tu servidor:
GET dirección de instalación?code=…
Con installation_id, return_url y, si lo había, state.De Tu servidor a UTILIA OS:
POST /external/v1/app-installations/exchange
Con la clave de tu aplicación y el code.De UTILIA OS a Tu servidor:
installation y credentials (respuesta)
Solo esta vez.Nota en UTILIA OS:
La instalación funciona y la pantalla de la empresa se actualiza sola.De UTILIA OS a Tu servidor:
Aviso APP_INSTALLED
Firmado con la clave de firma de la instalación.De Tu servidor a Empresa que instala:
Redirige a return_url (respuesta)
O a tu configuración, si la persona tiene algo que configurar.
La dirección de instalación
Es la que declara tu ficha. Tiene que ser HTTPS y estar en tu dominio verificado. UTILIA OS la abre con estos parámetros y conserva los que ya llevara:
- codestringobligatorio
- Código de un solo uso, del tipo uic_…. Vale 30 minutos y solo lo puede canjear la aplicación que publica la ficha.
- installation_idstringobligatorio
- Identificador de la instalación. Es el mismo que devuelve el canje, el de la cabecera X-Utilia-Installation-Id de los avisos y el de GET /external/v1/app-installations/:id.
- return_urlstringobligatorio
- Página de UTILIA OS a la que llevar a la persona al terminar. La fija UTILIA OS: con sesión abre el detalle de la instalación; sin sesión dice que ya puede cerrar la ventana.
- statestring
- Solo si la instalación empezó desde tu enlace «Instalar en UTILIA OS» con un state (hasta 500 caracteres). Te llega tal cual.
Por ejemplo, con la dirección https://acme.example/utilia/install:
https://acme.example/utilia/install?code=uic_X9f…&installation_id=cm3k9…&return_url=https%3A%2F%2Fos.utilia.ai%2Fapps%2Finstalled%3Finstallation_id%3Dcm3k9…Nadie de la empresa tiene que copiar nada: la persona pulsa Instalar y seguir en acme.example, llega a tu web y, cuando tu servidor termina, vuelve a UTILIA OS. Si la conexión falla o la persona cierra la ventana, el código sigue vivo hasta que caduca.
Empezar desde tu web
Si quieres poner en tu web un botón Instalar en UTILIA OS, enlaza la ficha de tu aplicación con install=1, que abre directamente la hoja de instalación, y, si quieres reconocer la vuelta, con tu propio state:
https://os.utilia.ai/dashboard/settings/apps/explore/acme-recordatorios?install=1&state=sesion_8f2cLa dirección de la ficha la copias con Compartir el enlace o Copiar el enlace desde la propia ficha. Si la ficha es «Solo con el enlace», esa dirección lleva un sufijo aleatorio y es el único camino para llegar a ella. Comprueba al volver que el state es uno que tú generaste.
Canjear el código
El canje se hace solo desde tu servidor, con la clave de API de la aplicación que publicó la ficha en X-Api-Key. Una petición que llega con las cabeceras de un navegador (Origin o Sec-Fetch-Site) se rechaza con 403 EXCHANGE_FROM_BROWSER, aunque el código sea bueno. Lo abre el permiso de la API «Recibir las credenciales de cada instalación» (apps:installations:exchange), que tiene la aplicación que publica la ficha.
curl -X POST 'https://os.utilia.ai/api/external/v1/app-installations/exchange' \
-H 'Content-Type: application/json' \
-H 'X-Api-Key: utl_la_clave_de_tu_aplicacion' \
-d '{ "code": "uic_X9f…" }'La respuesta, con 200 y Cache-Control: no-store:
{
"installation": {
"id": "cm3k9x2a40001qz8h7d1v2b3c",
"organization": { "id": "cm1a2b3c40000ab12cd34ef56", "name": "Ferretería López" },
"scopes": ["crm:clients:read", "crm:contacts:read"],
"webhookEvents": ["CLIENT_CREATED", "CONTACT_CREATED", "APP_INSTALLED", "APP_UNINSTALLED", "APP_ACCESS_CHANGED", "APP_SUSPENDED", "APP_REINSTATED"],
"installedAt": "2026-11-03T09:14:27.000Z"
},
"credentials": {
"apiKey": "utl_k3J9…",
"webhookSigningSecret": "9f86d081884c7d659a2feaa0c55ad015…"
}
}- installation.idstringobligatorio
- La instalación. Guárdalo: es la clave con la que encuentras sus credenciales.
- installation.organizationobjectobligatorio
- id y name de la empresa que instaló. El id es el organizationId que traen sus avisos.
- installation.scopesstring[]obligatorio
- Permisos de la API que concedió la empresa: los que pide tu ficha.
- installation.webhookEventsstring[]obligatorio
- Avisos que recibirá tu servidor por esta instalación: los de tu ficha que cubren esos permisos y los cinco del ciclo de vida. Vacío si la ficha no tiene dirección de avisos.
- installation.installedAtstringobligatorio
- Cuándo se instaló, en ISO 8601.
- credentials.apiKeystringobligatorio
- Clave de API de la instalación (utl_…), para la cabecera X-Api-Key. No se vuelve a enseñar.
- credentials.webhookSigningSecretstringobligatorio
- Clave de firma de los avisos de esta instalación (HMAC-SHA256). No se vuelve a enseñar.
Justo después, si es la primera vez que se conecta, llega a tu dirección de avisos el aviso APP_INSTALLED, firmado con esa clave de firma. Lo explica Avisos de cada instalación.
Guardar las credenciales de cada instalación
Cada empresa es una instalación distinta, con su clave y su clave de firma. Guárdalas por instalación, nunca juntas en una sola variable de entorno:
- La clave de API, cifrada, para llamar en nombre de esa empresa.
- La clave de firma, cifrada, para comprobar sus avisos. La encuentras por la cabecera
X-Utilia-Installation-Id. - El identificador de la instalación y el de la empresa, sin cifrar, para buscar.
- Los permisos y los avisos, para saber qué puedes pedir sin probar.
Si el canje responde bien pero tu base de datos falla al guardar, no hay segunda oportunidad: el código ya está gastado. Guarda primero y, si falla, pide a la empresa que vuelva a conectar. Las reglas de custodia están en Seguridad: credenciales y avisos.
Con la clave, cada llamada actúa con los permisos de la persona responsable que eligió la empresa, recortados por los permisos concedidos, por su plan y por los datos que esa persona puede ver. Si la empresa se queda sin persona responsable, sus llamadas responden 403 APP_RESPONSIBLE_INACTIVE; si deja de tener un aplicativo que necesitas, las de ese aplicativo responden 403 MODULE_NOT_ENABLED. En los dos casos se arregla en la empresa, no en tu código.
Volver a conectar
La empresa genera un código nuevo desde el detalle de la instalación, en Instaladas:
- Conectar con Acme, cuando la instalación está en Falta conectar porque el primer código caducó.
- Volver a conectar con Acme, con la instalación funcionando, si tú se lo pides: por ejemplo, porque perdiste las credenciales o crees que se han expuesto.
En los dos casos la persona vuelve a tu dirección de instalación con un code nuevo, y el canje te entrega una clave de API nueva y la misma clave de firma. Si la instalación ya funcionaba, la clave anterior sigue valiendo siete días para que cambies la de tu servidor sin cortes; si nunca se canjeó, se sustituye en el acto. El aviso APP_INSTALLED solo llega la primera vez que se conecta. Haz que tu servidor sustituya la clave de esa instalación, buscándola por su identificador, en lugar de crear otra.
Estados de una instalación
Así ves cada instalación con GET /external/v1/app-installations:
Estados de una instalación
Conectando
CONNECTING
Hay un código vigente sin canjear.Se llega desde Conectando cuando: Pasan 30 minutos sin canje
Falta conectar
NEEDS_CONNECTION
La empresa tiene que pulsar Conectar.
Se llega desde Conectando cuando: Tu servidor canjea el código
Activa
ACTIVE
Su clave funciona y le llegan avisos.Se llega desde Activa cuando: UTILIA aprueba una versión con más permisos
Pide más permisos
ACCESS_PENDING
Sigue con los que tenía.Se llega desde Activa cuando: UTILIA suspende la aplicación
Suspendida por UTILIA
SUSPENDED
No puede acceder a los datos.
Se llega desde Activa cuando: La empresa la desinstala
Desinstalada
UNINSTALLED
Estado final
Su clave deja de valer en el acto.
Otras transiciones
- Falta conectar pasa a Conectando: La empresa pulsa Conectar y recibes un código nuevo.
- Pide más permisos pasa a Activa: La empresa acepta los permisos nuevos.
- Suspendida por UTILIA pasa a Activa: UTILIA la reanuda; si nunca se conectó, vuelve a Falta conectar.
installedVia dice de dónde vino: CATALOG (desde Explorar), LINK (una ficha «Solo con el enlace») o TEST (una instalación de prueba).
Si el canje falla
Ningún error del canje se arregla repitiendo la misma petición. Cada código tiene su apartado, con el ancla que trae docsUrl:
| errorCode | HTTP | Qué pasa | Qué hacer |
|---|---|---|---|
EXCHANGE_FROM_BROWSER | 403 | La petición llegó con Origin o Sec-Fetch-Site. | Haz el canje desde tu servidor, nunca desde la página. |
INSTALLATION_CODE_WRONG_APP | 403 | El código es de una ficha de otra aplicación tuya. | Usa la clave de la aplicación que publicó esa ficha. |
INSTALLATION_CODE_INVALID | 404 | El código no existe para tu aplicación, o la instalación ya está desinstalada o suspendida. | Comprueba que lo copiaste entero. Si sigue, pide a la empresa que vuelva a conectar. |
INSTALLATION_CODE_USED | 409 | El código ya se canjeó una vez. | Si perdiste las credenciales, pide a la empresa que vuelva a conectar. |
INSTALLATION_CODE_EXPIRED | 410 | Pasaron los 30 minutos. | La empresa pulsa Conectar con tu aplicación en Instaladas. |
INSUFFICIENT_SCOPE | 403 | A tu aplicación le falta apps:installations:exchange. | Comprueba que llamas con la clave de la aplicación que publica la ficha. |
Un INSTALLATION_CODE_USED justo después de un canje correcto suele ser la misma dirección abierta dos veces (la persona recargó la página o un navegador la abrió por adelantado). Si ya tienes las credenciales de esa installation_id, ignóralo y lleva a la persona a return_url.
La referencia de las tres rutas, con la consulta de tus instalaciones, está en Referencia de las instalaciones.