Skip to content

Transacciones recurrentes ​

Un cobro (o un pago) que se repite: una suscripción mensual, una renta, una iguala. Das de alta una transacción recurrente y Finova genera el movimiento de cada periodo por su cuenta.

No escribas tú el periodo de cada mes

Es el error que parece funcionar hasta que cuenta el dinero dos veces. El generador de Finova corre a diario, tiene recuperación de días perdidos y su idempotencia es un índice único en la base — no un if. Si necesitas enterarte de cada periodo, suscríbete a recurring.occurrence_created y anótalo; no lo registres tú.

Cómo funciona ​

  1. Creas la recurrencia con su calendario (frequency, interval, start_on…).
  2. Finova calcula next_run_at.
  3. Un proceso diario materializa cada periodo vencido:
    • kind: "income" → una venta (ingreso cobrado o cuenta por cobrar, según el esquema de pago).
    • kind: "expense" → una cuenta por pagar.
  4. Cada ocurrencia dispara recurring.occurrence_created.

Si el proceso no corrió un día, al siguiente se pone al día: genera cada periodo vencido con su propia fecha, no todos con la de hoy.

El objeto RecurringTransaction ​

json
{
  "id":           "65d1a1f1234567890abcdef0",
  "object":       "recurring_transaction",
  "kind":         "income",
  "amount_cents": 150000,
  "amount":       1500.0,
  "currency":     "mxn",
  "description":  "Suscripción Plan Pro",

  "customer_id":  "65a1b2c3d4e5f6789012abcd",
  "account_id":   "65b3a1f1234567890abcdef0",
  "account_name": "BBVA MXN",
  "category_id":  null,
  "product_id":   null,
  "employee_id":  null,
  "project_id":   null,
  "vendor_id":    null,
  "classification": null,

  "frequency":         "monthly",
  "interval":          1,
  "byweekday":         [],
  "bymonthday":        [1],
  "start_on":          "2026-01-01",
  "ends_on":           null,
  "ends_count":        null,
  "runs_count":        9,
  "last_run_on":       "2026-09-01T06:00:00Z",
  "next_run_at":       "2026-10-01T06:00:00Z",
  "timezone":          "America/Mexico_City",
  "run_at_local_time": "00:00",
  "active":            true,

  "metadata":   { "external_ref": "sub_abc123", "orderId": "ord_123" },
  "created_at": "2026-01-01T00:00:12Z",
  "updated_at": "2026-09-01T06:00:03Z"
}

El calendario ​

CampoTipoDescripción
frequencystringmonthly, weekly, month_end, semi_monthly, every_n_days, custom.
intervalintCada cuántas unidades de frequency. Por defecto 1.
byweekdayarrayDías de la semana (para weekly / custom).
bymonthdayarrayDías del mes (para monthly / custom).
start_ondatePrimer día en que puede generar. Requerido.
ends_ondateÚltimo día. null = indefinida.
ends_countintNúmero máximo de ocurrencias.
timezonestringZona horaria del calendario. Por defecto la de tu empresa.
run_at_local_timestringHora local del disparo, HH:MM. Por defecto 00:00.
activeboolfalse deja de generar. Es la forma de cancelar.

Los campos de sólo lectura runs_count, last_run_on y next_run_at te dicen en qué punto va. next_run_at en null significa que ya no quedan ocurrencias.


Listar recurrencias ​

GET/api/v1/recurring-transactionsread-recurring_transactions

Busca antes de crear

Si estás migrando una cartera, es muy probable que varias de tus recurrencias ya estén dadas de alta en Finova, capturadas a mano. Crear una segunda sobre el mismo cliente genera el mismo mes dos veces, y desde la contabilidad no hay forma de distinguir el duplicado del bueno.

Busca primero. Es la diferencia entre migrar de una vez y migrar rezando.

Filtros:

ParámetroEfecto
kindincome o expense.
activetrue / false.
customer_idLas de un cliente.
external_refLa que lleva tu referencia en metadata.external_ref.
bash
curl 'https://developers.fi-nova.com/api/v1/recurring-transactions?customer_id=65a1b2c3d4e5f6789012abcd&active=true' \
  -H 'Authorization: Bearer finova_sk_TU_SECRETO'

Paginado estándar — ver paginación.


Obtener una recurrencia ​

GET/api/v1/recurring-transactions/:idread-recurring_transactions

Incluye items (los conceptos que se copian a cada ocurrencia).


Crear una recurrencia ​

POST/api/v1/recurring-transactionscreate-recurring_transactions

Requeridos: account_id, amount_cents, currency, frequency, start_on. Para kind: "expense", también classification.

Opcionales: kind (por defecto income), customer_id, category_id, product_id, employee_id, project_id, vendor_id, description, interval, byweekday, bymonthday, ends_on, ends_count, timezone, run_at_local_time, active, items, metadata.

bash
curl -X POST https://developers.fi-nova.com/api/v1/recurring-transactions \
  -H 'Authorization: Bearer finova_sk_TU_SECRETO' \
  -H 'Content-Type: application/json' \
  -d '{
    "data": {
      "kind":         "income",
      "account_id":   "65b3a1f1234567890abcdef0",
      "customer_id":  "65a1b2c3d4e5f6789012abcd",
      "amount_cents": 150000,
      "currency":     "mxn",
      "description":  "Suscripción Plan Pro",
      "frequency":    "monthly",
      "interval":     1,
      "start_on":     "2026-10-01",
      "timezone":     "America/Mexico_City",
      "items": [
        { "name": "Plan Pro", "quantity": 1, "unit_price_cents": 150000 }
      ],
      "metadata": { "external_ref": "sub_abc123", "orderId": "ord_123" }
    }
  }'

Si la recurrencia nace activa y su primera fecha ya venció, se materializa en el acto — igual que desde la aplicación, para que dar de alta un cobro de hoy no tenga que esperar a mañana.

Idempotencia ​

Manda metadata.external_ref con tu propia referencia. Si repites el alta con la misma, Finova devuelve 200 con la recurrencia que ya existía en vez de crear una segunda. Ver idempotencia.


Actualizar una recurrencia ​

PUT/api/v1/recurring-transactions/:idupdate-recurring_transactions

Mismos campos. Cualquier cambio en el calendario recalcula next_run_at.

Para cancelar una suscripción, manda active: false.

bash
curl -X PUT https://developers.fi-nova.com/api/v1/recurring-transactions/65d1... \
  -H 'Authorization: Bearer finova_sk_TU_SECRETO' \
  -H 'Content-Type: application/json' \
  -d '{ "data": { "active": false } }'

Emite recurring.deactivated.


No hay DELETE ​

Y es a propósito. Una recurrencia con meses ya generados tiene ingresos, cuentas por cobrar y facturas apuntando a ella; borrarla los dejaría huérfanos, señalando a un id que no resuelve. Para dejar de cobrar está active: false, que es lo que de verdad significa cancelar: deja el histórico en pie.

Hecho con cuidado por Finova.