Skip to main content

Qué podés hacer

La API de La Pyme te permite leer datos operativos, crear operaciones comerciales y consultar reportes sin acceder directo a la base de datos. Los casos principales son:
  • Consultar clientes, proveedores, productos, depósitos, listas de precios, etiquetas y métodos de pago.
  • Crear y sincronizar presupuestos en borrador con importes y reservas canónicas.
  • Registrar compras, ventas, transferencias y movimientos manuales de stock.
  • Facturar ventas que ya fueron importadas desde Tiendanube y editar pedidos creados en La Pyme.
  • Aplicar ajustes masivos de costos o precios.
  • Consultar reportes agrupados de ventas, compras, pagos e inventario.

Primer request

Usá un endpoint de lectura chico para validar credenciales, scopes y formato de respuesta:
Las solicitudes a la API aceptan Authorization: Bearer ... con API keys o tokens OAuth delegados emitidos para clientes públicos.
La cuota de la API pública es por organización: 5000 solicitudes por hora y 120 solicitudes por minuto entre todas las credenciales de esa organización.

Convenciones

  • Las respuestas usan request_id para trazabilidad y el status HTTP como señal de éxito o error.
  • Los errores usan un envelope estructurado con type, code, message, retryable y details.
  • Los objetos de recursos incluyen object como discriminador de solo lectura, por ejemplo "object": "customer".
  • Los listados devuelven has_more y next_cursor. Usá ese valor como cursor para pedir la siguiente página.
  • Las escrituras usan payloads de negocio planos: sin mode, sin input, sin client y sin meta.
  • Las escrituras que pueden crear duplicados aceptan una clave de reintento en el header Idempotency-Key. Cada endpoint indica si es obligatoria u opcional.
  • Todos los importes monetarios se envían y devuelven en centavos.

Paginación

Los listados devuelven un token para pedir la siguiente página:
  • Enviá limit para controlar el tamaño de página. El máximo es 100 y el default es 50.
  • Si has_more es true, copiá next_cursor y envialo como cursor en la siguiente request.
  • No mezcles un cursor con filtros distintos. Cuando cambian filtros o búsqueda, empezá sin cursor.
  • page no está soportado.
  • Los resultados se ordenan de forma estable por el criterio del endpoint. Si necesitás reconstruir un export grande, guardá el último next_cursor procesado.

Etiquetas asignadas

Los listados y detalles de clientes, proveedores, productos, ventas, compras, órdenes de compra y transferencias de stock incluyen tags. El campo siempre es un array en la respuesta default. Cuando el recurso no tiene etiquetas, devuelve "tags": []. Cada entrada usa el mismo recurso que devuelve GET /api/v1/tags. Las etiquetas archivadas siguen apareciendo mientras permanezcan asignadas, con archived_at no nulo, aunque ya no estén disponibles para nuevas asignaciones. Las etiquetas se ordenan por nombre.
En productos, la asignación pertenece al producto y se refleja en todas sus variantes vendibles. En ventas, tags forma parte de los campos default. Si enviás un fields explícito, agregá tags para incluirlo. Por ejemplo, fields=id,tags.

Idempotencia

Las escrituras que pueden crear duplicados requieren o aceptan Idempotency-Key.
  • Obligatoria: POST /api/v1/purchases, POST /api/v1/sales, POST /api/v1/quotes, PUT /api/v1/quotes/{quote_id}, DELETE /api/v1/quotes/{quote_id}, POST /api/v1/delivery-notes, POST /api/v1/products, POST /api/v1/products/bulk-adjustments, POST /api/v1/stock-movements, POST /api/v1/purchase-orders y POST /api/v1/purchase-orders/{purchase_order_id}/receipts.
  • Opcional: POST /api/v1/stock-transfers.
  • Reutilizá la misma key solo para reintentar la misma operación con el mismo payload.
  • Si reutilizás una key con otro payload, la API responde 409 IDEMPOTENCY_CONFLICT.
  • Cuando una respuesta exitosa viene de un replay, el cuerpo incluye idempotent_replay: true dentro del recurso de resultado cuando aplica.
  • Para timeouts de red o respuestas 5xx, reintentá con la misma key. Para errores 4xx, corregí el payload antes de enviar una key nueva.

Respuesta de lectura

Respuesta de error

Cada ítem de error.details puede incluir:
  • field: path lógico del campo o header relacionado.
  • code: código estable para ese detalle.
  • message: explicación legible para mostrar o registrar.

Documentos de ventas y compras

