# Zapini API — Kanban

**Versión:** 1.0.0
**Base URL:** `https://zapini.app/api/v1`

---

## Autenticación

Todos los endpoints requieren un Bearer Token:

```
Authorization: Bearer sk_your_api_token
Accept: application/json
Content-Type: application/json
```

Genera tokens de API en el panel admin en **API Docs → Gestionar Tokens**.

---

## API Kanban

**Ruta base:** `/api/v1/kanban`
**Requisito:** `kanban_enabled` debe ser true en tu cuenta de tenant.

La API Kanban proporciona acceso CRUD completo a tableros, columnas y leads. Úsala para crear integraciones de CRM, automatizar la gestión de pipeline o sincronizar con herramientas externas.

---

## Tableros

### Listar Tableros
`GET /api/v1/kanban/boards`

Retorna todos los tableros Kanban para la instancia autenticada.

```bash
curl -s -H "Authorization: Bearer sk_your_token" \
  "https://zapini.app/api/v1/kanban/boards"
```

**Respuesta:**
```json
{
  "success": true,
  "data": [
    {
      "uuid": "board-uuid",
      "name": "Sales Pipeline",
      "description": null,
      "is_default": true,
      "whatsapp_instance_uuid": "instance-uuid",
      "auto_detect_leads_enabled": false,
      "auto_detect_score_threshold": 50,
      "columns_count": 6,
      "created_at": "2026-01-01T00:00:00+00:00"
    }
  ]
}
```

---

### Crear Tablero
`POST /api/v1/kanban/boards`

Crea un nuevo tablero con columnas predeterminadas (Nuevo Lead, Calificado, Propuesta, Negociación, Ganado, Perdido).

| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| name | string | Sí | Nombre del tablero |
| description | string | No | Descripción del tablero |
| is_default | boolean | No | Establecer como tablero predeterminado |

```bash
curl -s -X POST \
  -H "Authorization: Bearer sk_your_token" \
  -H "Content-Type: application/json" \
  -d '{"name":"Q2 Pipeline","is_default":false}' \
  "https://zapini.app/api/v1/kanban/boards"
```

---

### Obtener Tablero
`GET /api/v1/kanban/boards/{uuid}`

Retorna detalles del tablero con estadísticas y columnas.

```bash
curl -s -H "Authorization: Bearer sk_your_token" \
  "https://zapini.app/api/v1/kanban/boards/board-uuid"
```

**Respuesta incluye `stats`:**
```json
{
  "stats": {
    "total_leads": 12,
    "open_leads": 9,
    "won_leads": 2,
    "lost_leads": 1,
    "total_value": 15000.00,
    "won_value": 5000.00,
    "conversion_rate": 66.7,
    "avg_time_to_close": 14.5
  }
}
```

---

### Actualizar Tablero
`PUT /api/v1/kanban/boards/{uuid}`

| Campo | Tipo | Descripción |
|-------|------|-------------|
| name | string | Nombre del tablero |
| description | string | Descripción del tablero |
| is_default | boolean | Establecer como predeterminado (desmarca los demás) |
| auto_detect_leads_enabled | boolean | Habilitar detección automática de leads |
| auto_detect_score_threshold | integer | Puntuación mínima (0–100) para detección automática |

---

### Eliminar Tablero
`DELETE /api/v1/kanban/boards/{uuid}`

Elimina el tablero y todas sus columnas y leads.

---

## Columnas

### Listar Columnas
`GET /api/v1/kanban/boards/{board_uuid}/columns`

Retorna columnas ordenadas por posición.

---

### Crear Columna
`POST /api/v1/kanban/boards/{board_uuid}/columns`

| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| name | string | Sí | Nombre de la columna |
| color | string | No | Color hex (ej. `#3B82F6`) |
| position | integer | No | Posición de la columna (al final si se omite) |
| wip_limit | integer | No | Máximo de leads en esta columna |
| is_final | boolean | No | Si esta es una columna de etapa final |

---

### Reordenar Columnas
`POST /api/v1/kanban/boards/{board_uuid}/columns/reorder`

```json
{
  "order": ["col-uuid-1", "col-uuid-2", "col-uuid-3"]
}
```

---

### Actualizar Columna
`PUT /api/v1/kanban/columns/{uuid}`

| Campo | Tipo | Descripción |
|-------|------|-------------|
| name | string | Nombre de la columna |
| color | string | Color hex |
| wip_limit | integer | Límite WIP |
| is_final | boolean | Flag de etapa final |
| min_ai_score | integer | Puntuación mínima de IA para enrutamiento automático |
| max_ai_score | integer | Puntuación máxima de IA para enrutamiento automático |

---

### Eliminar Columna
`DELETE /api/v1/kanban/columns/{uuid}`

| Consulta | Tipo | Descripción |
|---------|------|-------------|
| move_leads_to_uuid | string | UUID de columna para mover los leads (opcional) |

---

## Leads

### Listar Leads
`GET /api/v1/kanban/boards/{board_uuid}/leads`

| Parámetro | Tipo | Por Defecto | Descripción |
|-----------|------|-------------|-------------|
| status | string | open | `open` \| `won` \| `lost` \| `all` |
| priority | string | — | `low` \| `medium` \| `high` \| `urgent` |
| column_uuid | string | — | Filtrar por columna |
| search | string | — | Buscar por título, teléfono, email, notas |

