Upnify Documentación API

MÓDULO

Inicia aquí

Primeros pasos y conceptos relevantes para iniciar tu integración con la API de Upnify.

Bienvenida

Bienvenida

Te damos la bienvenida a la API de Upnify. Esta guía reúne los conceptos y recomendaciones que conviene conocer antes de comenzar una integración.

Aprende con una primera integración

Estos tutoriales breves incluyen pasos, código y un resultado que puedes comprobar. Recórrelos en orden o elige el tema que necesitas:

Conocimientos previos

Para desarrollar una integración con mayor seguridad y rapidez, te recomendamos contar con experiencia en:

  • El protocolo HTTP y servicios REST. Si necesitas reforzar estos conceptos, consulta la sección REST.
  • El funcionamiento del proceso y la cuenta de Upnify que integrarás.
  • Un lenguaje de programación, por ejemplo Node.js, C#, Go, Python, PHP, Java, Perl o Ruby.
  • Un cliente HTTP como Postman o Insomnia para explorar y probar solicitudes.

Cómo funciona la API de Upnify

La API usa un estilo REST y JSON para intercambiar información. Cada módulo documenta las rutas disponibles, los parámetros que debes enviar y el formato de sus respuestas.

Para realizar solicitudes autenticadas, la forma recomendada es obtener un token de integración e intercambiarlo por un token de sesión mediante POST /integraciones/sesion. Consulta Autenticación para realizar tu primera solicitud e Integraciones para conocer la vigencia y renovación de la sesión.

Trata los tokens y las credenciales como secretos: no los incluyas en código fuente, repositorios, registros de aplicación ni interfaces de usuario. Guárdalos en la configuración segura de tu aplicación y sustitúyelos si sospechas que fueron expuestos.

Consideraciones para tu integración

  • Consulta los estándares del API antes de implementar. Te ayudarán a interpretar solicitudes, respuestas y códigos HTTP de forma consistente.
  • Respeta el límite de 100 solicitudes por minuto. Si lo superas, la API puede responder con el código HTTP 429. Implementa espera y reintentos graduales; no repitas la solicitud de inmediato ni aumentes la frecuencia de llamadas.
  • Cuando estén disponibles para el evento que necesitas, utiliza webhooks en lugar de consultar periódicamente la información. Upnify puede notificar a tu sistema eventos como la creación de un prospecto, cliente o venta, evitando sincronizaciones innecesarias y acercando la integración al tiempo real.
  • Prueba los flujos completos: solicitudes correctas, datos faltantes, errores de autenticación, límites de consumo y reintentos. Registra solo la información necesaria y nunca tokens, contraseñas ni datos personales completos.

Automatizaciones sin código

También puedes conectar Upnify con otras aplicaciones mediante herramientas como Integromat o Zapier. Estas plataformas pueden ayudarte a crear automatizaciones como:

  • Agregar un cliente nuevo a una hoja de cálculo.
  • Notificar un prospecto nuevo a un grupo de Telegram.
  • Crear un cliente a partir de una venta de WooCommerce.

Antes de activar una automatización en producción, valida los campos que se comparten, los permisos del usuario o integración y el tratamiento de información sensible.

REST

REST y servicios RESTful

REST significa Representational State Transfer. Es un estilo de arquitectura para diseñar servicios web sencillos, mantenibles y escalables. Una API que sigue estos principios se conoce como API RESTful.

REST no es un protocolo ni una tecnología específica: aprovecha las convenciones de HTTP para que una aplicación cliente pueda solicitar o modificar información de un servicio web de forma predecible.

Recursos y URL

En REST, la información se organiza como recursos: por ejemplo, clientes, prospectos, ventas o productos. Cada recurso se identifica mediante una URL.

https://api.upnify.com/v4/clientes

Una URI identifica un recurso; una URL es un tipo de URI que además indica cómo localizarlo. En esta documentación usamos “URL” para referirnos a las direcciones que debes invocar.

Las rutas pueden incluir:

  • Parámetros de ruta, que identifican un recurso concreto, como /clientes/:tkCliente.
  • Parámetros de consulta, después de ?, para filtrar, ordenar o paginar resultados.
  • Un cuerpo JSON, normalmente al crear o actualizar información.

JSON: el formato de intercambio

