CRM Multicanal

API · versión 1

Conecta tu sistema con el CRM.

Lee y crea contactos y negocios, sincroniza las existencias con tu tienda en línea o tu ERP, consulta la agenda y recibe avisos cuando algo pasa.

Autenticación

El dueño o un administrador crea una llave en el CRM, en Ajustes → API, y elige qué puede hacer. La llave se ve una sola vez. Va en cada petición, en la cabecera Authorization:

curl https://crm.jscautomations.com/api/v1/contactos \
  -H "Authorization: Bearer jsc_…"

Cada llave solo ve los datos de su empresa y solo hace lo que sus permisos permiten. Admite hasta 120 peticiones por minuto, y los listados devuelven hasta 100 filas por página. Todas las respuestas son JSON en UTF-8, y las fechas van en ISO 8601.

Rutas

GET/api/v1/contactos?buscar=marcela&pagina=1&por_pagina=50

Lista los contactos, los más nuevos primero. buscar filtra por nombre, correo o teléfono.

Permiso: contactos:leer (Leer contactos)

{ "datos": [{ "id": "…", "nombre": "Marcela Ríos", "correo": "marcela@ejemplo.co",
  "telefono": "+573001234567", "no_contactar": false, "creado_en": "…" }],
  "pagina": 1, "por_pagina": 50, "hay_mas": false }

GET/api/v1/contactos/{id}

Un contacto por su id.

Permiso: contactos:leer (Leer contactos)

{ "id": "…", "nombre": "Marcela Ríos", … }

POST/api/v1/contactos

Crea un contacto. Si ya hay uno con ese correo o teléfono, lo devuelve (200) en vez de duplicarlo: reintentar es seguro.

Permiso: contactos:escribir (Crear contactos)

{ "nombre": "Marcela Ríos", "correo": "marcela@ejemplo.co", "telefono": "+573001234567", "notas": "Vino de la tienda" }
201 { "id": "…", "nombre": "Marcela Ríos", …, "ya_existia": false }

GET/api/v1/negocios?pagina=1

Lista los negocios con su etapa, monto y contacto.

Permiso: negocios:leer (Leer negocios)

{ "datos": [{ "id": "…", "titulo": "Pedido web #1043", "monto": 238000, "etapa": "Nuevo", "contacto_id": "…" }], … }

POST/api/v1/negocios

Abre un negocio en el embudo. Entra por la primera etapa, o por la que nombres en etapa. El monto va en pesos enteros.

Permiso: negocios:escribir (Crear negocios)

{ "titulo": "Pedido web #1043", "monto": 238000, "contacto_id": "…", "etapa": "Nuevo" }
201 { "id": "…", "titulo": "Pedido web #1043", "monto": 238000, "etapa": "Nuevo", … }

GET/api/v1/productos?buscar=vestido

El catálogo con precio (final, con IVA incluido), tratamiento de IVA y existencias. existencias: null significa que no se controlan.

Permiso: catalogo:leer (Leer el catálogo)

{ "datos": [{ "id": "…", "referencia": "VMA-AZ-L", "nombre": "Vestido midi", "precio": 189900, "iva": "gravado_19", "existencias": 5, "activo": true }], … }

PUT/api/v1/productos/{id o referencia}/existencias

Pone las existencias de un producto, buscado por id o por referencia. Queda en el historial del catálogo como «Vía API». Con 0, el agente lo da por agotado.

Permiso: catalogo:escribir (Actualizar existencias)

{ "existencias": 12 }
{ "id": "…", "referencia": "VMA-AZ-L", "existencias": 12, … }

GET/api/v1/citas?desde=2026-10-01T00:00:00-05:00&hasta=2026-10-31T23:59:59-05:00

Las citas entre dos fechas (hasta 93 días). Sin fechas, las de los próximos 30 días.

Permiso: agenda:leer (Leer la agenda)

{ "datos": [{ "id": "…", "titulo": "Asesoría de estilo", "inicio": "…", "fin": "…", "estado": "confirmada", "contacto_id": "…" }], … }

GET/api/v1/webhooks

Los webhooks registrados y los eventos disponibles.

Permiso: webhooks:gestionar (Gestionar webhooks)

{ "datos": [{ "id": "…", "evento": "lead_captured", "url": "https://…", "activo": true }], "eventos": [ … ] }

POST/api/v1/webhooks

Registra una dirección que recibe un aviso cada vez que pasa el evento. Solo https. Devuelve el secreto para verificar la firma UNA vez.

Permiso: webhooks:gestionar (Gestionar webhooks)

{ "evento": "lead_captured", "url": "https://tu-sistema.com/crm" }
201 { "id": "…", "evento": "lead_captured", "url": "https://…", "secreto": "…" }

DELETE/api/v1/webhooks/{id}

Deja de enviar avisos a esa dirección.

Permiso: webhooks:gestionar (Gestionar webhooks)

204 (sin cuerpo)

Errores

Siempre con la misma forma, para que tu sistema decida por el código y no por el texto:

{ "error": { "codigo": "sin_permiso", "mensaje": "Esta llave no tiene el permiso…" } }
400
Algo del cuerpo o los parámetros no es válido. El mensaje dice qué.
401
Falta la llave, no es válida o fue revocada.
403
La llave no tiene ese permiso, o el plan de la empresa no está activo.
404
No existe (o es de otra empresa: la respuesta es la misma).
429
Más de 120 peticiones en un minuto con esa llave. Espera los segundos de Retry-After.

Webhooks

El CRM envía un POST a tu dirección con este cuerpo, y la cabecera X-JSC-Signature: el HMAC-SHA256 del cuerpo, en hexadecimal, con el secreto que te dio el registro. Calcúlalo sobre el cuerpo tal como llega y compáralo antes de confiar en el aviso.

{ "event": "lead_captured", "tenantId": "…", "timestamp": "2026-10-01T15:04:05.000Z",
  "data": { "contacto": { "nombre": "Marcela Ríos", "telefono": "+573001234567" }, … } }
lead_captured
Cuando un cliente deja sus datos.
conversation_escalated
Cuando una conversación pasa a una persona.
cita_agendada
Cuando el agente agenda una cita.