Medios de pago

Conectar tu sistema de facturación con la tienda (API)

Que tu propio sistema de facturación use los productos, el stock y los clientes de tu tienda, y que las ventas que factura bajen el stock y queden como pedidos cobrados. Vos elegís qué puede hacer. Incluye la guía para tu programador.

Si facturás con tu propio sistema, podés conectarlo con tu tienda para que use tus productos, tu stock y tus clientes, y para que las ventas que factura bajen el stock y aparezcan como pedidos cobrados en tu panel.

Cómo se activa

Entrá a Facturación → Configuración

En tu panel: Facturación → Configuración, elegí «Otro sistema de facturación» y bajá hasta «2 · Que tu sistema use la tienda». Ahí mismo está, arriba, la conexión para facturar desde la tienda con tu sistema: todo lo de tu sistema de facturación vive en esa pantalla.

Elegí qué puede hacer tu sistema

Marcá las casillas. Sólo lectura son las tres primeras (productos, stock y clientes). Para que las ventas bajen el stock, marcá también «Registrar las ventas». Lo podés cambiar cuando quieras, sin cambiar la llave.

Creá la llave y pasásela a tu programador

Tocá Crear la llave. Se muestra una sola vez: copiala y pasásela a quien programa tu sistema, junto con la dirección que aparece en la misma pantalla y el link de esta página.

Cuidá la llave

Con la llave, tu sistema puede hacer lo que marcaste. Si se pierde o la vio quien no debía, creá una nueva desde la misma pantalla: la anterior deja de funcionar al instante. Desconectar la corta del todo.

Guía técnica (para tu programador)