La API intercambia datos mediante JSON (JavaScript Object Notation), un formato de texto legible por personas y fácil de procesar en la mayoría de los lenguajes.

{
  "nombre": "Usuario de ejemplo",
  "apellido": "Pérez",
  "edad": 38,
  "correo": "usuario@upnify.com"
}

Al enviar un cuerpo JSON, incluye el encabezado Content-Type: application/json. Revisa siempre la ficha del endpoint para conocer los campos requeridos, sus tipos y restricciones.

HTTP y sus métodos

HTTP define la comunicación entre tu aplicación y la API. Cada solicitud usa un método —también llamado verbo— que expresa la operación deseada sobre un recurso.

Método Uso habitual Consideración
GET Consultar recursos. No debe modificar información y puede repetirse sin cambiar el resultado esperado.
POST Crear un recurso o ejecutar una acción. No suele ser idempotente: repetir una solicitud puede generar otra operación.
PUT Actualizar un recurso existente. Envía solo los campos que la ficha del endpoint permite modificar.
DELETE Eliminar o desactivar un recurso. Revisa la ficha: según el recurso, la eliminación puede ser lógica o permanente.

Una solicitud HTTP incluye una URL, un método, encabezados y, cuando aplica, un cuerpo. La respuesta contiene un código de estado HTTP y, normalmente, datos JSON.

Códigos de respuesta

Como guía general, los códigos HTTP se agrupan así:

  • 2xx: la solicitud se procesó correctamente.
  • 4xx: la solicitud requiere corrección, autenticación o permisos adicionales. Por ejemplo, 401 y 403 se relacionan con acceso, y 429 indica que superaste el límite de solicitudes.
  • 5xx: ocurrió un problema en el servidor. Conserva un identificador de seguimiento si la respuesta lo proporciona y reintenta solo cuando sea apropiado.

No supongas que todas las rutas devuelven la misma estructura. Consulta la sección Respuesta de cada endpoint antes de procesar los datos.

Recomendaciones prácticas

  • Usa siempre HTTPS y conserva el token de sesión como un secreto. No lo incluyas en repositorios, registros ni URLs compartidas.
  • Envía únicamente los encabezados y parámetros documentados para cada endpoint.
  • Implementa tiempos de espera, manejo de errores y reintentos graduales. Ante un 429, espera antes de reintentar.
  • Pagina los listados y usa filtros para reducir el volumen de datos.
  • Cuando un evento admita webhooks, prefírelos a consultar la API de forma repetitiva.

Continúa con Autenticación para obtener un token y con Integraciones para conocer opciones de conexión de larga duración.

Autenticación

La forma recomendada de acceder al API de Upnify de manera consistente y segura es utilizar un token de integración e intercambiarlo por un token de sesión. El acceso de estas sesiones está limitado para integraciones.

1. Obtén un token de integración

Da de alta una integración en Ajustes → API dentro de tu cuenta de Upnify CRM y selecciona el logotipo de Upnify. Esto agregará una nueva integración para sistemas externos y te asignará su token de integración el cuál deberás intercambiar por uno de sesión. Consulta Integraciones para conocer la diferencia entre ambos tokens y cómo administrar la vigencia de la sesión.

Los valores TOKEN-INTEGRACION-EJEMPLO y TOKEN-SESION-EJEMPLO de esta guía son ficticios. Sustitúyelos por los valores de tu integración y de la sesión obtenida, respectivamente.

2. Intercambia el token por una sesión

Envía el token de integración en el encabezado token de POST /integraciones/sesion. Esta solicitud no necesita cuerpo.

curl --request POST \
  --url 'https://api.upnify.com/integraciones/sesion' \
  --header 'token: TOKEN-INTEGRACION-EJEMPLO' \
  --header 'Accept: application/json'

La respuesta es un arreglo JSON. Este ejemplo muestra una sesión obtenida el 22 de septiembre de 2026 a las 12:00, con dos días de vigencia:

[
  {
    "code": 0,
    "token": "TOKEN-SESION-EJEMPLO",
    "details": {
      "expiracion": "2026-09-24T12:00:00",
      "tkIntegracion": "TOKEN-INTEGRACION-EJEMPLO"
    }
  }
]

Comprueba que code sea 0 y guarda el valor de [0].token: ese es el token de sesión que usarás para consultar el API. details.tkIntegracion identifica el token de integración y details.expiracion informa el vencimiento vigente de la sesión, en hora local del servidor (CDMX), sin indicador de zona horaria.