Los detalles de ventas y compras informan la disponibilidad del documento sin incluir bytes base64, rutas de Storage ni URLs firmadas durables:
  • En ventas, el descriptor está en document.file y puede tener estado ready, pending, failed o missing.
  • En compras, el descriptor está en document y usa ready o missing.
  • Solo ready incluye una url. Esa ruta es estable, requiere sales:read o purchases:read y responde 302 hacia una URL firmada de cinco minutos. Configurá el cliente para seguir redirects.
  • pdf_path en compras se conserva deprecado por compatibilidad de V1. No lo uses para descargar. Migrá a document.url.
La document.url autenticada es el contrato para integraciones. El destino firmado del redirect es efímero y no debe guardarse. Los links públicos opacos /comprobantes/d/{token} enviados por email son credenciales de portador separadas, y la ruta pública histórica usada por WhatsApp no forma parte del contrato de la API.

Flujo de creación de compra

  1. Buscá el proveedor con GET /api/v1/suppliers.
  2. Buscá productos con GET /api/v1/products.
  3. Si enviás products_received: true, obtené el depósito con GET /api/v1/warehouses.
  4. Enviá POST /api/v1/purchases con el payload plano y un Idempotency-Key.
  5. Si la compra se crea, revisá normalized_purchase, projected_effects y warnings en la respuesta.
  6. Obtené la compra creada con GET /api/v1/purchases/{purchase_id}.

Ventas importadas y pedidos de La Pyme

Una venta importada desde Tiendanube o Mercado Libre ya existe en La Pyme como una sale. No la crees de nuevo y no uses las rutas de orders para facturarla. Obtené su ID con GET /api/v1/sales y facturá el mismo registro:
POST /api/v1/sales/{sale_id}/invoice nunca crea otra venta. Una respuesta 200 usa status: "issued". Una respuesta 202 usa status: "deferred": la venta todavía no fue facturada. Consultá su estado antes de volver a intentar. Si la venta ya estaba facturada y la key no es un replay, la API responde 409. Los rechazos finales o la configuración fiscal faltante responden 422 BUSINESS_REQUIREMENT_UNMET. Los pedidos creados dentro de La Pyme son recursos order. Para cambiar solo notes, PATCH /api/v1/orders/{order_id} conserva el contrato histórico sin Idempotency-Key. Para una edición estructural, enviá la representación completa de las líneas, assigned_warehouse_id, una Idempotency-Key y, cuando necesites evitar una escritura obsoleta, el valor updated_at que devuelve GET /api/v1/orders/{order_id} como expected_updated_at. La capability compartida conserva cantidades ya facturadas o preparadas y ajusta las reservas de stock en la misma transacción. Si cambiás assigned_warehouse_id o delivery_method, el trabajo pendiente y sus reservas se trasladan al nuevo destino en esa misma operación. En líneas existentes, unit_price usa el importe neto que devuelve el GET, incluso cuando el pedido incluye impuestos en los precios. Los campos opcionales omitidos conservan su valor actual. Enviá 0 o una cadena vacía cuando quieras quitar un descuento global o las notas.

Remitos

El recurso público canónico es delivery_note. Las integraciones nuevas deben usar estas rutas:
  • GET /api/v1/delivery-notes
  • POST /api/v1/delivery-notes
  • GET /api/v1/delivery-notes/{delivery_note_id}
Para crear un remito asociado a una venta existente, enviá solo el origen y los datos logísticos opcionales. La API toma el cliente, punto de venta, artículos, cantidades, productos y depósitos desde la venta. No envíes reemplazos para esos datos:
Para un remito independiente, usá origin.type: "custom" y enviá el cliente, el punto de venta y al menos un artículo. Un artículo de catálogo usa product_id. Un artículo libre usa is_custom: true y name:
Cada venta admite un solo remito. Repetir la misma key con el mismo request devuelve el recurso existente con idempotent_replay: true. Reutilizar la key con otro request responde 409 IDEMPOTENCY_CONFLICT. Usar otra key para una venta que ya tiene remito responde 409 STATE_CONFLICT. Si el remito de un replay fue eliminado después de su creación, repetir esa key también responde 409 STATE_CONFLICT. La key no crea un remito nuevo.

Flujo de creación de venta

Todas las ventas calculan los importes una sola vez y usan el mismo resultado canónico para la venta, el stock, la contabilidad y la fiscalización. En integraciones nuevas, enviá Lapyme-Version: 2026-08-20 para usar el contrato estricto con validación del total esperado.
  • En comprobantes A (voucher_type 1, 2 y 3), unit_price es el importe neto sin IVA.
  • En comprobantes a consumidor final, incluidos B (voucher_type 6, 7 y 8) y presupuesto (voucher_type 90), unit_price es el importe final con IVA incluido.
  • total es el total final esperado y es obligatorio.
  • Cuando enviás product_id, La Pyme resuelve el producto y aplica sus efectos. No necesitás otra lectura para calcular importes derivados.
  • No envíes subtotal, tax_amount, exempt_amount, non_taxed_amount, tributes_amount, discount_amount, tax_included_override ni rounding_adjustment. El contrato fechado también rechaza campos desconocidos.