Escribila (ej. https://mitienda.com.py o https://mitienda.maxtiendas.app) y todas las URLs de esta guía quedan listas para copiar.

Todas las rutas de esta página quedan así: https://tutienda.maxtiendas.app/api/v2/admin/external-billing

1. Antes de empezar

El administrador de la tienda entra a su panel → Facturación → Configuración, elige «Otro sistema de facturación» y, en «2 · Que tu sistema use la tienda», marca qué puede hacer tu sistema y genera la llave él mismo. Te pasa dos cosas:

DatoEjemplo
Dirección basehttps://mitienda.maxtiendas.app/api/v2/admin/external-billing
Llave57|kH3n... (se muestra una sola vez)

Cada llamada lleva tres cabeceras:

Authorization: Bearer <llave>
Accept: application/json
Content-Type: application/json

Permisos de la llave

El comerciante elige qué habilita. Si llamás a algo que no habilitó, la respuesta es 403 con "permiso": "<cual>" en el cuerpo.

PermisoRutas
productosGET /products
stockGET /stock
clientesGET /customers
ventasPOST /sales, /sales/{id}/status, /sales/{id}/cancel
notasnotas de crédito y de débito
remisionesnotas de remisión
cobroscobros de ventas a crédito

GET /me y DELETE /token funcionan con cualquier llave.

Respuestas y errores

CódigoQué significa
200 / 201Bien. 201 = se creó algo nuevo; 200 en un alta = ya existía (ver reintentos).
401Falta la llave o no es válida (la borraron o crearon otra).
403La llave no tiene ese permiso, o la ruta no es de esta integración.
404La tienda no tiene ese documento.
422Datos inválidos. El cuerpo trae message y errors por campo.
429Más de 120 llamadas por minuto. Esperá y reintentá.

2. Identificar la tienda

GET https://tutienda.maxtiendas.app/api/v2/admin/external-billing/me
{
  "data": {
    "tienda": "Mi Tienda",
    "url": "https://mitienda.maxtiendas.app",
    "stock": true,
    "moneda": "PYG",
    "iva": 10,
    "usuario": "Juan Pérez"
  }
}
  • stock: false → la tienda no lleva inventario: no hace falta consultar stock.
  • moneda → todas las ventas tienen que venir en esta moneda.
  • iva → la tasa general de la tienda (10, 5 o 0).

3. Productos

GET https://tutienda.maxtiendas.app/api/v2/admin/external-billing/products

Dos formas:

  • Buscar (para el buscador al facturar): GET /products?q=sofa → hasta 50 resultados, por nombre o código.
  • Traer todo (para sincronizar tu base): sin q, paginado.
    • page (desde 1), per_page (máximo 200, por defecto 100)
    • updated_since=2026-10-01T00:00:00 → sólo lo modificado desde esa fecha
{
  "data": [
    {
      "product_id": 1,
      "attribute_id": null,
      "codigo": "16707",
      "descripcion": "Sofa Molufan Dallas 3 y 2 Lugares",
      "nombre": "Sofa Molufan Dallas 3 y 2 Lugares",
      "variacion": null,
      "precio": 3500000,
      "iva": 10,
      "stock": { "controla": true, "disponible": 400 }
    },
    {
      "product_id": 15,
      "attribute_id": 88,
      "codigo": "REM-AZ-M",
      "descripcion": "Remera básica - Color : Azul, Talle : M",
      "nombre": "Remera básica",
      "variacion": "Color : Azul, Talle : M",
      "precio": 120000,
      "iva": 10,
      "stock": { "controla": true, "disponible": 7 }
    }
  ],
  "meta": { "page": 1, "per_page": 100, "total": 2532, "last_page": 26 }
}
  • Cada variación (talle, color) es su propia fila, con su attribute_id. Se factura y se descuenta la variación, no el producto general.
  • precio es el precio de venta con IVA incluido (la oferta, si tiene).
  • Guardá product_id y attribute_id: con eso la venta baja el stock de lo correcto.
  • meta sólo viene al traer todo, no en la búsqueda.

4. Stock

GET https://tutienda.maxtiendas.app/api/v2/admin/external-billing/stock?items=1:0,15:88

Lo disponible justo antes de emitir (entre la búsqueda y la emisión pudo venderse algo en la web). items = pares product_id:attribute_id separados por coma (0 si no tiene variación), hasta 200.

{
  "data": [
    { "product_id": 1,  "attribute_id": null, "existe": true, "stock": { "controla": true, "disponible": 400 } },
    { "product_id": 15, "attribute_id": 88,   "existe": true, "stock": { "controla": true, "disponible": 7 } }
  ]
}

5. Clientes

GET https://tutienda.maxtiendas.app/api/v2/admin/external-billing/customers

Igual que productos: ?q= busca (nombre, apellido, correo, CI o RUC; hasta 50) y sin q trae todos paginados con updated_since.

{
  "data": [
    {
      "customer_id": 4,
      "codigo_cliente": "MT-4",
      "nombre": "Ana González",
      "ruc": null,
      "naturaleza": 2,
      "tipo_documento": 1,
      "numero_documento": "4760362",
      "direccion": "Av. Mcal. López 1234",
      "email": "ana@ejemplo.com",
      "telefono": "0981234567"
    }
  ],
  "meta": { "page": 1, "per_page": 100, "total": 12, "last_page": 1 }
}
  • naturaleza: 1 = contribuyente (tiene RUC), 2 = no contribuyente.
  • tipo_documento (sin RUC): 1 = cédula, 5 = innominado.
  • Mandá codigo_cliente en la venta: así el pedido queda a nombre de ese cliente en la tienda.

6. Registrar una venta

POST https://tutienda.maxtiendas.app/api/v2/admin/external-billing/sales

Cuando tu sistema emite una factura con productos de la tienda, mandala acá. La tienda crea un pedido cobrado y facturado y baja el stock.

{
  "documento_id": 5001,
  "numero": "001-001-0000123",
  "cdc": "01800123456001001000012312026100112345678901",
  "estado": "APPROVED",
  "fecha": "2026-10-01T10:30:00",
  "moneda": "PYG",
  "total": 300000,
  "condicion": 1,
  "pagos": [ { "tipo_pago": 1, "monto": 300000 } ],
  "receptor": {
    "nombre": "Ana González",
    "numero_documento": "4760362",
    "email": "ana@ejemplo.com",
    "telefono": "0981234567",
    "codigo_cliente": "MT-4"
  },
  "items": [
    {
      "product_id": 1,
      "product_attribute_id": null,
      "codigo": "16707",
      "descripcion": "Sofa Molufan Dallas",
      "cantidad": 2,
      "precio_unitario": 150000,
      "descuento": 0
    }
  ]
}

Respuesta 201:

{ "message": "Venta registrada.", "data": { "order_id": 111, "reference": "SBK580321276", "existed": false } }
CampoObligatorioQué es
documento_idsíEl identificador interno y único del documento en TU sistema (entero > 0). Es la clave de todo lo demás: reintentos, anulación, notas, cobros.
totalsíTotal de la factura.
itemssíLas líneas (1 a 999).
items.*.descripcionsí
items.*.cantidadsíMayor a 0.
items.*.precio_unitariosíCon IVA incluido. Manda el de la factura, aunque difiera del catálogo.
items.*.product_id / product_attribute_idnoLos de la tienda. Sin product_id la línea no mueve stock (sirve para servicios, fletes, cosas que no están en la tienda).
numero, cdc, estado, fechanoLos datos de la factura electrónica.
monedanoPor defecto PYG. Tiene que ser la de la tienda (GET /me), si no → 422.
condicionno1 = contado, 2 = crédito.
pagos[]noCómo se cobró (contado). tipo_pago según SIFEN: 1 efectivo · 3 tarjeta de crédito · 4 tarjeta de débito · 5 transferencia · 7 billetera · 16 pago bancario · 17 pago móvil · 21 pago electrónico.
creditonoSi es a crédito: condicion (1 plazo, 2 cuotas), plazo, cuotas, entrega_inicial, detalle_cuotas[] { monto, vencimiento }. La tienda arma el plan de cuotas.
receptornoA quién se facturó. Con codigo_cliente (MT-<id>) se engancha al cliente de la tienda.

Reintentos (importante)

Si no recibís respuesta, reintentá con el mismo documento_id. Si la venta ya estaba registrada, la respuesta es 200 con "existed": true y el mismo pedido. Nunca se duplica.

Si el comercio también factura desde la tienda con tu sistema

Las dos conexiones se pueden usar juntas. Las facturas que la tienda te pidió emitir (POST /sifen/de, en la guía Facturar con tu facturadora) ya están en la tienda con su pedido: no hace falta mandarlas de vuelta. Si tu sistema manda todas sus ventas sin distinguir, tampoco pasa nada, con una condición: el documento_id tiene que ser el mismo id que le devolviste a la tienda al emitirla. Con eso la respuesta es "existed": true y el pedido de la tienda; no se crea otro ni se descuenta el stock dos veces. Vale igual para las notas de crédito, débito y remisión.


7. Después de emitir

Todas usan el documento_id de la venta en la dirección.

Estado ante la SET

POST https://tutienda.maxtiendas.app/api/v2/admin/external-billing/sales/{documento_id}/status
{ "estado": "APPROVED", "cdc": "0180…", "numero": "001-001-0000123" }

Sólo registra el estado. Si la SET la rechazó, anulala con la ruta de abajo para que vuelva el stock.

Anular la venta

POST https://tutienda.maxtiendas.app/api/v2/admin/external-billing/sales/{documento_id}/cancel

Sin cuerpo. El pedido pasa a Cancelado y la mercadería vuelve al stock.


8. Notas de crédito y de débito (permiso notas)

Nota de crédito

POST https://tutienda.maxtiendas.app/api/v2/admin/external-billing/sales/{documento_id}/credit-notes
{
  "documento_id": 7001,
  "numero": "001-001-0000045",
  "total": 150000,
  "motivo": 2,
  "items": [ { "product_id": 1, "product_attribute_id": null, "cantidad": 1 } ]
}
  • documento_id es el de la nota (único en tu sistema); el de la URL es el de la factura.
  • motivo (SIFEN): 1 devolución y ajuste de precios · 2 devolución · 3 descuento · 4 bonificación · 5 crédito incobrable.
  • Con devolución (motivo 1 o 2) e items, esa mercadería vuelve al stock.
  • Anular la nota: POST /credit-notes/{documento_id_de_la_nota}/cancel.

Nota de débito

POST https://tutienda.maxtiendas.app/api/v2/admin/external-billing/sales/{documento_id}/debit-notes
{ "documento_id": 7002, "numero": "001-001-0000046", "total": 50000, "motivo": 1 }

Sube lo que se debe del pedido.


Nota de remisión (permiso remisiones)

POST https://tutienda.maxtiendas.app/api/v2/admin/external-billing/sales/{documento_id}/remissions

La nota de remisión que tu sistema emitió para el traslado de esa venta.

{ "documento_id": 9001, "numero": "001-001-0000009", "cdc": "0180…", "estado": "APPROVED" }
  • documento_id: el de la remisión en tu sistema (único); el de la URL es el de la factura.
  • Queda registrada en el pedido de esa venta y no mueve stock (la mercadería ya salió con la factura).
  • Reintentar con el mismo documento_id no la duplica: responde 200 con "existed": true.

9. Cobros de ventas a crédito (permiso cobros)

Registrar un cobro

POST https://tutienda.maxtiendas.app/api/v2/admin/external-billing/sales/{documento_id}/payments
{ "recibo_id": 9001, "numero": "REC-0045", "importe": 100000, "fecha": "2026-10-15", "forma_pago": 1 }
  • recibo_id: identificador único del recibo en tu sistema. Reintentar con el mismo no lo duplica.
  • Se reparte solo entre las cuotas pendientes del pedido.
  • Anular: POST /sales/{documento_id}/payments/{recibo_id}/cancel.

10. Dar de baja la llave

DELETE /token — tu sistema elimina su propia llave (por ejemplo, al desinstalar la integración). El comerciante también puede desconectarla desde su panel cuando quiera.


11. Flujo recomendado

  1. Al instalar: GET /me (moneda, si lleva stock). Traé todo el catálogo y los clientes paginando.
  2. Cada noche (o cada hora): GET /products?updated_since=<última sincronización> y lo mismo con clientes.
  3. Al facturar: buscá con ?q=; antes de emitir, GET /stock de las líneas para no vender lo que no hay.
  4. Al emitir: POST /sales. Si falla la red, reintentá con el mismo documento_id.
  5. Cuando responde la SET: POST /sales/{id}/status; si la rechaza, POST /sales/{id}/cancel.
  6. Anulaciones, notas, remisiones y cobros: las rutas de las secciones 7 a 9.

12. Probar con curl

BASE="https://mitienda.maxtiendas.app/api/v2/admin/external-billing"
KEY="57|kH3n..."

curl -s "$BASE/me" -H "Authorization: Bearer $KEY" -H "Accept: application/json"

curl -s "$BASE/products?per_page=5" -H "Authorization: Bearer $KEY" -H "Accept: application/json"

curl -s -X POST "$BASE/sales" \
  -H "Authorization: Bearer $KEY" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{"documento_id":1,"total":150000,"items":[{"product_id":1,"descripcion":"Prueba","cantidad":1,"precio_unitario":150000}]}'

⚠️ La última llamada registra una venta de verdad y baja el stock. Para probar, usá una tienda de prueba, o anulala después con POST /sales/1/cancel.