3. Consulta el API con el token de sesión

Envía el token de sesión obtenido en el encabezado token de cada solicitud autenticada. Por ejemplo, para consultar prospectos con GET /prospectos:

curl --request GET \
  --url 'https://api.upnify.com/prospectos' \
  --header 'token: TOKEN-SESION-EJEMPLO' \
  --header 'Accept: application/json'

Vigencia y renovación de la sesión

Una sesión nueva tiene dos días de vigencia desde su creación. Al repetir POST /integraciones/sesion con el token de integración, el API reutiliza la sesión existente:

  • Si quedan cinco horas o más antes del vencimiento, conserva su fecha de expiración.
  • Si quedan menos de cinco horas o la sesión ya venció, renueva su vigencia por dos días desde el momento del intercambio.

La renovación conserva el token de la sesión existente. Guarda siempre el token y la fecha devueltos por el intercambio de forma segura para usar los valores vigentes.

El campo details.expiracion informa el vencimiento vigente, incluida la renovación cuando ocurre. Está expresado en formato ISO 8601, en hora local del servidor (CDMX), sin indicador de zona horaria. Puede ser null en sesiones anteriores que no tengan una fecha de expiración registrada; no interpretes ese valor como una garantía de vigencia indefinida.

Realizar consultas al API no renueva la sesión. Programa el intercambio dentro de las últimas cinco horas de vigencia, antes del vencimiento. Si la sesión ya expiró, repite el intercambio con el token de integración antes de continuar con las solicitudes autenticadas.

Protección de los tokens

Guarda ambos tokens en la configuración segura de tu aplicación y utiliza HTTPS. No los incluyas en repositorios, registros ni interfaces de usuario.

Tu primera petición

Objetivo: intercambiar tu token de integración y consultar hasta cinco prospectos. Duración: 5 minutos.

Paso 1. Prepara tu token

En Upnify CRM, entra a Ajustes → API, selecciona el logotipo de Upnify y obtén el token de la integración para sistemas externos. Puedes consultar los detalles en Autenticación.

Para el ejemplo completo necesitas Node.js 22 o posterior. Crea una carpeta de práctica y, dentro de ella, un archivo .env:

UPNIFY_TOKEN_INTEGRACION=TOKEN-INTEGRACION-EJEMPLO

Sustituye el valor ficticio por tu token. Mantén .env fuera del control de versiones y no lo compartas.

Paso 2. Reconoce las dos solicitudes

Primero se envía el token de integración a POST /integraciones/sesion:

curl --request POST 'https://api.upnify.com/integraciones/sesion' \
  --header 'token: TOKEN-INTEGRACION-EJEMPLO'

Si [0].code es 0, toma [0].token de la respuesta. Ese token de sesión se utiliza en GET /prospectos:

curl --get 'https://api.upnify.com/prospectos' \
  --header 'token: TOKEN-SESION-EJEMPLO' \
  --data-urlencode 'pagina=1' \
  --data-urlencode 'cantidadRegistros=5'

Los valores de ambos comandos son ficticios. El segundo se sustituye por el token devuelto por el primero.

Paso 3. Une el flujo en un programa

Guarda este código como primera-peticion.cjs. El programa conserva la sesión en memoria y muestra únicamente cuántos prospectos recibió.

async function main() {
  const tokenIntegracion = process.env.UPNIFY_TOKEN_INTEGRACION;
  if (!tokenIntegracion) throw new Error("Configura UPNIFY_TOKEN_INTEGRACION.");

  const intercambio = await fetch("https://api.upnify.com/integraciones/sesion", {
    method: "POST",
    headers: { token: tokenIntegracion },
  });
  if (!intercambio.ok) throw new Error(`Intercambio: HTTP ${intercambio.status}.`);
  const [sesion] = await intercambio.json();
  if (sesion?.code !== 0 || !sesion.token) {
    throw new Error("No se recibió una sesión válida.");
  }

  const respuesta = await fetch(
    "https://api.upnify.com/prospectos?pagina=1&cantidadRegistros=5",
    { headers: { token: sesion.token } },
  );
  if (!respuesta.ok) throw new Error(`Consulta: HTTP ${respuesta.status}.`);
  const prospectos = await respuesta.json();
  if (!Array.isArray(prospectos)) throw new Error("Se esperaba una lista.");
  console.log(`Conexión correcta. Prospectos recibidos: ${prospectos.length}.`);
}

