Obtener transacciones aprobadas

Cómo traer las transacciones según su estado de aprobación (aprobadas, rechazadas, pendientes…) y mantenerlas sincronizadas.

Caso de uso

Cada transacción pasa por un flujo de aprobación: el responsable la envía y los aprobadores la aprueban, la rechazan o piden más información. Esta receta trae las transacciones aprobadas, pero sirve igual para cualquier estado de aprobación: solo cambia el valor del filtro.

Aprobada no es lo mismo que pago autorizado

Una transacción tiene dos estados independientes:

  • Estado de aprobación (approvalWorkflow.status, filtro approvalWorkflowStatus): si tu empresa aprobó el gasto. Es el que usa esta receta.
  • Estado del pago (summaryStatus y transactionStatus): si la transacción se autorizó, se confirmó o se rechazó en el procesador. AUTHORIZED_PAYMENT significa que el pago se autorizó, no que el gasto esté aprobado.

Estados de aprobación

Filtra con approvalWorkflowStatus y uno o más de estos valores:

ValorSignificado
AUTHORIZEDAprobada en todos los niveles.
PARTIAL_AUTHORIZEDAprobada en al menos un nivel, esperando el siguiente.
SUBMITTEDEnviada, esperando la primera aprobación.
PENDING_SUBMISSIONPendiente de envío: faltan campos obligatorios.
INFORMATION_REQUIREDUn aprobador pidió información al responsable.
UNAUTHORIZEDRechazada.
EXEMPTEDEximida del flujo por una regla de exención.
ERRORError al procesar el flujo.
PENDINGValor histórico, solo en transacciones anteriores a PENDING_SUBMISSION.

Un valor que no está en la lista responde 400.

1. Trae las transacciones en el estado que necesitas

curl -g -X GET 'https://{HOST}/api/public/v1/purchases?approvalWorkflowStatus=AUTHORIZED&size=500&page=0&sort[0].property=createdDate&sort[0].direction=DESC' \
  -H 'X-API-KEY: tu_api_key_aqui'

Para varios estados a la vez, repite el parámetro. Por ejemplo, aprobadas y eximidas:

curl -X GET 'https://{HOST}/api/public/v1/purchases?approvalWorkflowStatus=AUTHORIZED&approvalWorkflowStatus=EXEMPTED&size=500' \
  -H 'X-API-KEY: tu_api_key_aqui'

Cada transacción trae su estado en approvalWorkflow:

{
  "uniqueCode": "…",
  "companyCode": "…",
  "approvalWorkflow": {
    "status": "AUTHORIZED",
    "lastEventType": "APPROVE",
    "lastEventAuditorUniqueCode": "…",
    "lastModifiedDate": "2026-10-02T17:52:23.687Z"
  }
}

Puedes combinar el filtro con los demás de GET /purchases: dateFrom/dateTo (fecha de pago), companyCode si tu key tiene varias compañías (ver Uso multi-compañía), comercio, presupuesto, etc. Recorre todas las páginas como se explica en Paginación.

2. Mantente sincronizado con los cambios de aprobación

El estado de una transacción cambia con el tiempo: una aprobada puede revertirse, y una pendiente puede aprobarse días después. Para enterarte sin volver a leer todo, filtra por la fecha del último cambio en el flujo con approvalWorkflowLastModifiedDateFrom:

curl -X GET 'https://{HOST}/api/public/v1/purchases?approvalWorkflowStatus=AUTHORIZED&approvalWorkflowLastModifiedDateFrom=2026-10-01T00:00:00Z&size=500&page=0' \
  -H 'X-API-KEY: tu_api_key_aqui'

Con este filtro:

  • El orden pasa a ser approvalWorkflow.lastModifiedDate ascendente y se ignora el sort que envíes.
  • No lo combines con lastModifiedDateFrom/lastModifiedDateTo: la API responde 400 con NOT_SUPPORTED.
  • Guarda el approvalWorkflow.lastModifiedDate más reciente que procesaste y úsalo como approvalWorkflowLastModifiedDateFrom en la próxima ejecución. Como el filtro es inclusive, vas a recibir otra vez la última transacción: deduplica por uniqueCode.

Para detectar las que dejaron de estar aprobadas

Si filtras por AUTHORIZED, no vas a ver las transacciones que pasaron de aprobadas a otro estado. Si necesitas saberlo, sincroniza sin approvalWorkflowStatus y actualiza el estado de cada transacción con el approvalWorkflow.status que trae.

La receta completa

// Node.js 18 o superior. Trae las transacciones aprobadas cuyo flujo cambió desde `since`.
const HOST = 'https://mx.stage.app.mendel.com';
const headers = { 'X-API-KEY': process.env.MENDEL_API_KEY, Accept: 'application/json' };

async function get(path) {
  const res = await fetch(`${HOST}/api/public/v1${path}`, { headers });
  if (!res.ok) throw new Error(`${res.status} en ${path}`);
  return res.json();
}

async function approvedSince(since, statuses = ['AUTHORIZED']) {
  const byCode = new Map();
  for (let page = 0, totalPages = 1; page < totalPages; page++) {
    const query = new URLSearchParams({
      approvalWorkflowLastModifiedDateFrom: since, page, size: 500,
    });
    for (const status of statuses) query.append('approvalWorkflowStatus', status);
    const body = await get(`/purchases?${query}`);
    for (const purchase of body._embedded?.purchases ?? []) {
      byCode.set(purchase.uniqueCode, purchase); // deduplica por uniqueCode
    }
    totalPages = body.page.totalPages;
  }
  const purchases = [...byCode.values()];
  // Próximo punto de partida: el último cambio de aprobación procesado.
  const checkpoint = purchases.reduce(
    (max, p) => (p.approvalWorkflow.lastModifiedDate > max ? p.approvalWorkflow.lastModifiedDate : max),
    since,
  );
  return { purchases, checkpoint };
}

const { purchases, checkpoint } = await approvedSince('2026-10-01T00:00:00Z');
console.log(`${purchases.length} transacciones aprobadas; próxima ejecución desde ${checkpoint}`);

Para traer otro estado, cambia statuses: por ejemplo ['UNAUTHORIZED'] para las rechazadas o ['SUBMITTED', 'PARTIAL_AUTHORIZED'] para las que esperan aprobación.

Problemas frecuentes

SíntomaCausa
400 en approvalWorkflowStatusEl valor no es uno de los estados de la tabla. Los valores van en inglés y en mayúsculas.
400 con NOT_SUPPORTEDCombinaste approvalWorkflowLastModifiedDateFrom con lastModifiedDateFrom o lastModifiedDateTo.
El orden no es el que pediste en sortCon approvalWorkflowLastModifiedDateFrom el orden es fijo: approvalWorkflow.lastModifiedDate ascendente.
Traes transacciones con pago autorizado que no están aprobadasFiltraste por summaryStatus, que es el estado del pago. Usa approvalWorkflowStatus.

En esta página