Para FCE A/B/C (voucher_type 201, 206 o 211), enviá también transfer_type con la opción que seleccionó el usuario (SCA o ADC) y due_date igual o posterior a invoice_date y a la fecha actual en Argentina. No hay una opción de transferencia predeterminada. La organización necesita un CBU válido; el cliente, la condición fiscal y el importe deben ser elegibles. Los datos faltantes o inválidos se rechazan antes de crear la venta o enviar el trabajo a ARCA. Los comprobantes comunes no requieren estos campos. Este fragmento muestra los campos fiscales de una FCE A; completá el cliente, el punto de venta, los renglones y el total como en el ejemplo anterior:
En el SDK y MCP save_sale, usá transferType y dueDate. El SDK se genera desde este OpenAPI. Cambiar la opción de transferencia con la misma Idempotency-Key responde 409 IDEMPOTENCY_CONFLICT; usá una nueva key solo para una venta nueva. save_sale con id solo modifica metadatos y etiquetas. Si total no coincide con el cálculo canónico, la API responde antes de crear la venta o cualquier efecto durable:
Omitir Lapyme-Version conserva los campos del contrato histórico, el total opcional y la configuración de precios con IVA de la organización. Este modo también calcula el IVA una sola vez y devuelve el header Deprecation. No necesitás agregar el header para recibir esta corrección. Usá el contrato fechado en integraciones nuevas. Los reintentos conservan la venta ya creada; no recalculan sus importes persistidos. Si el contrato histórico descartó transfer_type al aceptar una venta, el reintento con la misma key y el mismo cuerpo conserva ese resultado. La opción no se aplica a esa venta existente. Las ventas nuevas validan y guardan el campo. Idempotency-Key solo deduplica reintentos. Si querés guardar el ID de tu sistema en la venta, enviá integration_source e integration_id en el cuerpo.
POST /api/v1/stock-transfers también usa un payload de negocio plano. Idempotency-Key es opcional: cuando se envía, el servidor puede deduplicar reintentos. Cuando se omite, la operación sigue siendo válida pero no tiene protección automática contra repeticiones.Cada ítem puede usar el ID de una variante de combo con una cantidad entera. La respuesta y las lecturas posteriores muestran las líneas canónicas de sus componentes, con las cantidades ya multiplicadas y agregadas. No se guarda ni se mueve stock para la variante del combo.

Flujo de aumento de costos por proveedor

  1. Buscá el proveedor con GET /api/v1/suppliers.
  2. Revisá los productos afectados con GET /api/v1/products.
  3. Enviá POST /api/v1/products/bulk-adjustments con target: "cost", el filtro default_supplier_id y un Idempotency-Key.
  4. La capability de comercio actualiza costos, recalcula precios base cuando un producto usa pricing automático por margen y registra efectos de sincronización para canales conectados.

Endpoints disponibles

Contactos

  • GET /api/v1/customers
  • GET /api/v1/customers/metafield-definitions
  • POST /api/v1/customers
  • GET /api/v1/customers/{customer_id}
  • PUT /api/v1/customers/{customer_id}
  • GET /api/v1/suppliers
  • POST /api/v1/suppliers
  • GET /api/v1/suppliers/{supplier_id}
  • PUT /api/v1/suppliers/{supplier_id}

Productos y configuración

  • GET /api/v1/products
  • POST /api/v1/products
  • GET /api/v1/products/metafield-definitions
  • GET /api/v1/products/{product_id}
  • PUT /api/v1/products/{product_id}
  • PATCH /api/v1/products/{product_id}/metafields
  • POST /api/v1/products/bulk-adjustments
  • GET /api/v1/categories
  • POST /api/v1/categories
  • GET /api/v1/categories/{category_id}
  • PUT /api/v1/categories/{category_id}
  • GET /api/v1/price-lists
  • POST /api/v1/price-lists
  • GET /api/v1/price-lists/{price_list_id}
  • PUT /api/v1/price-lists/{price_list_id}
  • GET /api/v1/price-lists/{price_list_id}/prices
  • PUT /api/v1/price-lists/{price_list_id}/prices
  • GET /api/v1/price-lists/{price_list_id}/prices/{product_id}
