API Documentation

API REST para integrar asistentes IA en tu plataforma. Base URL: configurable por entorno.

Todas las peticiones deben incluir el header Content-Type: application/json salvo que se indique lo contrario.

Autenticación

Tres métodos de autenticación disponibles según el tipo de integración.

API Key

Para integraciones server-to-server. Crea tus claves en el panel de administración. Las claves tienen el prefijo ak_ y solo se muestran una vez al crearlas.

HTTP
Header: X-API-Key: ak_your_key_here
# o alternativamente
Header: Authorization: Bearer ak_your_key_here

Embed Token

Para integración mediante widget embebido. El token resuelve la configuración del asistente desde el backend.

HTTP
Header: X-Embed-Token: your_embed_token

JWT (Pre-Auth)

Para integraciones autenticadas. El JWT debe estar firmado con el secreto compartido configurado en el panel.

HTTP
Header: X-Embed-Token: your_embed_token
Header: Authorization: Bearer eyJhbG...

Chat API

Enviar mensaje (sin streaming)

POST/api/v1/chat/message
JSON
// Request Body
{
  "message": "string",
  "assistantId?": "string",
  "conversationId?": "string"
}

// Response
{
  "conversationId": "string",
  "message": "string"
}

Enviar mensaje (streaming SSE)

POST/api/v1/chat/stream

Respuesta de tipo text/event-stream. Eventos posibles:

SSE Events
// Request Body
{
  "message": "string",
  "assistantId?": "string",
  "conversationId?": "string"
}

// Event types
data: {"token":"hello","conversationId":"..."}           // text chunk
data: {"type":"thinking","content":"..."}                // tool processing
data: {"type":"action_preview","preview":{...}}          // action preview
data: {"type":"token","content":"..."}                   // text chunk (new format)

Confirmar acción

POST/api/v1/chat/confirm-action
JSON
{
  "conversationId": "string",
  "confirmAction": "string",
  "confirmPayload": {}
}

Listar conversaciones

GET/api/v1/chat/conversations
JSON
// Response
[
  {
    "id": "string",
    "createdAt": "string",
    "updatedAt": "string"
  }
]

Obtener mensajes

GET/api/v1/chat/conversations/:id/messages
JSON
// Response
[
  {
    "id": "string",
    "role": "user|assistant",
    "content": "string"
  }
]

Eliminar conversación

DELETE/api/v1/chat/conversations/:id

Obtener acciones disponibles

GET/api/v1/chat/actions?assistantId=xxx
JSON
// Response
[
  {
    "name": "string",
    "description": "string",
    "parameters": [...]
  }
]

Widget Integration

Integra el asistente en cualquier web con un simple script tag.

Widget flotante

HTML
<script src="https://your-api.com/widget/ai-assistant-widget.js"
  data-api-url="https://your-api.com/api"
  data-embed-token="your_token"
  data-mode="floating">
</script>

Widget inline

HTML
<div style="height: 600px;">
  <script src="https://your-api.com/widget/ai-assistant-widget.js"
    data-api-url="https://your-api.com/api"
    data-embed-token="your_token"
    data-mode="inline">
  </script>
</div>

Pre-autenticado

Pasa un JWT firmado para identificar al usuario sin necesidad de registro.

HTML
<script src="https://your-api.com/widget/ai-assistant-widget.js"
  data-embed-token="your_token"
  data-token="eyJhbG..."
  data-api-url="https://your-api.com/api">
</script>

Integración PRE_AUTH (autenticación externa)

Si tus usuarios ya están autenticados en tu plataforma, puedes usar el modo PRE_AUTH para que el widget los identifique automáticamente sin necesidad de registro adicional.

Tu backend firma un JWT con un secreto compartido entre tu sistema y la plataforma de IA. El widget recibe este JWT vía data-token y lo envía en cada petición.

Requisitos

1. Un secreto compartido configurado en ambos sistemas (tu backend y el panel de administración del asistente).

2. Un embed de tipo PRE_AUTH creado en el panel de administración.

3. Un endpoint en tu backend que genere y firme el JWT para usuarios autenticados.

Paso 1: Generar JWT en tu backend

El JWT debe contener los campos: sub (ID del usuario), email, name y tenantSlug.

Node.js / Express

JavaScript
const jwt = require('jsonwebtoken');
const PRE_AUTH_SECRET = process.env.AI_ASSISTANT_PRE_AUTH_SECRET;