main().catch((error) => {
  console.error(error.message);
  process.exitCode = 1;
});

Paso 4. Ejecuta y comprueba

node --env-file=.env primera-peticion.cjs

Resultado esperado: un mensaje de conexión correcta y un número entre 0 y 5. Una lista vacía también es una respuesta válida. Conserva la fecha details.expiracion al incorporar el ejemplo a tu aplicación: las sesiones nuevas duran dos días y se renuevan mediante el intercambio descrito en Autenticación.

Siguiente: crea un prospecto desde un formulario HTML.

Del formulario al CRM

Objetivo: crear un prospecto desde una página HTML con JavaScript, sin instalar un framework. Duración: 10 minutos.

Paso 1. Prepara una prueba local

Obtén un token de sesión siguiendo tu primera petición. Usa una cuenta destinada a pruebas: al enviar el formulario se creará un registro mediante POST /prospectos.

Este formulario es una herramienta local para quien desarrolla la integración. Introducirás tu token de sesión al probarlo; no quedará escrito en el archivo y el ejemplo no lo almacenará en cookies ni almacenamiento local. No uses este patrón para pedir credenciales a visitantes de un formulario público: el código del front-end y sus peticiones son visibles para quien utiliza la página.

Paso 2. Crea el formulario

Copia este documento completo en un archivo llamado formulario.html. Incluye nombre, apellidos, correo y teléfono como texto; tu cuenta puede exigir campos adicionales que deberás agregar según la respuesta de validación.

<!doctype html>
<html lang="es">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Mi primer prospecto</title>
</head>
<body>
  <h1>Crear un prospecto de prueba</h1>
  <form id="formulario">
    <p><label>Token de sesión
      <input name="token" type="password" required autocomplete="off">
    </label></p>
    <p><label>Nombre <input name="nombre" required maxlength="128"></label></p>
    <p><label>Apellidos <input name="apellidos" required maxlength="128"></label></p>
    <p><label>Correo <input name="correo" type="email" required maxlength="256"></label></p>
    <p><label>Teléfono <input name="telefono" type="tel" required maxlength="128"></label></p>
    <button type="submit">Crear prospecto</button>
  </form>
  <p id="estado" role="status" aria-live="polite"></p>

  <script>
    const formulario = document.querySelector("#formulario");
    const estado = document.querySelector("#estado");
    const boton = formulario.querySelector("button");

    formulario.addEventListener("submit", async (evento) => {
      evento.preventDefault();
      if (boton.disabled) return;
      boton.disabled = true;
      estado.textContent = "Enviando…";

      try {
        const campos = new FormData(formulario);
        const token = campos.get("token").trim();
        const prospecto = {
          nombre: campos.get("nombre").trim(),
          apellidos: campos.get("apellidos").trim(),
          correo: campos.get("correo").trim(),
          telefono: campos.get("telefono").trim(),
        };
        if (!token || !prospecto.nombre || !prospecto.correo) {
          throw new Error("Completa el token, el nombre y el correo.");
        }
        const respuesta = await fetch("https://api.upnify.com/prospectos", {
          method: "POST",
          headers: { token, "Content-Type": "application/json" },
          body: JSON.stringify(prospecto),
        });
        const datos = await respuesta.json();
        const resultado = datos[0];
        if (!respuesta.ok || resultado?.code !== 0) {
          const detalle = resultado?.fields ? ` Campos: ${resultado.fields}.` : "";
          throw new Error((resultado?.msg || `HTTP ${respuesta.status}. Revisa la solicitud.`) + detalle);
        }
        estado.textContent = "Prospecto creado. Comprueba el registro en Upnify.";
        formulario.reset();
      } catch (error) {
        estado.textContent = `${error.message} Si no se confirmó el envío, revisa Upnify antes de repetirlo.`;
      } finally {
        boton.disabled = false;
      }
    });
  </script>
</body>
</html>

El navegador valida los campos antes de enviar. JavaScript evita que la página se recargue, envía el token en el encabezado y los datos del prospecto como JSON. El botón queda deshabilitado mientras espera la respuesta para evitar envíos repetidos.

