C
Cotizera Docs

API de Automatizaciones

API de Automatizaciones

Las automatizaciones ejecutan acciones automáticas cuando ocurren eventos en tus cotizaciones. Puedes enviar correos, cambiar estados, disparar webhooks y más — todo basado en condiciones configurables.

Todos los endpoints requieren plan PRO y permiso config:manage (solo Owner).


Listar Automatizaciones

GET /api/automations

Lista todas las automatizaciones del tenant, incluyendo el conteo de ejecuciones.

Respuesta 200 OK:

[
  {
    "id": "clxyz...",
    "name": "Notificar al aceptar",
    "trigger": "QUOTE_ACCEPTED",
    "isActive": true,
    "conditions": [
      { "field": "total", "operator": "gt", "value": 5000 }
    ],
    "actions": [
      { "type": "send_email", "to": "owner", "subject": "Cotización aceptada", "body": "..." }
    ],
    "delayMinutes": 0,
    "createdAt": "2026-04-01T10:00:00.000Z",
    "_count": { "logs": 12 }
  }
]

Crear Automatización

POST /api/automations

Permiso: config:manage | Plan: PRO

Cuerpo de la solicitud:

{
  "name": "Email al enviar cotización grande",
  "trigger": "QUOTE_SENT",
  "conditions": [
    { "field": "total", "operator": "gt", "value": 10000 },
    { "field": "client.companyName", "operator": "is_not_empty" }
  ],
  "actions": [
    {
      "type": "send_email",
      "to": "client",
      "subject": "Tu cotización está lista",
      "body": "Gracias por tu interés. Adjuntamos tu cotización."
    }
  ],
  "delayMinutes": 5
}
Campo Tipo Requerido Descripción
name string Nombre (1-100 caracteres)
trigger string Evento que dispara la automatización (ver tabla abajo)
conditions array No Condiciones que deben cumplirse (lógica AND)
actions array Al menos una acción a ejecutar
delayMinutes number No Minutos de retraso antes de ejecutar (predeterminado: 0)

Respuesta 201 Created: Devuelve la automatización creada.


Triggers (Eventos)

Trigger Descripción
QUOTE_CREATED Se creó una nueva cotización
QUOTE_SENT Se envió una cotización al cliente
QUOTE_VIEWED El cliente vio la cotización en el portal
QUOTE_ACCEPTED El cliente aceptó la cotización
QUOTE_REJECTED El cliente rechazó la cotización
QUOTE_WON La cotización se marcó como ganada
QUOTE_LOST La cotización se marcó como perdida
QUOTE_EXPIRING La cotización está por vencer (dentro de 24 horas)

Condiciones

Las condiciones filtran cuándo se ejecuta la automatización. Todas las condiciones deben cumplirse (lógica AND).

{ "field": "total", "operator": "gt", "value": 5000 }
Campo Tipo Requerido Descripción
field string Campo a evaluar (ver campos disponibles)
operator string Operador de comparación
value string/number Depende Valor a comparar (no requerido para is_empty/is_not_empty)

Operadores

Operador Descripción Tipos compatibles
eq Es igual a todos
neq No es igual a todos
gt Mayor que number
lt Menor que number
gte Mayor o igual a number
lte Menor o igual a number
contains Contiene texto text
starts_with Comienza con text
is_empty Está vacío (sin valor) text
is_not_empty No está vacío text

Campos disponibles

Cotización

Campo Tipo Operadores
status select eq, neq
currency select eq, neq
total number eq, neq, gt, lt, gte, lte
subtotal number eq, neq, gt, lt, gte, lte
tax number eq, neq, gt, lt, gte, lte
shippingCost number eq, neq, gt, lt, gte, lte
viewCount number eq, neq, gt, lt, gte, lte
quoteNumber number eq, neq, gt, lt, gte, lte
notes text eq, neq, contains, starts_with, is_empty, is_not_empty

Cliente

Campo Tipo Operadores
client.contactName text eq, neq, contains, starts_with
client.companyName text eq, neq, contains, starts_with, is_empty, is_not_empty
client.email text eq, neq, contains, starts_with
client.phone text eq, neq, contains, is_empty, is_not_empty

Producto

Los campos con prefijo items.* evalúan si algún producto de la cotización cumple la condición.

Campo Tipo Operadores
items.productName text eq, neq, contains, starts_with
items.model text eq, neq, contains, is_empty, is_not_empty
items.unitPrice number eq, neq, gt, lt, gte, lte
items.quantity number eq, neq, gt, lt, gte, lte
items.discountPct number eq, neq, gt, lt, gte, lte
💡

