API M2Mv1.0.0
Bienvenido a la API Machine-to-Machine (M2M) oficial de Proyexa. Esta suite de integración ha sido diseñada meticulosamente bajo los más altos estándares de seguridad y escalabilidad para habilitar la comunicación programática directa entre instituciones financieras, pasarelas de pago o sistemas de terceros y el núcleo del ecosistema ERP de Proyexa.
A través de esta API, los integradores autorizados pueden consultar información financiera en tiempo real, validar saldos pendientes, aplicar pagos de manera automatizada y afectar la contabilidad de la empresa destino sin fricciones. Toda transacción realizada por esta vía genera trazas de auditoría completas, asegurando una conciliación bancaria transparente y en tiempo real.
Información Técnica
Todas las peticiones M2M deben realizarse desde el backend de tu integración apuntando al subdominio específico de tu cliente en Proyexa.
Entornos Disponibles
Descargar Colección Postman| Entorno | URL Base |
|---|---|
Sandbox (Pruebas) Datos ficticios, ideal para desarrollo. | https://sandbox.proyexa.app |
Producción Transacciones y contabilidad real. | https://{tenant-del-cliente}.proyexa.app |
Límites de Petición (Rate Limiting)
Para proteger la estabilidad del ecosistema ERP, la API M2M procesa un máximo de 60 peticiones por minuto por IP. Si superas este límite, recibirás un error HTTP 429 Too Many Requests. Asegúrate de cachear tu token de acceso y de no bombardear la API con retries indiscriminados.
Estructura y Modelos
Información Técnica
Nuestra API Rest sigue un estándar estrictamente definido. Incluye distintos modelos, respuestas, entidades y excepciones, estructurados de manera que brinden una experiencia sin fricción para los desarrolladores de integraciones M2M.
Modelos
Los modelos dentro del API Rest brindan estructuras predefinidas (JSON) para facilitar la interacción con entidades de Proyexa, como ser facturación, clientes, impuestos, etc.
Es muy importante conocer todas las utilidades de estos modelos para poder explotar su potencial al máximo. Dentro de los modelos podemos encontrar:
Invoice: datos de facturación e historial de cobrosCustomer: datos del cliente asociado a la facturaCurrency: datos de monedas y tipos de cambioInvoiceItem: todo tipo de artículos a la venta facturadosReceipt: datos de recibos y comprobantes de pago
Invoice Object
| Propiedad | Tipo | Descripción |
|---|---|---|
| id | string (ULID) | Identificador único de la factura. |
| number | string | Número fiscal (CAI) o correlativo de la factura. |
| payment_code | string | null | Código de pago rápido asociado. |
| date | string (datetime) | Fecha de emisión de la factura (ISO 8601). |
| due_date | string (date) | null | Fecha de vencimiento para pago. |
| subtotal | string (decimal) | Monto antes de impuestos y descuentos (2 decimales). |
| discount | string (decimal) | Monto total de descuentos (2 decimales). |
| tax_amount | string (decimal) | Monto total de impuestos (2 decimales). |
| total | string (decimal) | Monto total original (2 decimales). |
| balance | string (decimal) | Saldo pendiente actual (varía según pagos aplicados) (2 decimales). |
| status | string | Estado actual. active, partially_paid, paid. |
| customer | object (Customer) | Información básica del cliente. |
| currency | object | Moneda aplicada. (Solo retorna: code, symbol y exchange_rate). |
| items | array (InvoiceItem) | null | Lista de productos o servicios (Sólo en Detalle). |
Customer Object
| Propiedad | Tipo | Descripción |
|---|---|---|
| name | string | null | Razón social o nombre completo del cliente. |
| rtn | string | null | Registro Tributario Nacional (DNI / NIT) del cliente. |
Currency Object
| Propiedad | Tipo | Descripción |
|---|---|---|
| id | string (ULID) | ID interno de la moneda. |
| code | string | Código ISO de la moneda (ej. HNL, USD). |
| name | string | Nombre comercial (ej. Lempiras). |
| symbol | string | Símbolo (ej. $, L). |
| purchase_rate | string (decimal) | Tasa de compra oficial del ERP (4 decimales). |
| sale_rate | string (decimal) | Tasa de venta oficial del ERP (4 decimales). |
| is_default | boolean | Verdadero si es la moneda base del tenant. |
InvoiceItem Object
| Propiedad | Tipo | Descripción |
|---|---|---|
| description | string | Nombre o detalle del producto/servicio. |
| quantity | number | Cantidad facturada. |
| price | string (decimal) | Precio unitario base (2 decimales). |
| subtotal | string (decimal) | Total de la línea sin impuestos (2 decimales). |
| discount_amount | string (decimal) | Descuento aplicado en la línea (2 decimales). |
| tax_rate | string (decimal) | Porcentaje de impuesto. |
| tax_amount | string (decimal) | Impuesto por la línea (2 decimales). |
| total | string (decimal) | Total de la línea con impuestos y descuentos (2 decimales). |
Receipt Object (Recibo de Pago)
| Propiedad | Tipo | Descripción |
|---|---|---|
| id | string (ULID) | Identificador único del recibo generado. |
| number | string | Correlativo interno del recibo (ej. REC-000001). |
| date | string (datetime) | Fecha de generación. |
| amount | string (decimal) | Monto total abonado (2 decimales). |
| reference | string | Referencia bancaria proporcionada. |
| notes | string | Nota autogenerada con el rastro del pago bancario (útil para auditoría). |
| status | string | Estado del recibo. |
| invoice | object | Estado actualizado de la factura (id, number, balance, status). |
Manejo de Errores
Todas las respuestas de error de la API (a excepción del endpoint de OAuth) devuelven una estructura de datos estandarizada. No es necesario adivinar el formato de error para cada petición individual; puedes programar tu interceptor de manera centralizada.
Estructura Estándar (4xx / 5xx)
Siempre devolverá "error".
Descripción humana del error (ej. "No tienes permisos").
Si es un error HTTP 422, contendrá las validaciones por campo.
{
"status": "error",
"message": "No autenticado. Token inválido o ausente.",
"data": null,
"pagination": null,
"errors": null
}Autenticación
/oauth/tokenProyexa utiliza el estándar OAuth 2.0 (Client Credentials Grant). Obtén un token temporal para firmar tus peticiones.
Duración y Patrón de Integración
Por motivos de seguridad, los tokens de acceso M2M tienen un tiempo de vida estricto de 60 minutos (1 hora). Es una mala práctica (y puede generar bloqueos por límite de peticiones) solicitar un token nuevo antes de cada operación individual.
💡 Patrón Recomendado:
- Solicita el token y almacénalo temporalmente en la memoria o caché de tu sistema.
- Reutiliza el mismo token para todas tus operaciones continuas.
- Configura un interceptor HTTP en tu cliente para que, si recibe un error
401 Unauthorized, solicite silenciosamente un nuevo token y reintente la petición original.
Body (JSON)
Fijo: client_credentials
UUID de tu credencial M2M.
Llave secreta generada en Proyexa.
curl -X POST https://{tenant}.proyexa.app/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials",
"client_id": "99b0c...",
"client_secret": "kYxP9..."
}'{
"token_type": "Bearer",
"expires_in": 31536000,
"access_token": "eyJ0eXAiOiJKV1QiLC..."
}Monedas y Tasas
/m2m/billing/currenciesConsulta las monedas configuradas en el tenant y su tasa de conversión oficial. Indispensable para procesar pagos en dólares u otras denominaciones soportadas.
Headers
Bearer {access_token}
curl -X GET https://{tenant}.proyexa.app/m2m/billing/currencies \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"{
"status": "success",
"message": "Monedas obtenidas exitosamente.",
"data": [
{
"id": "019...",
"code": "HNL",
"name": "Lempiras",
"symbol": "L",
"purchase_rate": "1.0000",
"sale_rate": "1.0000",
"is_default": true
},
{
"id": "019...",
"code": "USD",
"name": "Dólares",
"symbol": "$",
"purchase_rate": "24.5000",
"sale_rate": "24.8000",
"is_default": false
}
],
"pagination": null,
"errors": null
}Listar Facturas
/m2m/billing/invoicesDevuelve la lista paginada de todas las facturas pendientes de pago (estado active o partially_paid). Puedes buscar por ID de cliente o RTN.
Query Parameters
Filtro por ID interno del cliente.
Búsqueda exacta por RTN/DNI del cliente.
Número de página a consultar (Defecto: 1).
Resultados por página (Defecto: 15).
Manejo de Paginación
Este endpoint puede devolver un gran volumen de datos, por lo que su respuesta está dividida en páginas. En el cuerpo JSON de la respuesta encontrarás el objeto pagination. Para obtener el siguiente bloque de registros, simplemente haz una nueva petición agregando el parámetro ?page=2 (o el número correspondiente) a la URL, guiándote por la propiedad has_more_pages.
curl -X GET "https://{tenant}.proyexa.app/m2m/billing/invoices?customer_id=01H9&per_page=15" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"{
"status": "success",
"message": "Facturas pendientes obtenidas exitosamente.",
"data": [
{
"id": "01J2X...",
"number": "000-001-01-00000042",
"payment_code": "42",
"date": "2026-06-30T10:00:00.000000Z",
"due_date": "2026-07-30T06:00:00.000000Z",
"subtotal": "1304.35",
"discount": "0.00",
"tax_amount": "195.65",
"total": "1500.00",
"balance": "1500.00",
"status": "active",
"customer": {
"name": "Empresa S.A.",
"rtn": "0801199012345"
},
"currency": {
"code": "HNL",
"symbol": "L",
"exchange_rate": "1.0000"
}
}
],
"pagination": {
"current_page": 1,
"last_page": 1,
"per_page": 15,
"total": 1,
"has_more_pages": false
},
"errors": null
}Detalle de Factura
/m2m/billing/invoices/{id_o_codigo}Validación Crítica
Siempre consulta este endpoint justo antes de procesar un abono monetario para verificar el saldo actualizado. Las facturas pueden haber recibido abonos desde otros canales.
Path Parameters
Soporta los siguientes formatos:
- UUID (ID interno de la base de datos)
- Número de Factura (
000-001-01-00000601) - Correlativo (
601) - Payment Code (Código de pago) (
42)
curl -X GET "https://{tenant}.proyexa.app/m2m/billing/invoices/000-001-01-00000042" \
-H "Authorization: Bearer {token}" \
-H "Accept: application/json"{
"status": "success",
"message": "Detalle de factura obtenido exitosamente.",
"data": {
"id": "01J2X...",
"number": "000-001-01-00000042",
"payment_code": "42",
"date": "2026-06-30T10:00:00.000000Z",
"due_date": "2026-07-30T06:00:00.000000Z",
"subtotal": "1304.35",
"discount": "0.00",
"tax_amount": "195.65",
"total": "1500.00",
"balance": "1500.00",
"status": "active",
"customer": {
"name": "Empresa S.A.",
"rtn": "0801199012345"
},
"currency": {
"code": "HNL",
"symbol": "L",
"exchange_rate": "1.0000"
},
"items": [
{
"description": "Servicio de Consultoría",
"quantity": 1.0000,
"price": "1304.35",
"subtotal": "1304.35",
"discount_amount": "0.00",
"tax_rate": "15.00",
"tax_amount": "195.65",
"total": "1500.00"
}
]
},
"pagination": null,
"errors": null
}Registrar Pago
/m2m/billing/invoices/{id_o_codigo}/paymentsAplica un abono monetario a la factura. Proyexa validará los alcances configurados en el ERP para determinar si tienes permitido registrar pagos parciales y generará el recibo contable automáticamente.
Body (JSON)
Monto depositado. Será rechazado si es superior al saldo pendiente.
Número de comprobante bancario único.
Código ISO (ej. USD). Si se envía una moneda foránea, el sistema hará la conversión automática usando la tasa oficial.
Idempotencia y Prevención de Pagos Dobles
Este endpoint está diseñado para ser seguro ante fallas de red. Utilizamos el parámetro reference_number como clave de idempotencia (Idempotency Key). Si tu sistema pierde conexión y reintenta aplicar un pago usando el mismo número de referencia bancaria, Proyexa detectará el duplicado, protegerá el saldo de la factura y devolverá un error 422 Unprocessable Entity.
curl -X POST "https://{tenant}.proyexa.app/m2m/billing/invoices/000-001-01-00000042/payments" \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"amount": 1500.00,
"reference_number": "TRX-88",
"currency_code": "HNL"
}'{
"status": "success",
"message": "Pago aplicado exitosamente.",
"data": {
"id": "01J2Z...",
"number": "REC-000001",
"date": "2026-07-01T10:00:00.000000Z",
"amount": "1500.00",
"reference": "M2M-TRX-88",
"notes": "M2M: Pago vía [Integración Banco] Transacción: TRX-88 (1500.00 HNL)",
"status": "active",
"invoice": {
"id": "01J2X...",
"number": "000-001-01-00000042",
"balance": "0.00",
"status": "paid"
}
},
"pagination": null,
"errors": null
}