Venflow API

Cambiar el estado de una factura

Cambiar el estado de una factura

Cuando un cliente paga por un medio externo a Venflow (efectivo, transferencia o taquilla), la factura permanece abierta y Venflow continúa intentando cobrarla. Estos endpoints te permiten actualizar su estado desde tu sistema, sin usar el dashboard: registrar el pago, darla por incobrable, anularla o reabrir el cobro de una factura en revisión.

AcciónEndpointQué hace
Marcar como pagadaPOST /v1/invoices/:id/mark_paidDeja constancia del pago y cierra la factura. No cobra nada
Marcar como incobrablePOST /v1/invoices/:id/mark_uncollectibleVenflow deja de intentar cobrarla. No cancela la suscripción
AnularPOST /v1/invoices/:id/mark_voidDeja la factura sin efecto: no se cobra ni cuenta como deuda. No cancela la suscripción
Reabrir el cobroPOST /v1/invoices/:id/mark_openDevuelve a la cola de cobro una factura en revisión con el banco

Las cuatro devuelven la factura actualizada, con la misma forma que GET /v1/invoices/:id.

Anular y reabrir el cobro requieren especial cuidado, ya que en algunos casos pueden dar lugar a un cobro duplicado. Por eso ambas acciones exigen un motivo (reason), y anular una factura en revisión requiere además una confirmación explícita. Te recomendamos revisar sus secciones antes de usarlas.

Requisito: la función debe estar habilitada

Estas acciones se habilitan por organización. Mientras estén deshabilitadas para la tuya, los cuatro endpoints responden 404 con el código not_found, igual que una ruta que no existe. Si recibes ese 404 con una factura que sí existe, pide que habiliten la función para tu organización. Como en el resto de la API, decide por el code de la respuesta, nunca por el message.

Una factura open puede estar esperando respuesta del banco

Una factura queda en revisión cuando el banco no ha confirmado si un cobro se realizó. En la API conserva el estado open y se identifica con el campo under_review: true. Para el resto de las facturas, este campo es false.

Mientras una factura está en revisión, Venflow no realiza nuevos intentos de cobro. El filtro GET /v1/invoices?status=open incluye estas facturas; usa el campo under_review para distinguirlas.

Te recomendamos consultar under_review antes de aplicar cualquier acción: en una factura en revisión, es posible que el débito ya se haya realizado, y cada acción tiene consecuencias distintas.

Qué acción se puede aplicar en cada estado

Estado actualmark_paidmark_uncollectiblemark_voidmark_open
openSí → paidSí → uncollectibleSí → voidNo
open con under_review: trueSí → paid ⚠️Sí → uncollectible ⚠️Sí → void 🔴, solo con confirm_under_review: trueSí → open 🔴
uncollectibleSí → paidNoNoNo
paidNoNoNoNo
voidNoNoNoNo
draftNoNoNoNo

Los íconos ⚠️ y 🔴 indican acciones con riesgo de cobro duplicado; el detalle está en la sección de cada una.

Si la acción no es válida para el estado actual de la factura, la llamada responde 400 con el código failed_precondition. Esto incluye marcar como incobrable una factura que ya lo es, reabrir una factura open que no está en revisión y anular una factura en revisión sin confirm_under_review: true. Repetir la llamada no cambia el resultado; consulta la factura antes de decidir cómo continuar.

Una respuesta 409 con el código aborted significa que esa llamada no aplicó la acción. Pasa por uno de dos motivos: el estado de la factura cambió justo mientras la aplicabas (por ejemplo, porque en ese momento entró el cobro automático), u otra llamada con la misma Idempotency-Key todavía está en curso. Como el código es el mismo, haz lo mismo en los dos casos: consulta la factura y, si la acción todavía hace falta, reintenta con la misma Idempotency-Key. Con la misma clave, la acción nunca se aplica dos veces.

