# Instalar el SDK

Requisitos, instalación con npm o pip y primera llamada del SDK de UTILIA OS en JavaScript y en Python.

Esta página te lleva de cero a la primera llamada: instalas el paquete de tu lenguaje, creas el cliente con la clave de tu aplicación externa e identificas a un usuario para abrirle un ticket de soporte. Los ejemplos de código están en pestañas; elige tu lenguaje una vez y la documentación lo recordará en todas las páginas.

## Requisitos

| | JavaScript | Python |
| - | - | - |
| Paquete | `@utilia-os/sdk-js` | `utilia-sdk` |
| Versión del lenguaje | Node.js 18 o superior | Python 3.9 o superior |
| Dependencias que se instalan solas | `axios` | `httpx` y `pydantic` 2 |

Necesitas además la **clave de acceso de tu aplicación externa**, que empieza por `utl_`. Se obtiene al dar de alta la aplicación: el proceso está en [Panel de aplicaciones externas](https://os.utilia.ai/docs/developers/api/apps-panel).

> **Atención: La clave no sale de tu servidor**
>
> La clave `utl_` lleva todos los permisos de la aplicación, también los que mueven dinero. Úsala solo en código de servidor: nunca en el navegador ni en una aplicación móvil.

## Instalación

### JavaScript

```bash
npm install @utilia-os/sdk-js
```

### Python

```bash
pip install utilia-sdk
```

En Python conviene instalarlo dentro de un entorno virtual (`python -m venv .venv` y, después, `source .venv/bin/activate`).

## Primera llamada

Es el recorrido mínimo para comprobar que la clave y la dirección base funcionan:

**Tu primera llamada, paso a paso**

1. **Crear el cliente** (UtiliaSDK): Con la dirección base y la clave utl\_ de tu aplicación.
2. [**Identificar al usuario**](https://os.utilia.ai/docs/developers/sdk/users) (users.identify): Lo crea o lo actualiza a partir de su externalId.
3. [**Abrir un ticket**](https://os.utilia.ai/docs/developers/sdk/tickets) (tickets.create): Devuelve su clave legible, por ejemplo APP-0001.
4. **Responder y cerrar** (addMessage y close): Añade un mensaje y cierra el ticket.

### JavaScript

```typescript
import { UtiliaSDK } from '@utilia-os/sdk-js';

const sdk = new UtiliaSDK({
  baseURL: 'https://os.utilia.ai/api',
  apiKey: process.env.UTILIA_API_KEY!, // utl_...
});

// 1. Identificar al usuario (lo crea o lo actualiza)
const user = await sdk.users.identify({
  externalId: 'usr-4821',
  email: 'laura.garcia@ejemplo.com',
  name: 'Laura García',
});

// 2. Abrir un ticket de soporte
const ticket = await sdk.tickets.create({
  user: { externalId: 'usr-4821' },
  title: 'No puedo acceder a mis facturas',
  description: 'Al entrar en la sección de facturación aparece un error 500.',
  category: 'CONSULTA',
  priority: 'ALTA',
});
console.log(ticket.ticketKey); // por ejemplo, APP-0001

// 3. Añadir un mensaje y cerrar el ticket
await sdk.tickets.addMessage(ticket.id, 'usr-4821', {
  content: 'Adjunto captura del error.',
});
await sdk.tickets.close(ticket.id, 'usr-4821');
```

### Python

```python
import asyncio
import os

from utilia_sdk import (
    AddMessageInput,
    CreateTicketInput,
    CreateTicketUser,
    IdentifyUserInput,
    UtiliaSDK,
)


async def main() -> None:
    async with UtiliaSDK(
        base_url="https://os.utilia.ai/api",
        api_key=os.environ["UTILIA_API_KEY"],  # utl_...
    ) as sdk:
        # 1. Identificar al usuario (lo crea o lo actualiza)
        user = await sdk.users.identify(
            IdentifyUserInput(
                external_id="usr-4821",
                email="laura.garcia@ejemplo.com",
                name="Laura García",
            )
        )

        # 2. Abrir un ticket de soporte
        ticket = await sdk.tickets.create(
            CreateTicketInput(
                user=CreateTicketUser(external_id="usr-4821"),
                title="No puedo acceder a mis facturas",
                description="Al entrar en la sección de facturación aparece un error 500.",
                category="CONSULTA",
                priority="ALTA",
            )
        )
        print(ticket.ticket_key)  # por ejemplo, APP-0001

        # 3. Añadir un mensaje y cerrar el ticket
        await sdk.tickets.add_message(
            ticket.id, "usr-4821", AddMessageInput(content="Adjunto captura del error.")
        )
        await sdk.tickets.close(ticket.id, "usr-4821")


asyncio.run(main())
```

## Python asíncrono o síncrono

El SDK de Python trae dos clases con los mismos servicios y los mismos métodos:

**Dos clases para Python**

### UtiliaSDK (Asíncrono)

Con async y await. Para FastAPI, Starlette, aiohttp y scripts que lanzan varias llamadas a la vez con asyncio.gather().

### UtiliaSDKSync (Síncrono)

Sin await. Para Django, Flask, scripts y herramientas de terminal, y trabajos de Celery o RQ.

Los ejemplos de esta documentación usan la clase asíncrona. Para la síncrona, cambia `UtiliaSDK` por `UtiliaSDKSync`, `async with` por `with` y quita los `await`.

Las dos abren una sesión HTTP que hay que cerrar al terminar. Con `async with` o `with` se cierra sola; si creas el cliente sin ese bloque, llama tú a `await sdk.close()` (o `sdk.close()` en la síncrona) para no dejar conexiones abiertas. En JavaScript no hace falta cerrar nada.

## Siguiente paso

- [Configurar el cliente](https://os.utilia.ai/docs/developers/sdk/configuration): Tiempo de espera, reintentos, depuración y autenticación con clave u OAuth.
- [Usuarios externos](https://os.utilia.ai/docs/developers/sdk/users): Identifica a tus usuarios: es el primer paso de tickets, facturas y cobros.