Paso 3. Abre la página y envía un registro

Desde la carpeta donde guardaste el archivo, puedes servirlo con Python 3:

python3 -m http.server 8000 --bind 127.0.0.1

Abre http://127.0.0.1:8000/formulario.html en tu navegador. Introduce tu token de sesión y datos ficticios, por ejemplo nombre Persona, apellidos De prueba, correo persona@example.com y teléfono 0000000000. Pulsa Crear prospecto una sola vez.

Paso 4. Comprueba el resultado

Resultado esperado: aparece “Prospecto creado” y puedes localizar el registro en Upnify. Si la cuenta exige otros datos, completa los campos indicados por el API y vuelve a probar. Si recibes un error de sesión, obtén una sesión vigente; si el navegador muestra un error de red o CORS, revisa la pestaña Red de sus herramientas de desarrollo para confirmar si la solicitud salió y qué respondió el API.

Siguiente: busca un prospecto antes de crearlo.

Busca antes de crear

Objetivo: buscar candidatos por correo y comprobar si hay una coincidencia exacta antes de registrar otro prospecto. Duración: 8 minutos.

Paso 1. Prepara el correo y la sesión

Usaremos GET /sistema/buscar, con secciones=prospectos, y compararemos el campo correo de los resultados. La búsqueda recibe texto de al menos tres caracteres y puede devolver coincidencias parciales. Su respuesta contiene dos listas: [0] incluye los totales por sección y [1] contiene los registros encontrados.

Con Node.js 22 o posterior, crea un archivo .env privado con estos valores, sustituyendo el token ficticio por tu sesión vigente:

UPNIFY_TOKEN_SESION=TOKEN-SESION-EJEMPLO
CORREO_PRUEBA=persona@example.com

Paso 2. Consulta los candidatos

Esta solicitud muestra cómo codificar el correo sin concatenarlo directamente en la URL:

curl --get 'https://api.upnify.com/sistema/buscar' \
  --header 'token: TOKEN-SESION-EJEMPLO' \
  --data-urlencode 'secciones=prospectos' \
  --data-urlencode 'buscar=persona@example.com' \
  --data-urlencode 'pagina=1' \
  --data-urlencode 'cantidadRegistros=20'

Paso 3. Comprueba el correo exacto

Guarda lo siguiente como buscar-prospecto.cjs. Revisa hasta cinco páginas de candidatos. Si alcanza ese límite sin completar la búsqueda, se detiene sin concluir que el contacto no existe.

async function buscarProspecto(correo, token) {
  const normalizar = (valor) => String(valor || "").trim().toLowerCase();
  const buscado = normalizar(correo);

  for (let pagina = 1; pagina <= 5; pagina += 1) {
    const url = new URL("https://api.upnify.com/sistema/buscar");
    url.search = new URLSearchParams({
      secciones: "prospectos", buscar: buscado,
      pagina: String(pagina), cantidadRegistros: "20",
    }).toString();
    const respuesta = await fetch(url, { headers: { token } });
    if (!respuesta.ok) throw new Error(`Búsqueda: HTTP ${respuesta.status}.`);
    const datos = await respuesta.json();
    const candidatos = datos[1];
    if (!Array.isArray(candidatos)) throw new Error("Se esperaba una lista.");

    const existente = candidatos.find((p) => normalizar(p.correo) === buscado);
    if (existente) return existente;
    if (candidatos.length < 20) return null;
  }
  throw new Error("Búsqueda incompleta: revisa más páginas antes de crear.");
}

async function main() {
  const token = process.env.UPNIFY_TOKEN_SESION;
  const correo = process.env.CORREO_PRUEBA?.trim();
  if (!token || !correo || correo.length < 3) {
    throw new Error("Configura una sesión y un correo de prueba válido.");
  }
  const existente = await buscarProspecto(correo, token);
  if (existente) {
    // Usa existente.tkProspecto en las operaciones siguientes.
    console.log("Coincidencia encontrada: reutiliza el prospecto.");
  } else {
    console.log("Sin coincidencias exactas en los resultados consultados.");
  }
}

main().catch((error) => {
  console.error(error.message);
  process.exitCode = 1;
});

Paso 4. Decide la siguiente acción

node --env-file=.env buscar-prospecto.cjs

