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.
Header: X-API-Key: ak_your_key_here
# o alternativamente
Header: Authorization: Bearer ak_your_key_hereEmbed Token
Para integración mediante widget embebido. El token resuelve la configuración del asistente desde el backend.
Header: X-Embed-Token: your_embed_tokenJWT (Pre-Auth)
Para integraciones autenticadas. El JWT debe estar firmado con el secreto compartido configurado en el panel.
Header: X-Embed-Token: your_embed_token
Header: Authorization: Bearer eyJhbG...Chat API
Enviar mensaje (sin streaming)
// Request Body
{
"message": "string",
"assistantId?": "string",
"conversationId?": "string"
}
// Response
{
"conversationId": "string",
"message": "string"
}Enviar mensaje (streaming SSE)
Respuesta de tipo text/event-stream. Eventos posibles:
// 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
{
"conversationId": "string",
"confirmAction": "string",
"confirmPayload": {}
}Listar conversaciones
// Response
[
{
"id": "string",
"createdAt": "string",
"updatedAt": "string"
}
]Obtener mensajes
// Response
[
{
"id": "string",
"role": "user|assistant",
"content": "string"
}
]Eliminar conversación
Obtener acciones disponibles
// Response
[
{
"name": "string",
"description": "string",
"parameters": [...]
}
]Widget Integration
Integra el asistente en cualquier web con un simple script tag.
Widget flotante
<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
<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.
<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
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
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
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.
<!-- 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.
primaryColorstringColor principal del widget (hex)avatarUrlstringURL del avatar del asistenteheaderColorstringColor de fondo del headerheaderTitlestringTítulo mostrado en el headerwelcomeMessagestringMensaje de bienvenida al abrir el chatfontFamilystringFamilia tipográfica del widgetborderRadiusstringRadio de bordes (ej: "12px")positionstringPosición del widget flotante ("bottom-right", "bottom-left")hideBrandingbooleanOcultar marca Paidio (planes Professional+){
"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)
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
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
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:
200OKPetición correcta201CreatedRecurso creado correctamente400Bad RequestParámetros inválidos o faltantes401UnauthorizedCredenciales no proporcionadas o inválidas403ForbiddenSin permisos para este recurso404Not FoundRecurso no encontrado429Too Many RequestsRate limit excedido500Internal Server ErrorError interno del servidorFormato de error
{
"statusCode": 401,
"message": "Invalid API key",
"error": "Unauthorized"
}