Para guardar precios de productos, usá PUT /api/v1/price-lists/{price_list_id}/prices con Idempotency-Key y un cuerpo como este:
price es un importe entero en centavos, desde cero. Las reglas son base_adjustment o cost_markup; deben coincidir con el modo de la lista automática. El margen sobre costo no puede ser negativo. Para pasar de un precio fijo a un porcentaje, quitá primero la entrada con otra solicitud. Cada producto puede aparecer una sola vez en la solicitud, entre altas y bajas. Hay un máximo de 500 entradas y 500 bajas. Los productos omitidos conservan sus entradas. La operación es atómica y devuelve updated, removed e idempotent_replay. Las bajas cuentan los productos solicitados, aunque no tuvieran entrada. En MCP, save_price_list con id y entries o removeEntries guarda estas entradas. Cada entrada de MCP usa product (UUID de variante, SKU o nombre). Los UUID no requieren una lectura adicional de productos; se resuelven como máximo 100 referencias sin UUID por llamada. Usá llamadas separadas para configurar la lista y para sus precios. Creá primero la lista si todavía no tiene un id. Leé el resultado efectivo con list_price_list_prices. Para exportar una lista, leé sus precios resueltos y unilos con productos por product_id. Cada unit_price es un entero en centavos ARS, con la base impositiva, la alícuota y la procedencia del cálculo. La respuesta no repite nombre, SKU, stock ni costo. Si omitís is_active, el listado incluye variantes activas e inactivas. Usalo para elegir un estado exacto cuando lo necesites. La paginación está ligada a pricing_revision. Si recibís PRICE_LIST_PRICES_CHANGED, reiniciala sin cursor. Guardá el ETag débil de la primera página o del detalle y envialo con If-None-Match. Una respuesta 304 no tiene cuerpo. El estado unavailable indica que falta un insumo de precio y no inventa un valor base. Este recurso devuelve el precio unitario base efectivo. No es una cotización por cliente, cantidad, fecha, promoción o envío. Las reglas configurables y las cotizaciones transaccionales son recursos separados. Los campos personalizados de productos están incluidos en todos los planes de la oferta actual. Algunas organizaciones con contratos anteriores conservan condiciones distintas. Descubrí primero las claves y validaciones con GET /api/v1/products/metafield-definitions, envialos al crear mediante metafields: [{ "key": "MARCA", "value": "vicus" }] y leelos en el detalle como [{ "key": "marca", "value": "Vicus" }]. Los valores son del grupo y se comparten entre variantes. El listado no los incluye. Para cambios posteriores, PATCH /api/v1/products/{product_id}/metafields usa entries: un string asigna y null borra. No uses string vacío. PUT /api/v1/products/{product_id} rechaza metafields. Las etiquetas se administran por su endpoint separado.

Compras y ventas

  • GET /api/v1/purchases
  • GET /api/v1/purchases/{purchase_id}
  • GET /api/v1/purchases/{purchase_id}/document
  • POST /api/v1/purchases
  • GET /api/v1/sales
  • POST /api/v1/sales
  • GET /api/v1/sales/{sale_id}
  • GET /api/v1/sales/{sale_id}/document
  • GET /api/v1/delivery-notes
  • POST /api/v1/delivery-notes
  • GET /api/v1/delivery-notes/{delivery_note_id}
  • GET /api/v1/purchase-orders
  • POST /api/v1/purchase-orders
  • GET /api/v1/purchase-orders/{purchase_order_id}
  • POST /api/v1/purchase-orders/{purchase_order_id}/confirm
  • POST /api/v1/purchase-orders/{purchase_order_id}/close
  • POST /api/v1/purchase-orders/{purchase_order_id}/reopen
  • POST /api/v1/purchase-orders/{purchase_order_id}/receipts

Inventario y ubicaciones

  • GET /api/v1/inventory
  • GET /api/v1/inventory/movements
  • POST /api/v1/stock-movements
  • GET /api/v1/stock-transfers
  • POST /api/v1/stock-transfers
  • GET /api/v1/stock-transfers/{transfer_id}
  • GET /api/v1/warehouses
  • POST /api/v1/warehouses
  • GET /api/v1/warehouses/{warehouse_id}
  • PUT /api/v1/warehouses/{warehouse_id}