Resultado esperado: si usas el correo del registro creado en el tutorial anterior, el programa indica una coincidencia y evita una nueva alta. Si no encuentra coincidencias, revisa los resultados y utiliza el formulario cuando corresponda crear el registro.

Esta consulta sólo cubre los prospectos visibles que devuelve la búsqueda; no garantiza unicidad en toda la cuenta. Dos procesos pueden consultar antes de que cualquiera cree el registro. Conserva las validaciones de unicidad de la cuenta y atiende cualquier rechazo del API. Si la búsqueda falla o queda incompleta, no uses ese resultado para autorizar una creación.

Siguiente: consulta por filtros y páginas.

Filtra y pagina prospectos

Objetivo: consultar prospectos de un país y recorrer hasta dos páginas de diez registros. Duración: 5 minutos.

Paso 1. Elige el filtro y el tamaño de página

GET /prospectos acepta el filtro idPais y los parámetros de paginación pagina y cantidadRegistros. En este ejemplo usamos MX y comenzamos en la página 1.

curl --get 'https://api.upnify.com/prospectos' \
  --header 'token: TOKEN-SESION-EJEMPLO' \
  --data-urlencode 'idPais=MX' \
  --data-urlencode 'pagina=1' \
  --data-urlencode 'cantidadRegistros=10'

Sustituye el token ficticio por tu sesión vigente. Para pedir la siguiente página, conserva el filtro y el tamaño y cambia únicamente pagina=2.

Paso 2. Recorre dos páginas desde Node.js

Usa Node.js 22 o posterior y un archivo .env privado con UPNIFY_TOKEN_SESION=TOKEN-SESION-EJEMPLO, sustituyendo el valor de ejemplo. Guarda este código como paginar-prospectos.cjs:

async function main() {
  const token = process.env.UPNIFY_TOKEN_SESION;
  if (!token) throw new Error("Configura UPNIFY_TOKEN_SESION.");
  const cantidadRegistros = 10;
  let recibidos = 0;

  for (let pagina = 1; pagina <= 2; pagina += 1) {
    const url = new URL("https://api.upnify.com/prospectos");
    url.search = new URLSearchParams({
      idPais: "MX", pagina: String(pagina),
      cantidadRegistros: String(cantidadRegistros),
    }).toString();
    const respuesta = await fetch(url, { headers: { token } });
    if (!respuesta.ok) throw new Error(`Consulta: HTTP ${respuesta.status}.`);
    const prospectos = await respuesta.json();
    if (!Array.isArray(prospectos)) throw new Error("Se esperaba una lista.");

    recibidos += prospectos.length;
    console.log(`Página ${pagina}: ${prospectos.length} registros.`);
    // Procesa los prospectos de esta página antes de consultar la siguiente.
    if (prospectos.length < cantidadRegistros) break;
  }
  console.log(`Total recibido en esta práctica: ${recibidos}.`);
}

main().catch((error) => {
  console.error(error.message);
  process.exitCode = 1;
});

Paso 3. Ejecuta y observa cuándo termina

node --env-file=.env paginar-prospectos.cjs

Resultado esperado: el programa recibe entre 0 y 20 registros. Si una página tiene menos de diez, termina; si ambas están completas, se detiene en la segunda por el límite de esta práctica. Ese total no representa necesariamente todos los prospectos de la cuenta.

Paso 4. Adapta el ejemplo

Cambia MX por el país que necesites y repite la consulta. Una lista vacía puede significar que no hay prospectos visibles con ese filtro. Para una sincronización mayor, procesa cada página antes de avanzar y contempla que los registros pueden cambiar entre solicitudes; la paginación no representa una fotografía inmutable de la cuenta.

Siguiente: aprende a manejar errores.

Maneja los errores

Objetivo: distinguir cuándo renovar la sesión, corregir datos o esperar antes de reintentar. Duración: 10 minutos.

Paso 1. Lee el estado HTTP y el código del API

Una petición puede fallar aunque fetch no lance una excepción: revisa respuesta.ok, el estado HTTP y el cuerpo JSON. Los errores del API se devuelven como un arreglo; el primer elemento puede incluir code, msg y fields.

