Yurest API · v1

Documentación de la API

Endpoints REST expuestos por n8n para el portal de gestión Yurest. Base URL: https://n8n-soporte.data.yurest.dev/webhook

Introducción

Esta API se expone vía workflows de n8n y persiste en Supabase (Postgres). Todos los endpoints comparten el prefijo:

https://n8n-soporte.data.yurest.dev/webhook

El frontend usa YurestConfig.apiFetch(url, opts) que automáticamente añade headers de autenticación y maneja sesiones expiradas (401/403 → redirige a login).

Convención de respuesta: casi todos los endpoints devuelven 200 OK con un objeto JSON. Operaciones de escritura devuelven al menos { success: boolean } y, donde aplica, datos de diagnóstico (filas afectadas, errores específicos).

Autenticación

El portal usa Basic Auth almacenado en sessionStorage tras un login interno. El header se añade automáticamente vía YurestConfig.apiFetch():

Authorization: Basic <base64(usuario:contraseña)>
Content-Type: application/json

Si la sesión expira, cualquier endpoint responde 401 y el portal redirige al login.

Endpoints públicos (sin auth)

EndpointPor qué es público
responderSolicitudEl cliente lo invoca desde el email sin tener cuenta.
completarFicha?t=<token>Para precargar datos al rellenar la solicitud (validado por token aleatorio).

Errores y diagnóstico

StatusSignificadoCuándo
200OK · revisa body.successCasi todas las respuestas (incluso fallos lógicos vienen 200).
401 / 403Sesión expiradaFrontend redirige a login.html.
500Error interno del workflowExcepción no controlada en n8n.
Patrón de diagnóstico: los workflows de escritura críticos (eliminarFicha, grabadoA3) devuelven además { success, affected/ficha_count/sol_count, errores: [] } para detectar UPDATEs sin efecto (RLS bloqueando, ID inexistente, etc.).

CORS

Todos los endpoints aceptan peticiones desde cualquier origen y responden con los siguientes headers:

Access-Control-Allow-Origin:  *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization

📂 Auth y listado

GET /webhook/018f3362-7969-4c49-9088-c78e4446c77f Basic Auth

Workflow 04-fichas-alta. Devuelve la lista completa de fichas. El portal lo usa también como verificador de sesión en el login.

Aliases en config.js

ENDPOINTS.login · ENDPOINTS.altas

Respuesta 200

{
  "clientes": [
    {
      "id": "uuid",
      "denominacion": "Test SL",
      "cif": "B40597437",
      "email": "contacto@test.es",
      "tipo_cliente": "planes",
      "estado": "rellenado | completada",
      "grabado_a3": false,
      "grabado_a3_at": null,
      "fecha_solicitud": "2026-04-17T...",
      "fecha_rellenado": "2026-04-17T...",
      "fecha_completado": "2026-04-17T...",
      "sepa_mandato": { ... },
      "adjuntos": [ ... ],
      "paquetes_carrito": { ... },
      "deleted_at": null
      // ... resto de columnas
    }
  ]
}
Filtrado backend

El workflow excluye filas con deleted_at != NULL.

📋 Fichas

POST /webhook/57e04029-bae4-4124-8c43-c535e831a147 Basic Auth

Workflow 04-fichas-alta. Crea una ficha nueva (sin id) o actualiza una existente (con id). En modo edición solo actualiza los campos enviados — no destruye los demás.

Body (todos opcionales en edición)

CampoTipoNotas
iduuidSi presente → UPDATE; ausente → INSERT
Nombre SociedadstringMapea a denominacion
CIF/NIFstringMapea a cif
Email · Email Factura · Email CCstring
Tipo Clientestringlite · planes · corporate
Estadostring"rellenado" cuando comercial completa
JP * · Firmante * · TPV *stringsBloques de datos
Lite · Distribuidor"Sí" / ""Booleanos como string
AdjuntosarrayPDF/JPG/PNG en base64
SEPAobjectMandato firmado (datos + firma_base64)
paquetes_carritoobjectSnapshot del carrito (módulos, precios, periodos)
localesarrayLocales de la ficha (insertados aparte)

Respuesta 200 (éxito)

{ "id": "uuid-de-la-ficha", "success": true }

Respuesta 200 (error en INSERT Locales)

{ "error": "..." }

El nodo INSERT Locales tiene continueOnFail: true, así que un fallo en locales no rompe el INSERT/UPDATE de la ficha principal pero sí aparece en el body.

GET /webhook/5a304fcd-ae1d-49e6-92d1-c5a5e007bbfd?t=<token>|?id=<id> Público

Workflow 12-completar-ficha. Devuelve los datos de una ficha o solicitud para precargar el formulario. Acepta tres formas de identificación.

Query params

ParamTipoUso
tstring (16-128 chars)Token aleatorio público (preferente)
iduuid o númeroUUID de ficha o ID-Solicitud numérico (uso interno)

Respuesta 200 (encontrado)