Si una llamada se cortó y no sabes si se aplicó, reintenta también con la misma Idempotency-Key, no con una nueva: la acción no se aplica otra vez y recibes la factura como está en ese momento.

Marcar una factura como pagada

curl -X POST "https://api.venflow.app/v1/invoices/<invoice_id>/mark_paid" \
  -H "Api-Key: pvk_live_abc123..." \
  -H "Organization: org_xyz789..." \
  -H "Idempotency-Key: pago-factura-1043-intento-1" \
  -H "Content-Type: application/json" \
  -d '{
    "reference": "000123456789",
    "reason": "Pagó en efectivo en la taquilla"
  }'
CampoTipoNotas
referencestring (1-500)Requerido. La referencia del pago tal como aparece en el estado de cuenta. Queda guardada en la transacción y en el historial de la factura, y es la que tu equipo puede buscar después
reasonstring (máx. 500)Opcional. Una nota que queda en el historial de la factura

⚠️ Es posible marcar como pagada una factura en revisión, pero ten en cuenta que el cobro automático podría haberse debitado. Si el banco lo confirma después, el pago quedaría registrado dos veces. Te recomendamos confirmar con tu cliente el medio de pago antes de hacerlo.

Marcar una factura como incobrable

curl -X POST "https://api.venflow.app/v1/invoices/<invoice_id>/mark_uncollectible" \
  -H "Api-Key: pvk_live_abc123..." \
  -H "Organization: org_xyz789..." \
  -H "Idempotency-Key: incobrable-factura-1043" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "El cliente cerró su cuenta bancaria" }'
CampoTipoNotas
reasonstring (máx. 500)Opcional. Por qué se da la factura por perdida; queda en su historial

⚠️ Si la factura está en revisión (under_review: true), marcarla como incobrable no anula el cobro pendiente: el banco aún no ha informado si se procesó. Si la suscripción usa cobros por API, además se procesan los cobros que estaban en espera. Te recomendamos verificar el estado del cobro con el banco antes de hacerlo.

Marcar una factura como incobrable no cancela la suscripción; para cancelarla, usa el API de suscripciones. Este endpoint no acepta un campo de cancelación: si envías cancel_subscription, el campo se ignora, la factura se marca como incobrable y la suscripción sigue activa.

Anular una factura

curl -X POST "https://api.venflow.app/v1/invoices/<invoice_id>/mark_void" \
  -H "Api-Key: pvk_live_abc123..." \
  -H "Organization: org_xyz789..." \
  -H "Idempotency-Key: anular-factura-1043" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "La cuota se canceló en la taquilla" }'
CampoTipoNotas
reasonstring (1-500)Requerido. Por qué se anula la factura; queda en su historial
confirm_under_reviewbooleanSolo para una factura en revisión (under_review: true), y ahí es obligatorio en true. En cualquier otra factura no hace falta

Al anular una factura, esta queda sin efecto: Venflow no intentará cobrarla y dejará de considerarla una deuda del cliente. La suscripción no se cancela.

Anular una factura en revisión no cancela el cobro pendiente. El banco aún no ha confirmado si ese débito se realizó; si lo confirma después, el pago quedará asociado a una factura anulada. Por eso, sobre una factura con under_review: true, la llamada responde 400 (failed_precondition) y no aplica cambios, a menos que envíes "confirm_under_review": true. Te recomendamos confirmarlo solo después de verificar con tu cliente o con tu banco que el cobro no se realizó.

Reabrir el cobro de una factura en revisión

curl -X POST "https://api.venflow.app/v1/invoices/<invoice_id>/mark_open" \
  -H "Api-Key: pvk_live_abc123..." \
  -H "Organization: org_xyz789..." \
  -H "Idempotency-Key: reabrir-factura-1043" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "El banco confirmó que el débito no se hizo" }'
CampoTipoNotas
reasonstring (1-500)Requerido. Por qué reabres el cobro, por ejemplo cómo confirmaste que el cobro anterior no se hizo; queda en el historial de la factura