Situación Cómo reconocerla Qué hacer
Sesión vencida HTTP 401, code: 40003 Repite el intercambio con el token de integración y usa la sesión devuelta.
Datos incorrectos Por ejemplo, HTTP 409, code: 2 Revisa msg y fields, corrige la solicitud y vuelve a enviarla.
Límite de solicitudes HTTP 429 Reduce la frecuencia y espera antes de reintentar.
Otro error de acceso Otro HTTP 401 o HTTP 403 Revisa las credenciales o el acceso; no repitas indefinidamente.

Ejemplo de una respuesta de sesión vencida:

[
  { "code": 40003, "msg": "Sesion expirada." }
]

Paso 2. Prepara ambos tokens

Con Node.js 22 o posterior, coloca en un archivo .env privado tu token de integración y una sesión obtenida mediante Autenticación. Sustituye estos valores ficticios:

UPNIFY_TOKEN_INTEGRACION=TOKEN-INTEGRACION-EJEMPLO
UPNIFY_TOKEN_SESION=TOKEN-SESION-EJEMPLO

Paso 3. Añade reintentos limitados a una consulta

Guarda este código como manejar-errores.cjs. Hace como máximo tres intentos de lectura, renueva una sola vez si la sesión venció y espera uno o dos minutos ante un 429.

const esperar = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function renovarSesion(tokenIntegracion) {
  const respuesta = await fetch("https://api.upnify.com/integraciones/sesion", {
    method: "POST", headers: { token: tokenIntegracion },
  });
  if (!respuesta.ok) throw new Error(`Intercambio: HTTP ${respuesta.status}.`);
  const [sesion] = await respuesta.json();
  if (sesion?.code !== 0 || !sesion.token) {
    throw new Error("No se recibió una sesión válida.");
  }
  return sesion;
}

async function consultarProspectos(token, tokenIntegracion) {
  let renovada = false;
  for (let intento = 0; intento < 3; intento += 1) {
    const respuesta = await fetch(
      "https://api.upnify.com/prospectos?pagina=1&cantidadRegistros=5",
      { headers: { token } },
    );
    const datos = await respuesta.json().catch(() => null);
    if (respuesta.ok) {
      if (!Array.isArray(datos)) throw new Error("Se esperaba una lista JSON.");
      return datos;
    }
    const errorApi = datos?.[0];
    if (respuesta.status === 401 && errorApi?.code === 40003 && !renovada && intento < 2) {
      const sesion = await renovarSesion(tokenIntegracion);
      token = sesion.token;
      renovada = true;
      // En tu aplicación, conserva token y sesion.details.expiracion de forma segura.
      continue;
    }
    if (respuesta.status === 429 && intento < 2) {
      await esperar(60_000 * (intento + 1));
      continue;
    }
    throw new Error(`HTTP ${respuesta.status}; código ${errorApi?.code ?? "no disponible"}.`);
  }
}

async function main() {
  const token = process.env.UPNIFY_TOKEN_SESION;
  const tokenIntegracion = process.env.UPNIFY_TOKEN_INTEGRACION;
  if (!token || !tokenIntegracion) throw new Error("Configura ambos tokens en .env.");
  const prospectos = await consultarProspectos(token, tokenIntegracion);
  console.log(`Consulta completada: ${prospectos.length} registros.`);
}

main().catch((error) => {
  console.error(error.message);
  process.exitCode = 1;
});

Paso 4. Comprueba cada decisión

node --env-file=.env manejar-errores.cjs

Resultado esperado: con una sesión vigente, la consulta termina en el primer intento. Si vence, se intercambia el token y se repite la lectura. Si se agotan los intentos, se muestra el error y el programa termina.

Para practicar los fallos, sustituye fetch por respuestas simuladas: una secuencia 401/40003 → intercambio correcto → 200, otra 429 → 200 y otra 409/2. Comprueba que la última se detenga sin repetir la solicitud. No necesitas generar tráfico para provocar el límite del API.

Antes de aplicarlo a escrituras: un fallo de red no confirma si el servidor creó el registro. No traslades estos reintentos automáticamente a POST /prospectos; primero busca y comprueba el resultado para evitar altas repetidas. Las consultas normales no renuevan la sesión: programa su renovación según Autenticación.

Integraciones

Las integraciones conectan tu aplicación con Upnify para recibir contactos, consultar catálogos, configurar avisos y reservar citas. Cada ficha indica dónde enviar los parámetros, qué devuelve la operación y cómo llamarla desde cURL, JavaScript, Node.js, Python, Go y .NET.