Etiquetas, cobranzas, medios de pago y reportes

  • GET /api/v1/tags
  • POST /api/v1/tags
  • PATCH /api/v1/tags/{tag_id}
  • POST /api/v1/customers/tags/apply
  • POST /api/v1/suppliers/tags/apply
  • POST /api/v1/products/tags/apply
  • POST /api/v1/sales/tags/apply
  • GET /api/v1/customer-payments
  • POST /api/v1/customer-payments
  • GET /api/v1/customer-payments/{payment_id}
  • POST /api/v1/customer-payments/{payment_id}/void
  • GET /api/v1/supplier-payments
  • POST /api/v1/supplier-payments
  • GET /api/v1/supplier-payments/{payment_id}
  • POST /api/v1/supplier-payments/{payment_id}/void
  • GET /api/v1/payment-methods
  • POST /api/v1/payment-methods
  • GET /api/v1/payment-methods/{payment_method_id}
  • PUT /api/v1/payment-methods/{payment_method_id}
  • GET /api/v1/points-of-sale
  • POST /api/v1/reports/query - ver Reportes

Ejemplo de creación de producto con variantes

Para crear variantes, enviá options con entre uno y tres nombres y variants con las combinaciones vendibles. Cada variante debe incluir exactamente un valor para cada opción declarada. Los SKU y las combinaciones no pueden repetirse. El límite es de 250 variantes por request. Los importes están expresados en centavos.
Para cargar stock inicial, agregá warehouse_stocks dentro de cada variante. Reutilizá la misma Idempotency-Key solamente para reintentar el mismo producto y la misma matriz.

Ejemplo de creación de compra

Ejemplo de aumento masivo de costos

Scopes requeridos

  • customers:read
  • customers:write
  • categories:read
  • categories:write
  • suppliers:read
  • suppliers:write
  • products:read
  • products:write
  • warehouses:read
  • warehouses:write
  • purchases:read
  • purchases:write
  • sales:read
  • sales:write
  • transfers:read
  • transfers:write
  • price_lists:read
  • price_lists:write
  • payment_methods:read
  • payment_methods:write
  • reports:read
Cada endpoint está documentado en detalle en la referencia OpenAPI de esta sección.

Campos personalizados de clientes

Desde el 9 de octubre de 2026, GET /api/v1/customers/metafield-definitions permite descubrir las definiciones de contacto no sistémicas de tu empresa. Usa customers:read; customers:write y admin también lo permiten. La respuesta es una lista con object: "list", url, data, has_more y next_cursor. Las definiciones se ordenan por key e id ascendentes e incluyen object: "metafield_definition", id (UUID), key, name, description (puede ser null), field_type y validations. limit vale 50 por defecto y admite entre 1 y 100. Cuando has_more sea true, enviá el next_cursor opaco como cursor para obtener la próxima página. No uses page ni offsets. Recorré todas las páginas para descubrir los campos obligatorios antes de crear clientes; un cursor o límite inválido devuelve 400 INVALID_REQUEST. Las validaciones incluyen required, min_length y max_length para texto, min y max para números y options para select. Los campos booleanos aceptan "true" o "false"; las fechas usan YYYY-MM-DD. La respuesta no incluye valores de clientes ni cantidades. Los campos obligatorios deben completarse al crear un cliente. Primero consultá las definiciones. Después enviá sus IDs y valores con el contrato existente de creación o actualización:
El GET no requiere Idempotency-Key. El POST y el PUT conservan sus requisitos de autenticación e idempotencia. Las definiciones y los valores de otra empresa siguen rechazados por el alcance del recurso.

Documentos de clientes repetidos

Desde el 9 de octubre de 2026, POST /api/v1/customers rechaza un DNI o CUIT que ya pertenece a un cliente de la misma empresa, aunque esté archivado. Devuelve 409 CONFLICT con «Ya existe un cliente con ese documento». La API y MCP no admiten la excepción administrativa de la pantalla Clientes. Consultá el cliente existente y usá su ID; no reintentes la creación con otra Idempotency-Key. Repetir una creación ya confirmada con su misma clave conserva la respuesta original. El detalle de un cliente y las respuestas de creación y actualización devuelven también arca_destination_country, foreign_tax_id y arca_country_tax_id. Son los mismos campos que aceptan las escrituras de un foreign_customer, para consultar y conservar su identidad fiscal. Al crear un foreign_customer, enviá también country con el nombre del país de destino. Para cambiar arca_destination_country, enviá el nuevo country en la misma actualización; omitirlo devuelve una validación y conserva los datos anteriores. Los demás cambios parciales conservan la identidad omitida. Los datos de identidad del exterior tienen la misma protección contra edición durante un intento fiscal activo que el nombre y el documento del cliente. La identidad predeterminada de Consumidor Final (tipo 99, número 0) y los proveedores están exceptuados. Las importaciones conservan su comportamiento de vinculación.