Esta acción solo aplica a facturas en revisión (under_review: true). La factura vuelve al estado open, deja de estar en revisión y Venflow la incluye en su próximo ciclo de cobro.

Mientras el cobro anterior no esté confirmado, Venflow no realiza un segundo débito sobre la misma factura: primero consulta nuevamente ese cobro con el banco. Si el banco lo confirma, la factura se marca como pagada; si aún no hay respuesta, vuelve a quedar en revisión; y si el banco lo rechaza, la factura permanece open y Venflow podrá intentar cobrarla de nuevo.

Excepción: si la factura corresponde a un cobro por API sin reintentos automáticos (retry_policy: "none"), Venflow no realiza nuevos intentos ni consulta el cobro pendiente. La factura queda en estado open y su seguimiento queda a cargo de tu equipo.

Reabre el cobro únicamente si confirmaste que el débito anterior no se realizó. Para registrar un pago recibido por otro medio, usa mark_paid.

Qué webhook recibes

Al anular o reabrir el cobro de una factura se envía el evento INVOICE_UPDATE_EVENT, tanto si la acción se realiza por API como desde el dashboard:

Accióninvoice.status en el webhook
Anular (mark_void)cancelled: así llaman los webhooks a una factura anulada (void en la API)
Reabrir el cobro (mark_open)open

Reglas del texto

reference y reason se validan igual en los cuatro endpoints. Todas devuelven 400 (invalid_argument):

  • Máximo 500 caracteres, contando los espacios entre palabras. Los espacios al inicio y al final se quitan antes de contar y de guardar el texto.
  • No pueden contener una clave API. Si el texto incluye algo que parece una (pvk_, pvtk_ y similares), se rechaza, y el mensaje de error no repite el texto que mandaste.
  • En mark_void y mark_open, reason es obligatorio: vacío o solo con espacios también responde 400.

Los campos que no figuran en la tabla del endpoint se ignoran: no generan un error ni tienen efecto. Revisa el nombre de cada campo, ya que uno mal escrito se considera ausente. Por ejemplo, si envías razon en lugar de reason, la acción se aplica sin motivo o, si el motivo es obligatorio, se rechaza con 400. Del mismo modo, un confirm_under_review mal escrito hace que la anulación de una factura en revisión sea rechazada.

Idempotency-Key: reintentar sin aplicar la acción dos veces

Las cuatro acciones exigen el header Idempotency-Key. Sin él, la respuesta es un 400.

Si tu llamada se corta por la red o por un timeout, no sabes si la acción se aplicó. Reintenta con la misma clave: Venflow no vuelve a aplicar la acción y te devuelve la factura como está en ese momento.

SituaciónResultado
Misma clave, misma factura, misma acción y mismos datosLa acción no se repite. Se devuelve la factura como está ahora
Misma clave con otro reference, reason o confirm_under_review400, con un mensaje que nombra el campo distinto
Misma clave con otra factura u otra acción400
Misma clave mientras la primera llamada sigue en curso409. Espera unos segundos, consulta la factura y, si la acción todavía hace falta, reintenta con la misma clave
La primera llamada falló (por ejemplo, un 400 por el estado)La clave queda libre: puedes reintentar con ella
La primera llamada respondió 500Consulta la factura antes de reintentar: el error pudo ocurrir después de aplicar la acción

Cómo elegir la clave:

  • Una clave por cada operación real, no por cada intento. Si registras dos pagos distintos, usa dos claves distintas.
  • La clave es única dentro de tu organización y puede tener hasta 255 caracteres. Un identificador de tu sistema (el id del pago en tu caja, por ejemplo) o un UUID funcionan bien.
  • El mensaje de error nunca muestra los datos guardados con la clave: solo dice qué campo no coincide.

Permisos de la clave API

Cualquier clave API de tu organización puede usar los cuatro endpoints. No hace falta darle ningún permiso aparte.