Identificadores y autenticación

Conserva los nombres y valores devueltos por cada operación:

Valor Uso
tkIntegracion Identifica una integración para consultarla, configurarla o eliminarla.
Token de integración Autoriza la recepción de contactos y las operaciones que lo solicitan. Conserva el valor completo, incluido su prefijo. Puede aparecer como tkIntegracionSesion al crear una integración o tkSesionIntegracion al consultarla.
Token de sesión Se obtiene intercambiando el token de integración mediante POST /integraciones/sesion. Se envía en el encabezado token de las operaciones que requieren una sesión.
idFormulario Identificador del formulario asociado a una integración, devuelto al crearla o consultarla.

La ubicación de token depende de la ruta: puede ser un encabezado, un segmento de la URL o un campo del cuerpo. Sigue la ficha de la operación. Guarda los tokens de forma segura y evita registrarlos o exponer las configuraciones que los contienen.

Recepción de contactos

  1. Consulta los catálogos para obtener los identificadores de fases, orígenes, etiquetas y campos personalizados que necesites.
  2. Envía el contacto a POST /integraciones/:token con al menos correo o movil. Si configuras un mapeo, usa los nombres de entrada esperados por esa configuración.
  3. Revisa details[0].tkContacto y details[0].action para saber qué contacto se procesó y qué acción se realizó. HTTP 200 por sí solo no confirma que se haya creado un contacto.
  4. Utiliza un trid distinto por solicitud y conserva ese valor al reintentarla. Si ya aparece en el historial, la respuesta indica duplicated.

Para modificar un contacto existente, utiliza PUT /integraciones/:token con tkProspecto y los campos admitidos en su ficha. Esta operación puede reactivar el contacto y no admite todos los campos de la recepción inicial.

Calendarios y formularios

Para reservar una cita, consulta primero los horarios con POST /integraciones/calendario, registra o localiza al contacto con POST /integraciones/calendario/prospecto y utiliza los identificadores resultantes en POST /integraciones/calendario/cita. Ofrece únicamente horarios con ocupado: false y comprueba que la reserva devuelva tkCita.

Para cambiar la configuración de una integración, utiliza PUT /integraciones/:tkIntegracion/config.

Lectura de las respuestas

Las fichas distinguen entre respuestas que son arreglos y respuestas que son objetos. Revisa siempre el estado HTTP y el contenido recibido. Los listados paginados indican sus parámetros y, cuando corresponde, el total del encabezado Row-Count.

Algunas configuraciones se envían como texto JSON dentro del cuerpo; la tabla de parámetros lo indica expresamente. En las respuestas normalizadas, esas configuraciones pueden aparecer como objetos JSON. Los ejemplos utilizan datos ficticios que debes sustituir por los de tu integración.

POST /integraciones/webhooksRegistrar un webhook DELETE /integraciones/webhooks/:tkWebhookEliminar un webhook GET /integraciones/plantillasConsultar plantillas de integración POST /integraciones/plantillasCrear una plantilla de integración PUT /integraciones/plantillas/:tkIntegracionPlantillaActualizar una plantilla de integración DELETE /integraciones/plantillas/:tkIntegracionPlantillaEliminar una plantilla de integración POST /integracionesCrear una integración POST /integraciones/sesionObtener o renovar una sesión POST /integraciones/valida/:tokenVerificar un token de integración GET /integraciones/catalogos/:catalogo/:tokenConsultar un catálogo para integraciones GET /integraciones/formulariosConsultar integraciones para formularios GET /integracionesListar integraciones de la cuenta GET /integraciones/:tkIntegracionConsultar el detalle de una integración GET /integraciones/:tkIntegracion/historicoConsultar el historial de una integración POST /integraciones/calendarioConsultar horarios de un calendario POST /integraciones/calendario/prospectoRegistrar el contacto de una reserva GET /integraciones/widgets/:tkWidgetConsultar la configuración de un widget POST /integraciones/calendario/citaCrear una cita desde un calendario POST /integraciones/:tokenRecibir un contacto desde una integración PUT /integraciones/:tokenActualizar un contacto desde una integración GET /integraciones/conversiones-datos/:tkIntegracionConsultar conversiones de ventas PUT /integraciones/:tkIntegracion/configActualizar la configuración de una integración DELETE /integraciones/:tkIntegracionEliminar una integración