{
  "found": true,
  "id": "uuid",
  "ID Solicitud": 5,
  "Nombre Sociedad": "Test SL",
  "Email": "contacto@test.es",
  "Tipo Cliente": "planes",
  "SEPA": { "iban": "ES...", "deudor": {...}, "firma_base64": "..." },
  // ... resto de campos
}

Respuesta 200 (no encontrado)

{ "found": false, "error": "Solicitud no encontrada" }
POST /webhook/a2b1b1d6-a1dc-4366-b60e-b5e4506faa3d Basic Auth

Workflow 10-eliminar. Soft-delete (UPDATE deleted_at = NOW()) en fichas_alta y solicitudes. Como los UUIDs son únicos entre tablas, sólo afecta a la que contiene el ID.

Body

{
  "action": "delete",
  "entity": "ficha" | "solicitud",
  "id": "uuid",
  "row_number": "uuid"   // alias por compat
}

Respuesta 200

{
  "success": true,
  "entity": "ficha",
  "id": "uuid",
  "ficha_count": 1,
  "sol_count": 0,
  "errores": []
}
success: false: revisa errores (problemas Supabase) o si ficha_count + sol_count == 0 → el id ya no existía.

📨 Solicitudes

POST /webhook/b0629324-e611-47d4-835f-3ac9bcd4dc9b Basic Auth

Workflow 08-solicitudes. Inserta solicitud en estado pendiente y envía email al cliente con la URL del formulario.

Body

{
  "ID Solicitud": 5,
  "access_token": "32-chars-uuid-sin-guiones",
  "Nombre Sociedad": "Empresa SL",
  "Nombre": "Ana García",
  "Email": "ana@empresa.com",
  "Comercial": "Pedro Martin",
  "Tipo Cliente": "planes",
  "Fecha": "2026-04-17",
  "Estado": "Pendiente",
  "email_to": "ana@empresa.com",
  "email_subject": "Solicitud de creación de ficha de alta",
  "email_body": "Hola Ana, te mando este formulario...",
  "form_url": "https://.../solicitud.html?t=..."
}

Si access_token no viene, el workflow lo genera con crypto.randomUUID().

Respuesta 200

{ "id": "uuid", "success": true }
GET /webhook/1757fdcc-7fa7-4cb9-93b9-eb8118adaa1e Basic Auth

Workflow 08-solicitudes. Lista solicitudes que no estén en estado completado (las completadas se mueven a la pestaña "Rellenado cliente").

Respuesta 200

{
  "solicitudes": [
    {
      "id": "uuid",
      "access_token": "...",
      "ID Solicitud": 5,
      "Nombre Sociedad": "...",
      "Email": "...",
      "Estado": "pendiente",
      "Fecha": "2026-04-17T..."
    }
  ]
}
GET /webhook/fa16b994-5af1-4368-ba6b-592e633937c3 Basic Auth

Workflow 09-rellenado-cliente. Lista solicitudes con estado=eq.completada (= clientes que ya rellenaron su parte y esperan que el comercial las complete).

Respuesta 200

{
  "items": [{ "id": "uuid", "Nombre Sociedad": "...", "Email": "...", "Comercial": "..." }]
}
POST /webhook/6da4274f-5a6d-4981-a92a-f9d7eb734144 Público

Workflow 11-auxiliares. El cliente envía sus datos desde solicitud.html. Crea la ficha, carpeta Drive, marca solicitud completada y dispara emails + tarea Asana si TPV no integrado.

Body (todos los datos del formulario)

{
  "ID Solicitud": 5,
  "access_token": "...",
  "Estado": "Rellenado cliente",
  "Nombre Sociedad": "...", "CIF/NIF": "...",
  "JP Nombre": "...", "Firmante DNI": "...",
  "TPV": "Revo",
  "TPV No Integrado": "Sí",  // si checkbox marcado
  "TPV NI Nombre": "...", "TPV NI Contacto": "...", "TPV NI Email": "...",
  "SEPA": {
    "iban": "ES91...",
    "swift": "CAIXESBB",
    "deudor": { "nombre": "...", "direccion": "...", ... },
    "tipo_pago": "recurrente",
    "firma_base64": "data:image/png;base64,...",
    "firmado_at": "2026-04-17T..."
  }
}

Efectos

  • INSERT en fichas_alta con estado=completada + SEPA persistido.
  • Crea carpeta en Google Drive y guarda carpeta_drive en la ficha.
  • Email al cliente con enlace al Drive.
  • Email al comercial avisando.
  • UPDATE solicitudes: estado=completado + ficha_id (dispara trigger que copia fecha_solicitud).
  • Si TPV no integrado: tarea en Asana (proyecto Integraciones 1207920061546505) + email a soporte/a.jareno/luis.

Respuesta 200

{ "success": true }

📒 Contabilidad

POST /webhook/yurest-grabado-a3 Basic Auth

Workflow 13-grabado-a3. Toggle del flag grabado_a3 en una ficha. Trigger SQL setea grabado_a3_at al pasar de FALSE a TRUE.

Body

{ "id": "uuid", "grabado_a3": true | false }

Respuesta 200