app.get('/api/ai-assistant/token', authMiddleware, async (req, res) => {
  // Verify user has active subscription/access
  const user = req.user;

  const token = jwt.sign({
    sub: String(user.id),
    email: user.email,
    name: user.name,
    tenantSlug: 'your-tenant-slug'
  }, PRE_AUTH_SECRET, { expiresIn: '60m' });

  res.json({ token });
});

Python / Django

Python
import jwt
from django.conf import settings

@login_required
def ai_assistant_token(request):
    token = jwt.encode({
        'sub': str(request.user.id),
        'email': request.user.email,
        'name': request.user.get_full_name(),
        'tenantSlug': 'your-tenant-slug',
        'exp': datetime.utcnow() + timedelta(hours=1)
    }, settings.AI_ASSISTANT_PRE_AUTH_SECRET, algorithm='HS256')

    return JsonResponse({'token': token})

PHP / Laravel

PHP
Route::middleware('auth')->get('/api/ai-assistant/token', function (Request $request) {
    $token = JWT::encode([
        'sub' => (string) $request->user()->id,
        'email' => $request->user()->email,
        'name' => $request->user()->name,
        'tenantSlug' => 'your-tenant-slug',
        'exp' => time() + 3600
    ], config('services.ai_assistant.secret'), 'HS256');

    return response()->json(['token' => $token]);
});

Paso 2: Inyectar el widget con el token

Desde tu frontend, obtiene el token de tu backend y lo pasa al widget vía data-token.

HTML
<!-- 1. Fetch the token from YOUR backend -->
<script>
  fetch('/api/ai-assistant/token', {
    headers: { 'Authorization': 'Bearer ' + yourSessionToken }
  })
  .then(r => r.json())
  .then(data => {
    const script = document.createElement('script');
    script.src = 'https://your-assistant.com/widget/ai-assistant-widget.js';
    script.setAttribute('data-api-url', 'https://your-assistant.com/api');
    script.setAttribute('data-embed-token', 'your-embed-token');
    script.setAttribute('data-token', data.token);
    document.body.appendChild(script);
  });
</script>

Personalización (Branding)

Configura la apariencia del widget desde el panel de administración o mediante la API.

CampoTipoDescripción
primaryColorstringColor principal del widget (hex)
avatarUrlstringURL del avatar del asistente
headerColorstringColor de fondo del header
headerTitlestringTítulo mostrado en el header
welcomeMessagestringMensaje de bienvenida al abrir el chat
fontFamilystringFamilia tipográfica del widget
borderRadiusstringRadio de bordes (ej: "12px")
positionstringPosición del widget flotante ("bottom-right", "bottom-left")
hideBrandingbooleanOcultar marca Paidio (planes Professional+)
JSON
{
  "primaryColor": "#d4a853",
  "avatarUrl": "https://example.com/bot-avatar.png",
  "headerColor": "#0f172a",
  "headerTitle": "Soporte IA",
  "welcomeMessage": "Hola, en que puedo ayudarte?",
  "fontFamily": "Inter, sans-serif",
  "borderRadius": "12px",
  "position": "bottom-right",
  "hideBranding": false
}

Ejemplos de código

JavaScript (fetch)

JavaScript
const response = await fetch('https://your-api.com/api/v1/chat/stream', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-API-Key': 'ak_your_key',
  },
  body: JSON.stringify({ message: 'Hola' }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const chunk = decoder.decode(value);
  // Parse SSE lines...
}

Python

Python
import requests

response = requests.post(
    'https://your-api.com/api/v1/chat/message',
    headers={'X-API-Key': 'ak_your_key'},
    json={'message': 'Hola'},
)
print(response.json())

cURL

Bash
curl -X POST https://your-api.com/api/v1/chat/message \
  -H "Content-Type: application/json" \
  -H "X-API-Key: ak_your_key" \
  -d '{"message": "Hola"}'

Rate Limits

La API tiene un límite de 100 peticiones por minuto por IP. Si superas el límite, recibirás un error 429 Too Many Requests.

Adicionalmente, tu plan de Stripe determina el límite mensual de tokens consumidos. Puedes consultar tu consumo actual en el panel de administración.

Errores

La API usa códigos de estado HTTP estándar:

CódigoEstadoDescripción
200OKPetición correcta
201CreatedRecurso creado correctamente
400Bad RequestParámetros inválidos o faltantes
401UnauthorizedCredenciales no proporcionadas o inválidas
403ForbiddenSin permisos para este recurso
404Not FoundRecurso no encontrado
429Too Many RequestsRate limit excedido
500Internal Server ErrorError interno del servidor

Formato de error

JSON
{
  "statusCode": 401,
  "message": "Invalid API key",
  "error": "Unauthorized"
}