> ## Documentation Index
> Fetch the complete documentation index at: https://docs.horneross.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Reference

> Documentación completa de todos los endpoints de la API.

## Chat con agente

El endpoint principal para enviar mensajes:

```
POST /api/v2/agent/{agentId}/chat
```

### Request

```json theme={null}
{
  "query": "¿Cuáles son los horarios?",
  "conversationId": "conv_abc123",
  "visitorId": "user_456",
  "streaming": false,
  "contact": {
    "email": "cliente@ejemplo.com",
    "firstName": "Juan",
    "phoneNumber": "+5491123456789"
  }
}
```

| Campo            | Tipo    | Requerido | Descripción              |
| ---------------- | ------- | --------- | ------------------------ |
| `query`          | string  | Sí        | Mensaje del usuario      |
| `conversationId` | string  | No        | Para mantener contexto   |
| `visitorId`      | string  | No        | ID único del usuario     |
| `streaming`      | boolean | No        | Respuesta en tiempo real |
| `contact`        | object  | No        | Datos del contacto       |

### Response

```json theme={null}
{
  "answer": "Nuestros horarios son de 9 a 18 hs.",
  "conversationId": "conv_abc123",
  "messageId": "msg_xyz789",
  "sources": [
    {"source": "FAQ", "score": 0.95}
  ]
}
```

***

## Conversaciones

### Listar conversaciones

```
GET /api/v2/conversations
```

**Parámetros:**

* `agentId` - Filtrar por agente
* `status` - `open`, `resolved`, `unresolved`
* `limit` - Cantidad (default: 20)

**Respuesta:**

```json theme={null}
{
  "data": [
    {
      "id": "conv_abc123",
      "agentId": "agent_xyz",
      "status": "open",
      "messagesCount": 5,
      "contact": {"email": "cliente@ejemplo.com"},
      "createdAt": "2024-01-21T10:00:00Z"
    }
  ]
}
```

### Obtener conversación

```
GET /api/v2/conversations/{conversationId}
```

### Obtener mensajes

```
GET /api/v2/conversations/{conversationId}/messages
```

### Cambiar estado

```
PUT /api/v2/conversations/{conversationId}/status
```

```json theme={null}
{"status": "resolved"}
```

***

## Agentes

### Listar agentes

```
GET /api/v2/agents
```

### Obtener agente

```
GET /api/v2/agents/{agentId}
```

**Respuesta:**

```json theme={null}
{
  "id": "agent_abc123",
  "name": "Agente de Ventas",
  "description": "Responde consultas de productos",
  "modelName": "gpt-4o",
  "tools": ["datastore", "lead-capture"],
  "status": "active"
}
```

### Crear agente

```
POST /api/v2/agents
```

```json theme={null}
{
  "name": "Agente de Soporte",
  "systemPrompt": "Sos un agente de soporte...",
  "modelName": "gpt-4o",
  "tools": ["datastore", "request-human"]
}
```

### Actualizar agente

```
PUT /api/v2/agents/{agentId}
```

***

## Datastores

### Listar datastores

```
GET /api/v2/datastores
```

### Buscar en datastore

```
POST /api/v2/datastores/{datastoreId}/query
```

```json theme={null}
{
  "query": "¿Cuáles son los horarios?",
  "topK": 5
}
```

**Respuesta:**

```json theme={null}
{
  "results": [
    {
      "content": "Nuestros horarios son...",
      "score": 0.95,
      "source": {"name": "FAQ General"}
    }
  ]
}
```

### Agregar fuente (archivo)

```
POST /api/v2/datastores/{datastoreId}/sources/file
```

Usar `multipart/form-data`:

```bash theme={null}
curl -X POST .../sources/file \
  -H "Authorization: Bearer API_KEY" \
  -F "file=@documento.pdf"
```

### Agregar fuente (URL)

```
POST /api/v2/datastores/{datastoreId}/sources/url
```

```json theme={null}
{"url": "https://ejemplo.com/faq"}
```

### Agregar fuente (texto)

```
POST /api/v2/datastores/{datastoreId}/sources/text
```

```json theme={null}
{
  "content": "Información a indexar...",
  "name": "Políticas de envío"
}
```

***

## Respuestas de error

```json theme={null}
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "API key inválida"
  }
}
```

| Código | Significado          |
| ------ | -------------------- |
| 400    | Parámetros inválidos |
| 401    | API key inválida     |
| 403    | Sin permisos         |
| 404    | Recurso no existe    |
| 429    | Rate limit excedido  |
| 500    | Error del servidor   |

***

## Streaming

Para recibir la respuesta token por token:

```javascript theme={null}
const response = await fetch('.../chat', {
  headers: {
    'Accept': 'text/event-stream',
  },
  body: JSON.stringify({
    query: 'Contame sobre tus productos',
    streaming: true
  }),
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  console.log(decoder.decode(value));
}
```

Eventos:

* `token` - Cada token de la respuesta
* `source` - Fuente encontrada
* `done` - Respuesta completa