{
  "success": true,
  "id": "uuid",
  "grabado_a3": true,
  "affected": 1,
  "errores": []
}

📁 Proyectos

GET POST PUT DELETE /webhook/proyectos Basic Auth

Workflow 01-proyectos-crud. CRUD de proyectos de implementación.

MétodoBodyRespuesta
GET{ proyectos: [...] }
POST{ proyecto: {...} }{ data: {...}, success: true }
PUT{ proyecto: { id, ...campos } }id devuelto
DELETE{ id: "uuid" }Soft-delete

El POST/PUT acepta asanaProjectId y asanaProjectUrl para vincular un tablero Asana.

PUT /webhook/proyectos/tarea Basic Auth

Workflow 02-proyectos-tareas. Actualiza una tarea/sección dentro de un proyecto (toggle completada, edición, etc.).

Body

{
  "proyectoId": "uuid",
  "seccionNombre": "Puesta en Marcha / Finalización",
  "tarea": { "id": "...", "completada": true, ... }
}

Respuesta 200

{ "success": true }
PUT /webhook/proyectos/tarea/mover Basic Auth

Mueve una tarea entre secciones (drag & drop kanban).

Body

{ "proyectoId": "uuid", "tareaId": "...", "seccionOrigen": "...", "seccionDestino": "..." }

📉 Bajas

GET POST /webhook/84f094b2... · /webhook/73ce8d34... · /webhook/95d5ed5d... Basic Auth

Workflow 05-bajas. Gestión de bajas de clientes (registro, edición de campos individuales y borrado).

EndpointOperación
bajasGET listado
bajaCliente · bajaLocal · bajaModulos · bajaEditarPOST campos específicos (mismo webhook con action)
bajaBorrarPOST borra una baja

📊 Distribución

POST /webhook/6d3ed726-c86a-4b86-a2ae-7f07da9630a5 Basic Auth

Workflow 06-distribucion. Asigna un implementador a una ficha.

Body

{ "fichaId": "uuid", "implementador": "Carlos Aparicio" }

📁 Drive

GET /webhook/2010bb2b-... · /webhook/bdef8517-... Basic Auth

Workflow 11-auxiliares. getDrive devuelve la URL de la carpeta Drive de una ficha; docsSubidos consulta si hay documentos subidos.

Query

?id=<ficha_uuid>

🔌 Integraciones externas (proxy)

GET /webhook/asana/tasks?projectId=... · /webhook/asana/task/stories?taskId=... Basic Auth

Workflow 07-calendar-asana. Proxy a la API de Asana para evitar exponer credenciales en el frontend. Devuelve tareas de un proyecto o historias (comentarios) de una tarea.

POST /webhook/calendar/event Basic Auth

Crea un evento en Google Calendar (sesiones de implementación).

Body

{ "summary": "...", "start": "ISO", "end": "ISO", "attendees": [...] }

Apéndice A · Tipos de datos

Objeto SEPA

{
  "referencia": "YUREST-5",
  "acreedor": {
    "identificador": "ES##ZZZB40597437",
    "nombre": "Yurest Solutions Sociedad Limitada",
    "direccion": "Calle Transits, 6",
    "cp": "46002", "poblacion": "Valencia", "provincia": "Valencia",
    "pais": "España"
  },
  "deudor": {
    "nombre": "...", "direccion": "...",
    "cp": "...", "poblacion": "...", "provincia": "...", "pais": "..."
  },
  "swift": "CAIXESBB",
  "iban": "ES9121000418450200051332",
  "tipo_pago": "recurrente" | "unico",
  "fecha_firma": "2026-04-17",
  "localidad": "Valencia",
  "firma_base64": "data:image/png;base64,...",
  "firmado_at": "2026-04-17T14:33:33.152Z"
}

Objeto Adjunto

{
  "id": "adj_xxx",
  "nombre": "contrato.pdf",
  "tipo": "application/pdf" | "image/png" | "image/jpeg",
  "size": 12345,
  "data": "data:application/pdf;base64,...",
  "fecha": "2026-04-17T..."
}

Objeto paquetes_carrito

{
  "items": [{ "id": "plan_pro", "precio": 1580 }],
  "descuentos": { "cart": 0, "planes_setup": 0, "planes_recur": 0 },
  "periodos": { "planes": "mensual" | "anual" },
  "corp_module_locales": { "modulo_x": [0, 1] },
  "locales_mensual": [25, 30]
}

Apéndice B · Tabla de estados

fichas_alta.estado

EstadoSignificadoQuién lo asigna
pendienteInicial (poco usado)
completadaCliente rellenó su parte (workflow 11)Cliente vía solicitud.html
rellenadoComercial completó la ficha (workflow 04)Comercial vía index.html

solicitudes.estado

EstadoSignificado
pendienteEsperando que el cliente la rellene
completadoCliente rellenó (genera ficha)
Nota semántica: los nombres son legacy. "completada" en fichas_alta ≠ "completado" en solicitudes. Los triggers SQL ya alinean fechas con esta semántica (fecha_rellenado, fecha_completado, grabado_a3_at) para que la analítica sea coherente.