Los campos items.* usan lógica "alguno coincide" — la condición se cumple si al menos un producto de la cotización coincide.


Acciones

Cada automatización debe tener al menos una acción. Se ejecutan en orden.

send_email

Envía un correo electrónico.

{
  "type": "send_email",
  "to": "client",
  "subject": "Tu cotización está lista",
  "body": "Hemos preparado una cotización personalizada para ti."
}
Campo Tipo Requerido Descripción
to string "client", "owner" o "custom"
customEmail string Condicional Email destino (requerido si to es "custom")
subject string Asunto del correo
body string Cuerpo del correo

send_notification

Crea una notificación en la app para el owner.

{
  "type": "send_notification",
  "title": "Cotización aceptada",
  "body": "El cliente ha aceptado la cotización COT-0042"
}

change_status

Cambia el estado de la cotización.

{
  "type": "change_status",
  "newStatus": "SENT"
}

Valores válidos: GENERATED, SENT, WON, LOST, ACCEPTED, REJECTED

add_label

Agrega una etiqueta a la cotización.

{
  "type": "add_label",
  "labelId": "clxyz..."
}

create_reminder

Crea un recordatorio para dar seguimiento.

{
  "type": "create_reminder",
  "delayMinutes": 1440,
  "message": "Dar seguimiento a esta cotización"
}

fire_webhook

Envía un POST a una URL externa con los datos de la cotización. Ideal para conectar con Zapier, Slack, o cualquier servicio externo.

{
  "type": "fire_webhook",
  "url": "https://hooks.zapier.com/hooks/catch/123456/abcdef/",
  "headers": {
    "Authorization": "Bearer mi-token-secreto"
  },
  "includeItems": true
}
Campo Tipo Requerido Descripción
url string URL del webhook (debe ser válida)
headers object No Headers HTTP adicionales (ej: Authorization)
includeItems boolean No Incluir productos en el payload (predeterminado: true)

El payload enviado tiene esta estructura:

{
  "event": "QUOTE_SENT",
  "timestamp": "2026-04-09T14:30:00.000Z",
  "data": {
    "quote": {
      "id": "clxyz...",
      "quoteNumber": 42,
      "status": "SENT",
      "total": 15000,
      "subtotal": 13000,
      "currency": "MXN",
      "notes": "...",
      "client": {
        "id": "...",
        "contactName": "María López",
        "companyName": "Acme Corp",
        "email": "maria@acme.com"
      },
      "items": [
        {
          "productName": "Servicio premium",
          "model": "SRV-001",
          "unitPrice": 13000,
          "quantity": 1,
          "discountPct": 0
        }
      ]
    }
  }
}
ℹ️

El webhook tiene un timeout de 5 segundos. Si el servidor no responde a tiempo, la acción se registra como fallida.


Obtener una Automatización

GET /api/automations/:id

Permiso: config:manage | Plan: PRO

Obtiene una automatización con sus últimas 10 ejecuciones.

Respuesta 200 OK: Devuelve la automatización con el array logs.


Actualizar Automatización

PATCH /api/automations/:id

Permiso: config:manage | Plan: PRO

Actualiza una automatización. Todos los campos son opcionales. Incluye isActive para activar o desactivar.

{
  "isActive": false
}

Respuesta 200 OK: Devuelve la automatización actualizada.


Eliminar Automatización

DELETE /api/automations/:id

Permiso: config:manage

Elimina permanentemente una automatización y todo su historial de ejecución.

Respuesta 200 OK:

{
  "ok": true
}
⚠️

Esta operación no se puede deshacer. Se eliminan también todos los registros de ejecución.


Historial de Ejecuciones

GET /api/automations/:id/logs

Permiso: config:manage | Plan: PRO

Lista las ejecuciones de una automatización con paginación.

Parámetros de consulta:

Parámetro Tipo Predeterminado Descripción
page number 1 Número de página
limit number 20 Resultados por página (máximo 100)

Respuesta 200 OK:

{
  "logs": [
    {
      "id": "clxyz...",
      "automationId": "...",
      "quoteId": "...",
      "tenantId": "...",
      "status": "COMPLETED",
      "triggeredAt": "2026-04-09T14:30:00.000Z",
      "completedAt": "2026-04-09T14:30:01.000Z",
      "error": null
    }
  ],
  "total": 47,
  "page": 1,
  "totalPages": 3
}

Estados posibles: TRIGGERED, COMPLETED, FAILED.

© 2026 Cotizera. All rights reserved.