```bash
curl -s -H "Authorization: Bearer sk_your_token" \
  "https://zapini.app/api/v1/kanban/boards/board-uuid/leads?status=open&priority=high"
```

---

### Crear Lead
`POST /api/v1/kanban/leads`

| Campo | Tipo | Requerido | Descripción |
|-------|------|-----------|-------------|
| board_uuid | string | Sí | UUID del tablero destino |
| column_uuid | string | No | Columna destino (primera columna si se omite) |
| title | string | Sí | Título del lead |
| phone_number | string | Sí | Número de teléfono del contacto |
| email | string | No | Email del contacto |
| value | decimal | No | Valor del negocio |
| priority | string | No | `low` \| `medium` \| `high` \| `urgent` |
| notes | string | No | Notas iniciales |
| due_date | date | No | Fecha límite (YYYY-MM-DD) |
| custom_fields | object | No | Campos personalizados clave-valor |

```bash
curl -s -X POST \
  -H "Authorization: Bearer sk_your_token" \
  -H "Content-Type: application/json" \
  -d '{
    "board_uuid": "board-uuid",
    "title": "John Doe - Pro Plan",
    "phone_number": "5511999999999",
    "value": 299.00,
    "priority": "high"
  }' \
  "https://zapini.app/api/v1/kanban/leads"
```

**Respuesta:**
```json
{
  "success": true,
  "data": {
    "uuid": "lead-uuid",
    "title": "John Doe - Pro Plan",
    "phone_number": "5511999999999",
    "value": "299.00",
    "value_formatted": "R$ 299,00",
    "priority": "high",
    "priority_label": "High",
    "source": "api",
    "ai_score": null,
    "is_open": true,
    "is_won": false,
    "is_lost": false,
    "is_overdue": false,
    "column": {
      "uuid": "col-uuid",
      "name": "New Lead",
      "color": "#3B82F6"
    },
    "created_at": "2026-01-01T00:00:00+00:00"
  }
}
```

---

### Obtener Lead
`GET /api/v1/kanban/leads/{uuid}`

Retorna detalles completos del lead incluyendo notes, custom_fields, ai_analysis y lost_reason.

---

### Actualizar Lead
`PUT /api/v1/kanban/leads/{uuid}`

| Campo | Tipo | Descripción |
|-------|------|-------------|
| title | string | Título del lead |
| phone_number | string | Número de teléfono |
| email | string | Email |
| value | decimal | Valor del negocio |
| priority | string | Nivel de prioridad |
| notes | string | Notas |
| due_date | date | Fecha límite |
| custom_fields | object | Campos personalizados |

---

### Eliminar Lead
`DELETE /api/v1/kanban/leads/{uuid}`

Eliminación suave del lead (puede recuperarse desde la base de datos).

---

### Mover Lead
`POST /api/v1/kanban/leads/{uuid}/move`

```json
{
  "column_uuid": "target-column-uuid",
  "position": 0
}
```

Si `position` se omite, el lead se agrega al final. Mover a una columna final "Ganado" o "Perdido" establece automáticamente el estado del lead.

---

### Marcar como Ganado
`POST /api/v1/kanban/leads/{uuid}/won`

```json
{
  "value": 299.00
}
```

---

### Marcar como Perdido
`POST /api/v1/kanban/leads/{uuid}/lost`

```json
{
  "reason": "Budget constraints"
}
```

---

### Agregar Nota
`POST /api/v1/kanban/leads/{uuid}/note`

```json
{
  "note": "Interested in annual subscription. Follow up next week."
}
```

Las notas se agregan con marca de tiempo y nombre de usuario.

---

### Obtener Actividades
`GET /api/v1/kanban/leads/{uuid}/activities`

Retorna el historial completo de actividades de un lead.

**Respuesta:**
```json
{
  "success": true,
  "data": [
    {
      "id": 1,
      "type": "created",
      "description": null,
      "metadata": { "column_name": "New Lead" },
      "user": { "id": 1, "name": "John" },
      "created_at": "2026-01-01T00:00:00+00:00",
      "created_at_human": "2 days ago"
    }
  ]
}
```

---

### Calificar Lead con IA
`POST /api/v1/kanban/leads/{uuid}/ai-qualify`

Ejecuta análisis de IA en el lead (requiere integración de IA configurada).

**Respuesta:**
```json
{
  "success": true,
  "data": {
    "lead": { "uuid": "...", "ai_score": 82 },
    "ai_result": {
      "score": 82,
      "analysis": { "summary": "High-intent lead...", "strengths": [] }
    }
  }
}
```

---

## Códigos de Error

| Código | HTTP | Descripción |
|--------|------|-------------|
| `NOT_FOUND` | 404 | Recurso no encontrado |
| `FORBIDDEN` | 403 | Kanban no habilitado para esta cuenta |
| `VALIDATION_ERROR` | 422 | Error de validación — verifica `error.details` |
| `MOVE_FAILED` | 422 | No se puede mover el lead (ej: límite WIP alcanzado) |
| `NO_AI_PROVIDER` | 422 | No hay integración de IA configurada |
| `INSTANCE_REQUIRED` | 400 | `instance_uuid` requerido para autenticación Sanctum |
| `NO_BOARD` | 422 | No se encontró tablero Kanban para el tenant |
| `UNAUTHORIZED` | 401 | Token inválido o faltante |
| `SERVER_ERROR` | 500 | Error interno del servidor |

---

*Generado por Zapini — https://zapini.app*
